aboutsummaryrefslogtreecommitdiff
path: root/files/fr/mdn/tools/kumascript/index.html
blob: 9ded41a11a8da2ac00111a3d0be5c96f0fb80f2c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
---
title: KumaScript
slug: MDN/Tools/KumaScript
tags:
  - Guide
  - Kuma
  - KumaScript
  - MDN
  - MDN Meta
translation_of: MDN/Tools/KumaScript
---
<div>{{MDNSidebar}}</div>

<div></div>

<p><span class="seoSummary">Sur la plate-forme <a href="/en-US/docs/MDN/Kuma">Kuma</a> qui propulse MDN, le système de modèles pour automatiser certains aspects du contenu sur le wiki est appelé <a class="link-https" href="https://github.com/mozilla/kumascript" title="https://github.com/mozilla/kumascript">KumaScript</a>. KumaScript repose sur du JavaScript côté serveur implanté à l'aide de <a class="external" href="http://nodejs.org/" title="http://nodejs.org/">Node.js</a>.</span> Cet article vous fournit des informations basiques sur l'utilisation de KumaScript.</p>

<p>Pour un aperçu détaillé et des questions et réponses sur KumaScript, visitez la <a href="https://vreplay.mozilla.com/replay/showRecordDetails.html?sortBy=date&amp;viewCount=1&amp;currentPage=1&amp;groupBy=combo&amp;roomFilter=&amp;usernameFilter=&amp;searchFilter=&amp;usernameFullFilter=&amp;myManager=-1&amp;adminManager=0&amp;webCast=0&amp;command=&amp;recId=1082&amp;auxMessage=&amp;auxMessage1=&amp;lang=en&amp;langChanged=&amp;tenantFilter=&amp;securityTab=">discussion Fireside KumaScript</a> de l'équipe de développement de MDN. KumaScript a remplacé DekiScript, qui était le langage modèle pour MindTouch, la précédente plate-forme utilisée par MDN.</p>

<h3 id="Quest_KumaScript">Qu'est KumaScript ?</h3>

<ul>
 <li>Un moyen de réutiliser et de localiser du contenu qui apparaît répétitivement sur plusieurs documents (par exemple les tableaux de compatibilité, les sections de navigations, les bannières d'avertissement, etc.)</li>
 <li>Un moyen de construire des documents à partir de contenu tiré d'autres documents.</li>
 <li>Un moyen de rechercher et d'inclure du contenu d'autres sites web et services (par exemple Bugzilla).</li>
</ul>

<h3 id="Ce_que_KumaScript_nest_pas">Ce que KumaScript n'est pas</h3>

<ul>
 <li>KumaScript ne supporte pas le scriptage interactif du même genre que celui que peuvent accepter les soumissions de formulaires.</li>
 <li>KumaScript n'a pas accès à une base de données, à des fichiers, ou à tout autre moyen de stocker de l'information de manière persistente.</li>
 <li>KumaScript ne supporte pas la personnalisation de site en fonction de l'utilisateur couramment connecté.</li>
 <li>KumaScript n'a pas accès aux informations de l'utilisateur, seulement au contenu et aux métadonnées de la page en train d'être visitée.</li>
</ul>

<h2 id="Les_bases">Les bases</h2>

<p>KumaScript fonctionne en permettant aux <a href="/en-US/docs/MDN/Community/Roles">utilisateurs MDN de confiance</a> d'écrire des <a class="link-https" href="https://github.com/visionmedia/ejs" title="https://github.com/visionmedia/ejs">modèles JavaScript embarqués</a>. Ces modèles peuvent être invoqués dans le contenu du document par tout auteur MDN via l'usage de macros.</p>

<p>Un script en KumaScript est un <em>modèle</em>, et chaque modèle est un fichier du dépôt Github. Un <a class="link-https" href="/en-US/docs/Template:hello" title="/en-US/docs/Template:hello">modèle</a> ressemble à ceci :</p>

<pre class="notranslate">&lt;% for (var i = 0; i &lt; $0; i++) { %&gt;
Hello #&lt;%= i %&gt;
&lt;% } %&gt;</pre>

<p>Invoquer un modèle se fait avec un <em>macro</em>, pouvant être utilisé à tout endroit dans toute page wiki. Un <a class="link-https" href="/en-US/docs/KumaTests/hello_test?raw=1" title="/en-US/docs/KumaTests/hello_test?raw=1">macro</a> ressemble à ceci :</p>

<pre class="notranslate">\{{ hello("3") }}</pre>

<p>La <a class="link-https" href="/en-US/docs/KumaTests/hello_test" title="/en-US/docs/KumaTests/hello_test">sortie du macro</a> ressemble à :</p>

<pre class="notranslate">Hello #0
Hello #1
Hello #2</pre>

<h3 id="Syntaxe_des_macro">Syntaxe des macro</h3>

<p>Les modèles KumaScript sont invoqués dans le contenu d'un document avec des macros comme ceci :</p>

<pre class="notranslate">\{{ templateName("arg0", "arg1", ..., "argN") }}
</pre>

<p>La syntaxe des macros consiste en quatre règles :</p>

<ul>
 <li>Les macros commencent avec <code>\\{{</code> et se terminent avec <code>}}</code>.</li>
 <li>La première partie du macro est le nom du modèle invoqué. La valeur en bas-de-casse de ce nom doit correspondre à un nom de fichier en bas-de-casse sur le dépôt des macros de KumaScript.</li>
 <li>Un modèle peut accepter des paramètres, et cette lsite de paramètres débute te se termine avec des parenthèses.</li>
 <li>Tout les paramètres non numériques doivent être exprimés entre guillemets. Seuls les guillemets peuvent être exprimés sans guillemets.</li>
</ul>

<h4 id="Utiliser_JSON_comme_paramètre_de_macro">Utiliser JSON comme paramètre de macro</h4>

<p>En tant que fonctionnalité semi-expérimentale (il n'est pas garantie qu'elle fonctionne), vous pouvez fournir un objet JSON pour le premier paramètre uniquement, par exemple :</p>

<pre class="notranslate">\\{{ templateName({ "Alpha":"one", "Beta":["a","b","c"], "Foo":"http:\/\/mozilla.org\/" }) }}
</pre>

<p>Les données de ce macro sont disponibles dans le code du modèle en tant qu'objet à l'argument <code>$0</code> (par exemple <code>$0.Alpha</code>, <code>$0.Beta</code>, <code>$0.Foo</code>). Celà vous permet aussi d'exprimer des structures de données complexes dans les paramètres des macros qu'il serait difficile voire impossible d'exprimer comme une simple liste de paramètres.</p>

<p>Notee que ce style de paramètre est très strict — il doit correspondre exactement à la <a href="http://json.org/" title="http://json.org/">syntaxe JSON</a>, qui a quelques contraintes sur l'échappement des caractères qu'il est aisé d'oublier (par exemple que toutes les barres obliques culbutées doivent être échapées). Si vous avez un doute, <a href="http://jsonlint.com/" title="http://jsonlint.com/">essayer de faire passer votre JSON dans un validateur</a>.</p>

<h4 id="Comment_écrire_dans_du_texte">Comment écrire "\\{{" dans du texte</h4>

<p>Bien que la séquence de caractères "<code>\\{{</code>" soit utilisée pour démarrer un macro, elle peut causer des problèmes si vous voulez seulement écrire "<code>\\{{</code>" et "<code>}}</code>" sur une page. Celà produira alors probablement des messages <code>DocumentParsingError</code>.</p>

<p>Dans ce cas, vous pouvez échapper la barre oblique culbutée avec une seconde barre, tel que : <code>\\\{{</code></p>

<h3 id="Syntaxe_des_modèles">Syntaxe des modèles</h3>

<p>Each KumaScript template is kept in a separate wiki page. Creating and editing these pages requires an elevated privilege, which MDN admins can grant to trusted editors.</p>

<p>KumaScript templates are processed by an <a class="link-https" href="https://github.com/visionmedia/ejs" title="https://github.com/visionmedia/ejs">embedded JavaScript template engine</a> with a few simple rules:</p>

<ul>
 <li>Within a template, the parameters passed in from the macro are available as the variables <code>$0</code>, <code>$1</code>, <code>$2</code>, and so on. The entire list of parameters is also available in a template as the variable <code>arguments</code>.</li>
 <li>Most text is treated as output and included in the output stream.</li>
 <li>JavaScript variables and expressions can be inserted into the output stream with these blocks:
  <ul>
   <li><code>&lt;%= expr %&gt;</code>  the value of a JavaScript expression is escaped for HTML before being included in output (e.g., characters like <code>&lt;</code> and <code>&gt;</code> are turned into <code>&amp;lt;</code> and <code>&amp;gt;</code>).</li>
   <li><code>&lt;%- expr %&gt;</code>  the value of a JavaScript expression is included in output without any escaping. (Use this if you want to dynamically build markup or use the results of another template that may include markup.)</li>
   <li>It is an error to include semicolons inside these blocks.</li>
  </ul>
 </li>
 <li>Anything inside a <code>&lt;% %&gt;</code> block is interpreted as JavaScript. This can include loops, conditionals, etc.</li>
 <li>Nothing inside a <code>&lt;% %&gt;</code> block can ever contribute to the output stream. But, you can transition from JS mode to output mode using <code>&lt;% %&gt;</code>for example:
  <pre class="notranslate">&lt;% for (var i = 0; i &lt; $0; i++) { %&gt;
Hello #&lt;%= i %&gt;
&lt;% } %&gt;
</pre>

  <p>Note how the JavaScript code is contained in <code>&lt;% ... %&gt;</code>, and output happens in the space between <code>%&gt; ... &lt;%</code>. The <code>for</code> loop in JS can begin with one <code>&lt;% %&gt;</code> block, transition to output mode, and finish up in a second <code>&lt;% %&gt;</code> JS block.</p>
 </li>
 <li>For more details on EJS syntax, <a class="link-https" href="https://github.com/visionmedia/ejs" title="https://github.com/visionmedia/ejs">check out the upstream module documentation</a>.</li>
</ul>

<h3 id="Tips">Tips</h3>

<h4 id="Dates_and_times">Dates and times</h4>

<p>It's important to note that the standard JavaScript {{jsxref("Date")}} constructor is overridden by the KumaScript <code>Date</code> interface. You can create a JavaScript <code>Date</code> by calling the KumaScript <code>date.now()</code> or <code>date.parse()</code> function.</p>

<h2 id="Fonctionnalités_avancées">Fonctionnalités avancées</h2>

<p>Beyond the basics, the KumaScript system offers some advanced features.</p>

<h3 id="Variables_denvironnement">Variables d'environnement</h3>

<p>When the wiki makes a call to the KumaScript service, <a class="link-https" href="https://github.com/mozilla/kuma/blob/master/apps/wiki/kumascript.py#L130" title="https://github.com/mozilla/kuma/blob/master/apps/wiki/views.py#L537">it passes along some context on the current document</a> that KumaScript makes available to templates as variables:</p>

<dl>
 <dt><code>env.path</code></dt>
 <dd>The path to the current wiki document</dd>
 <dt><code>env.url</code></dt>
 <dd>The full URL to the current wiki document</dd>
 <dt><code>env.id</code></dt>
 <dd>A short, unique ID for the current wiki document</dd>
 <dt><code>env.files</code></dt>
 <dd>An array of the files attached to the current wiki document; each object in the array is as described under {{ anch("File objects") }} below</dd>
 <dt><code>env.review_tags</code></dt>
 <dd>An array of the review tags on the article ("technical", "editorial", etc.)</dd>
 <dt><code>env.locale</code></dt>
 <dd>The locale of the current wiki document</dd>
 <dt><code>env.title</code></dt>
 <dd>The title of the current wiki document</dd>
 <dt><code>env.slug</code></dt>
 <dd>The URL slug of the current wiki document</dd>
 <dt><code>env.tags</code></dt>
 <dd>An array list of tag names for the current wiki document</dd>
 <dt><code>env.modified</code></dt>
 <dd>Last modified timestamp for the current wiki document</dd>
 <dt><code>env.cache_control</code></dt>
 <dd><code>Cache-Control</code> header sent in the request for the current wiki document, useful in deciding whether to invalidate caches</dd>
</dl>

<h4 id="File_objects">File objects</h4>

<p>Each file object has the following fields:</p>

<dl>
 <dt><code>title</code></dt>
 <dd>The attachment's title</dd>
 <dt><code>description</code></dt>
 <dd>A textual description of the current revision of the file</dd>
 <dt><code>filename</code></dt>
 <dd>The file's name</dd>
 <dt><code>size</code></dt>
 <dd>The size of the file in bytes</dd>
 <dt><code>author</code></dt>
 <dd>The username of the person who uploaded the file</dd>
 <dt><code>mime</code></dt>
 <dd>The MIME type of the file</dd>
 <dt><code>url</code></dt>
 <dd>The URL at which the file can be found</dd>
</dl>

<h4 id="Working_with_tag_lists">Working with tag lists</h4>

<p>The <code>env.tags</code> and <code>env.review_tags</code> variables return arrays of tags. You can work with these in many ways, of course, but here are a couple of suggestions.</p>

<h5 id="Looking_to_see_if_a_specific_tag_is_set">Looking to see if a specific tag is set</h5>

<p>You can look to see if a specific tag exists on a page like this:</p>

<pre class="brush: js notranslate">if (env.tags.indexOf("tag") != −1) {
  // The page has the tag "tag"
}
</pre>

<h5 id="Iterating_over_all_the_tags_on_a_page">Iterating over all the tags on a page</h5>

<p>You can also iterate over all the tags on a page, like this:</p>

<pre class="brush: js notranslate">env.tag.forEach(function(tag) {
  // do whatever you need to do, such as:
  if (tag.indexOf("a") == 0) {
    // this tag starts with "a" - woohoo!
  }
});</pre>

<h3 id="APIs_and_Modules">APIs and Modules</h3>

<p>KumaScript offers some built-in utility APIs, as well as the ability to define new APIs in modules editable as wiki documents.</p>

<h4 id="Built-in_methods">Built-in methods</h4>

<p>This manually-maintained documentation is likely to fall out of date with the code. With that in mind, <a class="link-https" href="https://github.com/mozilla/kumascript/blob/master/lib/kumascript/api.js#L175" title="https://github.com/mozilla/kumascript/blob/master/lib/kumascript/api.js#L208">you can always check out the latest state of built-in APIs in the KumaScript source</a>. But here is a selection of useful methods exposed to templates:</p>

<dl>
 <dt><code>md5(string)</code></dt>
 <dd>Returns an MD5 hex digest of the given string.</dd>
 <dt><code>template("name", ["arg0", "arg1", ..., "argN"])</code></dt>
 <dd>Executes and returns the result of the named template with the given list of parameters.</dd>
 <dd>Example: <code>&lt;%- template("warning", ["foo", "bar", "baz"]) %&gt;</code>.</dd>
 <dd>Example using the <code>domxref</code> macro: <code>&lt;%- template("domxref", ["Event.bubbles", "bubbles"]) %&gt;</code>.</dd>
 <dd>This is a JavaScript function. So, if one of the parameters is an arg variable like $2, do not put it in quotes. Like this: <code>&lt;%- template("warning", [$1, $2, "baz"]) %&gt;</code>. If you need to call another template from within a block of code, do not use <code>&lt;%</code> ... <code>%&gt;</code>. Example: <code>myvar = "&lt;li&gt;" + template("LXRSearch", ["ident", "i", $1]) + "&lt;/li&gt;";</code></dd>
 <dt><code>require(name)</code></dt>
 <dd>Loads another template as a module; any output is ignored. Anything assigned to <code>module.exports</code> in the template is returned.</dd>
 <dd>Used in templates like so: <code>&lt;% var my_module = require('MyModule'); %&gt;</code>.</dd>
 <dt><code>cacheFn(key, timeout, function_to_cache)</code></dt>
 <dd>Using the given key and cache entry lifetime, cache the results of the given function. Honors the value of <code>env.cache_control</code> to invalidate cache on <code>no-cache</code>, which can be sent by a logged-in user hitting shift-refresh.</dd>
 <dt><code>request</code></dt>
 <dd>Access to <a class="link-https" href="https://github.com/mikeal/request" title="https://github.com/mikeal/request"><code>mikeal/request</code></a>, a library for making HTTP requests. Using this module in KumaScript templates is not yet very friendly, so you may want to wrap usage in module APIs that simplify things.</dd>
 <dt><code>log.debug(string)</code></dt>
 <dd>Outputs a debug message into the script log on the page (i.e. the big red box that usually displays errors).</dd>
</dl>

<h4 id="Built-in_API_modules">Built-in API modules</h4>

<p>There's only one API built in at the moment, in the <code>kuma</code> namespace. You can see the most up to date list of methods under <code>kuma</code> from <a href="https://github.com/mozilla/kumascript/blob/master/lib/kumascript/api.js#L74">the KumaScript source code</a>, but here are a few:</p>

<dl>
 <dt><code>kuma.inspect(object)</code></dt>
 <dd>Renders any JS object as a string, handy for use with <code>log.debug()</code>. See also: <a href="http://nodejs.org/api/util.html#util_util_inspect_object_options">node.js <code>util.inspect()</code></a>.</dd>
</dl>

<dl>
 <dt><code>kuma.htmlEscape(string)</code></dt>
 <dd>Escapes the characters <code>&amp;, &lt;, &gt;, "</code> to <code>&amp;amp, &amp;lt;, &amp;gt;, &amp;quot;</code>, respectively.</dd>
 <dt><code>kuma.url</code></dt>
 <dd>See also: <a href="http://nodejs.org/api/url.html">node.js <code>url</code> module</a>.</dd>
 <dt><code>kuma.fetchFeed(url)</code></dt>
 <dd>Fetch an RSS feed and parse it into a JS object. See also: <a href="https://developer.mozilla.org/en-US/docs/Template:InsertFeedLinkList"><code>Template:InsertFeedLinkList</code></a></dd>
</dl>

<h4 id="Creating_modules">Creating modules</h4>

<p>Using the built-in <code>require()</code> method, you can load a template as a module to share common variables and methods between templates. A module can be defined in a template like this:</p>

<pre class="notranslate">&lt;%
module.exports = {
    add: function (a, b) {
        return a + b;
    }
}
%&gt;
</pre>

<p>Assuming this template is saved as <code>/en-US/docs/Template:MathLib</code>, you can use it in another template like so:</p>

<pre class="notranslate">&lt;%
var math_lib = require("MathLib");
%&gt;
The result of 2 + 2 = &lt;%= math_lib.add(2, 2) %&gt;
</pre>

<p>And, the output of this template will be:</p>

<pre class="notranslate">The result of 2 + 2 = 4
</pre>

<h4 id="Auto-loaded_modules">Auto-loaded modules</h4>

<p>There are a set of modules editable as wiki templates that are automatically loaded and made available to every template. This set is defined in the configuration file for the KumaScript service - any changes to this requires an IT bug to edit configuration and a restart of the service.</p>

<p>For the most part, these attempt to provide stand-ins for legacy DekiScript features to ease template migration. But, going forward, these can be used to share common variables and methods between templates:</p>

<ul>
 <li><code>mdn.*</code> - <a class="link-https" href="/en-US/docs/Template:MDN:Common" title="/en-US/docs/Template:MDN:Common">Template:MDN:Common</a></li>
 <li><code>Date.*</code> - <a class="link-https" href="/en-US/docs/Template:DekiScript:Date" title="/en-US/docs/Template:DekiScript:Date">Template:DekiScript:Date</a></li>
 <li><code>Page.*</code> - <a class="link-https" href="/en-US/docs/Template:DekiScript:Page" title="/en-US/docs/Template:DekiScript:Page">Template:DekiScript:Page</a></li>
 <li><code>String.*</code> - <a class="link-https" href="/en-US/docs/Template:DekiScript:String" title="/en-US/docs/Template:DekiScript:String">Template:DekiScript:String</a></li>
 <li><code>Uri.*</code> - <a class="link-https" href="/en-US/docs/Template:DekiScript:Uri" title="/en-US/docs/Template:DekiScript:Uri">Template:DekiScript:Uri</a></li>
 <li><code>Web.*</code> - <a class="link-https" href="/en-US/docs/Template:DekiScript:Web" title="/en-US/docs/Template:DekiScript:Web">Template:DekiScript:Web</a></li>
 <li><code>Wiki.*</code> - <a class="link-https" href="/en-US/docs/Template:DekiScript:Wiki" title="/en-US/docs/Template:DekiScript:Wiki">Template:DekiScript:Wiki</a></li>
</ul>

<p><strong>Note:</strong> You might notice that the DekiScript modules use a built-in method named <code>buildAPI()</code>, like so:</p>

<pre class="notranslate">&lt;% module.exports = buildAPI({
    StartsWith: function (str, sub_str) {
        return (''+str).indexOf(sub_str) === 0;
    }
}); %&gt;
</pre>

<p>The reason for this is because DekiScript is case-insensitive when it comes to references to API methods, whereas JavaScript is strict about uppercase and lowercase in references. So, <code>buildAPI()</code> is a hack to try to cover common case variations in DekiScript calls found in legacy templates.</p>

<div class="note">
<p>With that in mind, please do not use <code>buildAPI()</code> in new modules.</p>
</div>

<h2 id="Tips_and_caveats">Tips and caveats</h2>

<h3 id="Debugging">Debugging</h3>

<p>A useful tip when debugging. You can use the <code>log.debug()</code> method to output text to the scripting messages area at the top of the page that's running your template. Note that you need to be really sure to remove these when you're done debugging, as they're visible to all users! To use it, just do something like this:</p>

<pre class="notranslate">&lt;%- log.debug("Some text goes here"); %&gt;
</pre>

<p>You can, of course, create more complex output using script code if it's helpful.</p>

<h3 id="Caching">Caching</h3>

<p>KumaScript templates are heavily cached to improve performance. For the most part, this works great to serve up content that doesn't change very often. But, as a logged-in user, you have two options to force a page to be regenerated, in case you notice issues with scripting:</p>

<ul>
 <li>Hit Refresh in your browser. This causes KumaScript to invalidate its cache for the content on the current page by issuing a request with a <code>Cache-Control: max-age=0</code> header.</li>
 <li>Hit Shift-Refresh in your browser. This causes KumaScript to invalidate cache for the current page, as well as for any templates or content used by the current page by issuing a request with a <code>Cache-Control: no-cache</code> header.</li>
</ul>

<h3 id="Using_search_keywords_to_open_template_pages">Using search keywords to open template pages</h3>

<p>When using templates, it's common to open the template's code in a browser window to review the comments at the top, which are used to document the template, its parameters, and how to use it properly. To quickly access templates, you can create a Firefox <a href="http://kb.mozillazine.org/Using_keyword_searches">search keyword</a>, which gives you a shortcut you can type in the URL box to get to a template more easily.</p>

<p>To create a search keyword, open the bookmarks window by choosing "Show all bookmarks" in the Bookmarks menu, or by pressing <kbd>Control</kbd>-<kbd>Shift</kbd>-<kbd>B</kbd> (<kbd>Command</kbd>-<kbd>Shift</kbd>-<kbd>B</kbd> on Mac). Then from the utility ("Gear") menu in the Library window that appears, choose "New Bookmark...".</p>

<p>This causes the bookmark editing dialog to appear. Fill that out as follows:</p>

<dl>
 <dt>Name</dt>
 <dd>A suitable name for your search keyword; "Open MDN Template" is a good one.</dd>
 <dt>Location</dt>
 <dd><kbd>https://developer.mozilla.org/en-US/docs/Template:%s</kbd></dd>
 <dt>Tags {{optional_inline}}</dt>
 <dd>A list of tags used to organize your bookmarks; these are entirely optional and what (if any) tags you use is up to you.</dd>
 <dt>Keyword</dt>
 <dd>The shortcut text you wish to use to access the template. Ideally, this should be something short and quick to type, such as simply "t" or "mdnt".</dd>
 <dt>Description {{optional_inline}}</dt>
 <dd>A suitable description explaining what the search keyword does.</dd>
</dl>

<p>The resulting dialog looks something like this:</p>

<p><img alt="The bookmark editor box showing how a search keyword to open templates looks." src="https://mdn.mozillademos.org/files/12620/Open-MDN-Template-Window.png" style="border-style: solid; border-width: 1px; height: 279px; width: 426px;"></p>

<p>Then click the "Add" button to save your new search keyword. From then on, typing your keyword, then a space, then the name of a macro will open that macro in your current tab. So if you used "t" as the keyword, typing <kbd>t ListSubpages</kbd> will show you the page at {{TemplateLink("ListSubpages")}}.</p>

<h2 id="Cookbook">Cookbook</h2>

<p>This section will list examples of common patterns for templates used on MDN, including samples of legacy DekiScript templates and their new KumaScript equivalents.</p>

<h3 id="Force_templates_used_on_a_page_to_be_reloaded">Force templates used on a page to be reloaded</h3>

<p>It bears repeating: To force templates used on a page to be reloaded after editing, hit Shift-Reload. Just using Reload by itself will cause the page contents to be regenerated, but using cached templates and included content. A Shift-Reload is necessary to invalidate caches beyond just the content of the page itself.</p>

<h3 id="Recovering_from_Unknown_Error">Recovering from "Unknown Error"</h3>

<p>Sometimes, you'll see a scripting message like this when you load a page:</p>

<pre class="notranslate">Kumascript service failed unexpectedly: &lt;class 'httplib.BadStatusLine'&gt;</pre>

<p>This is probably a temporary failure of the KumaScript service. If you Refresh the page, the error may disappear. If that doesn't work, try a Shift-Refresh. If, after a few tries, the error persists - <a class="link-https" href="https://bugzilla.mozilla.org/enter_bug.cgi?product=mozilla.org&amp;format=itrequest">file an IT bug</a> for Mozilla Developer Network to ask for an investigation.</p>

<h3 id="Broken_wiki.languages_macros">Broken wiki.languages() macros</h3>

<p>On some pages, you'll see a scripting error like this:</p>

<pre class="notranslate">Syntax error at line 436, column 461: Expected valid JSON object as the parameter of the preceding macro but...
</pre>

<p>If you edit the page, you'll probably see a macro like this at the bottom of the page:</p>

<pre class="notranslate">\{{ wiki.languages({ "zh-tw": "zh_tw/Core_JavaScript_1.5_教學/JavaScript_概要", ... }) }}
</pre>

<p>To fix the problem, just delete the macro. Or, replace the curly braces on either side with HTML comments <code>&lt;!-- --&gt;</code> to preserve the information, like so:</p>

<pre class="notranslate">&lt;!-- wiki.languages({ "zh-tw": "zh_tw/Core_JavaScript_1.5_教學/JavaScript_概要", ... }) --&gt;
</pre>

<p>Because Kuma supports localization differently, these macros aren't actually needed any more. But, they've been left intact in case we need to revisit the relationships between localized pages. Unfortunately, it seems like migration has failed to convert some of them properly.</p>

<h3 id="Finding_the_Current_Pages_Language">Finding the Current Page's Language</h3>

<p>In KumaScript, the locale of the current document is exposed as an environment variable:</p>

<pre class="notranslate">var lang = env.locale;
</pre>

<p>The <code>env.locale</code> variable should be reliable and defined for every document.</p>

<h3 id="Reading_the_contents_of_a_page_attachment">Reading the contents of a page attachment</h3>

<p>You can read the contents of an attached file by using the <code>mdn.getFileContent()</code> function, like this:</p>

<pre class="notranslate">&lt;%
  var contents = mdn.getFileContent(fileUrl);
  ... do stuff with the contents ...
%&gt;
</pre>

<p>or</p>

<pre class="notranslate">&lt;%-mdn.getFileContent(fileObject)%&gt;
</pre>

<p>In other words, you may specify either the URL of the file to read or as a file object. The file objects for a page can be accessed through the array <code>env.files</code>. So, for example, to embed the contents of the first file attached to the article, you can do this:</p>

<pre class="notranslate">&lt;%-mdn.getFileContent(env.files[0])%&gt;
</pre>

<div class="note"><strong>Note:</strong> You probably don't want to try to embed the contents of a non-text file this way, as the raw contents would be injected as text. This is meant to let you access the contents of text attachments.</div>

<p>If the file isn't found, an empty string is returned. There is currently no way to tell the difference between an empty file and a nonexistent one. But if you're putting empty files on the wiki, you're doing it wrong.</p>

<h3 id="Localizing_template_content">Localizing template content</h3>

<p>Templates cannot be translated like other wiki pages. KumaScript only looks for templates in the en-US locale (i.e., <code>/en-US/docs/Template:{name}</code>), and does not look for templates that have been translated to another locale (i.e., <code>/fr/docs/Template:{name}</code>).</p>

<p>So the main way to output content tailored to the current document locale is to pivot on the value of <code>env.locale</code>. There are many ways to do this, but a few patterns are common in the conversion of legacy DekiScript templates:</p>

<h4 id="Ifelse_blocks_in_KumaScript">If/else blocks in KumaScript</h4>

<p>The KumaScript equivalent of this can be achieved with simple if/else blocks, like so:</p>

<pre class="notranslate">&lt;% if ("fr" == env.locale) { %&gt;
&lt;%- template("CSSRef") %&gt; « &lt;a title="Référence_CSS/Extensions_Mozilla" href="/fr/docs/Référence_CSS/Extensions_Mozilla"&gt;Référence CSS:Extensions Mozilla&lt;/a&gt;
&lt;% } else if ("ja" == env.locale) { %&gt;
&lt;%- template("CSSRef") %&gt; « &lt;a title="CSS_Reference/Mozilla_Extensions" href="/ja/docs/CSS_Reference/Mozilla_Extensions"&gt;CSS リファレンス:Mozilla 拡張仕様&lt;/a&gt;
&lt;% } else if ("pl" == env.locale) { %&gt;
&lt;%- template("CSSRef") %&gt; « &lt;a title="Dokumentacja_CSS/Rozszerzenia_Mozilli" href="/pl/docs/Dokumentacja_CSS/Rozszerzenia_Mozilli"&gt;Dokumentacja CSS:Rozszerzenia Mozilli&lt;/a&gt;
&lt;% } else if ("de" == env.locale) { %&gt;
&lt;%- template("CSSRef") %&gt; « &lt;a title="CSS_Referenz/Mozilla_CSS_Erweiterungen" href="/de/docs/CSS_Referenz/Mozilla_CSS_Erweiterungen"&gt;CSS Referenz: Mozilla Erweiterungen&lt;/a&gt;
&lt;% } else { %&gt;
&lt;%- template("CSSRef") %&gt; « &lt;a title="CSS_Reference/Mozilla_Extensions" href="/en-US/docs/CSS_Reference/Mozilla_Extensions"&gt;CSS Reference:Mozilla Extensions&lt;/a&gt;
&lt;% } %&gt;
</pre>

<p>Depending on what text editor is your favorite, you may be able to copy &amp; paste from the browser-based editor and attack this pattern with a series of search/replace regexes to get you most of the way there.</p>

<p>My favorite editor is MacVim, and a series of regexes like this does the bulk of the work with just a little manual clean up following:</p>

<pre class="notranslate">%s#&lt;span#^M&lt;span#g
%s#&lt;span lang="\(.*\)" .*&gt;#&lt;% } else if ("\1" == env.locale) { %&gt;#g
%s#&lt;span class="script"&gt;template.Cssxref(#&lt;%- template("Cssxref", [#
%s#)&lt;/span&gt; &lt;/span&gt;#]) %&gt;
</pre>

<p>Your mileage may vary, and patterns change slightly from template to template. That's why the migration script was unable to just handle this automatically, after all.</p>

<h4 id="String_variables_and_switch">String variables and switch</h4>

<p>Rather than switch between full chunks of markup, you can define a set of strings, switch them based on locale, and then use them to fill in placeholders in a single chunk of markup:</p>

<pre class="notranslate">&lt;%
var s_title = 'Firefox for Developers';
switch (env.locale) {
    case 'de':
        s_title = "Firefox für Entwickler";
        break;
    case 'fr':
        s_title = "Firefox pour les développeurs";
        break;
    case 'es':
        s_title = "Firefox para desarrolladores";
        break;
};
%&gt;
&lt;span class="title"&gt;&lt;%= s_title %&gt;&lt;/span&gt;
</pre>

<h4 id="Use_mdn.localString">Use <code>mdn.localString()</code></h4>

<p>A recent addition to the <code>Template:MDN:Common</code> module is <code>mdn.localString()</code>, used like this:</p>

<pre class="notranslate">&lt;%
var s_title = mdn.localString({
  "en-US": "Firefox for Developers",
  "de": "Firefox für Entwickler",
  "es": "Firefox para desarrolladores"
});
%&gt;
&lt;span class="title"&gt;&lt;%= s_title %&gt;&lt;/span&gt;
</pre>

<p>This is more concise than the switch statement, and may be a better choice where a single string is concerned. However, if many strings need to be translated (e.g., as in <a class="link-https" href="/en-US/docs/Template:CSSRef" title="/en-US/docs/Template:CSSRef">CSSRef</a>), a switch statement might help keep all the strings grouped by locale and more easily translated that way.</p>

<p>When the object does not have the appropriate locale, the value of "en-US" is used as the initial value.</p>

<h2 id="See_also">See also</h2>

<ul>
 <li><a href="/en-US/docs/Project:Getting_started_with_Kuma" title="Getting started with Kuma">Getting started with Kuma</a></li>
 <li><a href="/en-US/docs/Project:KumaScript_reference" title="Project:en/KumaScript reference">KumaScript reference</a></li>
 <li><a class="link-https" href="https://wiki.mozilla.org/MDN/Kuma" title="https://wiki.mozilla.org/MDN/Kuma">Kuma wiki</a></li>
</ul>