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
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
|
---
title: Introducción a KumaScript
slug: MDN/Tools/KumaScript
translation_of: MDN/Tools/KumaScript
original_slug: MDN/Tools/Introduction_to_KumaScript
---
<div>{{MDNSidebar}}</div>
<div>{{draft}}</div>
<h2 id="Vistazo_general">Vistazo general</h2>
<p>En el verano de 2012, MDN cambió a una nueva plataforma wiki llamada <a class="link-https" href="https://wiki.mozilla.org/MDN/Kuma" title="https://wiki.mozilla.org/MDN/Kuma">Kuma</a>. Esta reemplaza el lenguaje de plantilla <a class="external" href="http://developer.mindtouch.com/en/docs/DekiScript" title="http://developer.mindtouch.com/en/docs/DekiScript">DekiScript</a> con un nuevo sistema llamado <a class="link-https" href="https://github.com/mozilla/kumascript" title="https://github.com/mozilla/kumascript">KumaScript</a>. KumaScript se alimenta de JavaScript del lado del servidor, usando <a class="external" href="http://nodejs.org/" title="http://nodejs.org/">Node.js</a>. Este artículo provee informaciónde cómo usar KumaScript y cómo actualizar scripts migrados parcialmente desde MindTouch.</p>
<p>Para detalles y preguntas frecuentes sobre KumaScript, mira el <a href="https://vreplay.mozilla.com/replay/showRecordDetails.html?sortBy=date&viewCount=1&currentPage=1&groupBy=combo&roomFilter=&usernameFilter=&searchFilter=&usernameFullFilter=&myManager=-1&adminManager=0&webCast=0&command=&recId=1082&auxMessage=&auxMessage1=&lang=en&langChanged=&tenantFilter=&securityTab=" style="line-height: 1.5;">KumaScript Fireside Chat</a> del equipo de desarrolladores<span style="line-height: 1.5;"> MDN</span><span style="line-height: 1.5;">.</span></p>
<p><span style="">¿Qué es KumaScript?</span></p>
<ul>
<li>Una forma de reutilizar y localizar contenido que aparece repetidamente entre los documentos (por ejemplo, rótulos de compatibilidad, navegación de secciones, carteles de advertencia).</li>
<li>Una manera de construir documentos sacados de otros documentos.</li>
<li>Una manera de buscar e incluir contenido de otros sitios web y servicios (por ejemplo, Bugzilla).</li>
</ul>
<h3 id="¿Qué_no_es_KumaScript">¿Qué no es KumaScript?</h3>
<ul>
<li>KumaScript no soporta scripts interactivos del tipo que pueden aceptar las incripciones por formulario.</li>
<li>KumaScript no tiene acceso a bases de datos, archivos, ni a cualquier otra forma de guardar información persistentemente.</li>
<li>KumaScript no soporta la personalización basada en el usuario que tiene la sesión abierta.</li>
<li>KumaScript no tiene acceso a información de usuario, sólo al contenido y a los metadatos de una wiki que se esté visualizando.</li>
</ul>
<h2 id="Aspectos_básicos">Aspectos básicos</h2>
<p>KumaScript funciona permitiendo a <em>wiki de confianza</em> escribir <a class="link-https" href="https://github.com/visionmedia/ejs" title="https://github.com/visionmedia/ejs">plantillas JavaScript ensambladas</a>. Estas plantillas pueden ser invocadas en el contenido del documento por cualquier editor <em>wiki</em> mediante el uso de <a class="link-https" href="/en-US/docs/KumaTests/hello_test?raw=1" title="/en-US/docs/KumaTests/hello_test?raw=1">macros</a>.</p>
<table style="display: block;">
<tbody>
<tr>
<td>
<p>Una <a class="link-https" href="/en-US/docs/Template:hello" title="/en-US/docs/Template:hello">plantilla</a> se vé así:</p>
</td>
<td>
<p>Una <a class="link-https" href="/en-US/docs/KumaTests/hello_test?raw=1" title="/en-US/docs/KumaTests/hello_test?raw=1">macro</a> se vé así:</p>
</td>
<td>
<p>El <a class="link-https" href="/en-US/docs/KumaTests/hello_test" title="/en-US/docs/KumaTests/hello_test">resultado de una macro</a> sale así:</p>
</td>
</tr>
<tr>
<td>
<pre class="notranslate">
<% for (var i = 0; i < $0; i++) { %>
Hello #<%= i %>
<% } %></pre>
</td>
<td>
<pre class="notranslate">
\{{ hello("3") }}
</pre>
</td>
<td>
<pre class="notranslate">
Hello #0
Hello #1
Hello #2</pre>
</td>
</tr>
</tbody>
</table>
<h3 id="Sintaxis_de_una_macro">Sintaxis de una macro</h3>
<p>Las plantillas KumaScript se invocan en el contenido del documento con macros, como esta:</p>
<pre class="notranslate">\{{ templateName("arg0", "arg1", ..., "argN") }}
</pre>
<p>La sintaxis de una Macro se compone de estas reglas:</p>
<ul>
<li>Las Macros comienzan y terminan con los caracteres <code>\{{</code> y <code>}}</code>.</li>
<li>La primera parte de la macro es el nombre de la plantilla. Esta corresponde a una wiki en <code>/en-US/docs/Template:{name}</code>. Editar y crear estas páginas requiere un permiso especial que los administradores pueden otorgar a editores de confianza.</li>
<li>Una plantilla puede aceptar parámetros, y esta lista de parámetroa comienza y termina con paréntesis.</li>
<li>En una plantilla, los parámetros ingresados están disponibles dentro de la macro como las variables <code>$0</code>, <code>$1</code>, <code>$2</code>, y así sucesivamente.</li>
<li>Todos los parámetros no numéricos deber ir entre comillas. Los números pueden quedar sin ellas.</li>
<li>La lista completa de parámetros también está disponible en una plantilla como la variable <code>arguments</code>.</li>
</ul>
<h4 id="Usando_JSON_parámetro_de_macro">Usando JSON parámetro de macro</h4>
<p>Hay una característica semi-experimental disponible para las macros. Puedes proveerlas de un objeto JSON como primero y único parámetro, así:</p>
<pre class="notranslate">\{{ templateName({ "Alpha":"one", "Beta":["a","b","c"], "Foo":"http:\/\/mozilla.org\/" }) }}
</pre>
<p>Los datos de esta macro estarán disponibles en un código de plantilla como un objeto en el argumento <code>$0</code> (por ejemplo, <code>$0.Alpha</code>, <code>$0.Beta</code>, <code>$0.Foo</code>). Esto también te permite expresar estructuras de datos complejos en los parámetros de macro que son difíciles o imposibles de hacer con una simple lista de parámetros.</p>
<p>Nota que el estilo de este parámetro es muy complejo. Se debe adherir exactamente a la <a href="http://json.org/" title="http://json.org/">sintaxis JSON</a>, que tiene algunas exigencias escurridizas que son fáciles de pasar por alto (por ejemplo, todas las barras (/) llevan escapes). Cuando haya dudas, <a href="http://jsonlint.com/" title="http://jsonlint.com/">intenta ejecutar tu JSON con un validador</a>.</p>
<h4 id="Cómo_escribir">Cómo escribir "\{{"</h4>
<p>Como la secuencia de caracteres "<code>\{{</code>" se usa para indicar el comienzo de una macro, puede ser un problema si justo quieres usar "<code>\{{</code>" and "<code>}}</code>" como texto de una página. Probablemente dará un mensaje de error <code>DocumentParsingError</code>.</p>
<p>En este caso, puedes escapar la primer llave con una barra invertida, así: <code>\\{</code></p>
<h3 id="Sintaxis_de_la_plantilla">Sintaxis de la plantilla</h3>
<p>Las plantillas KumaScript son procesadas por un <a class="link-https" href="https://github.com/visionmedia/ejs" title="https://github.com/visionmedia/ejs">motor de plantillas JavaScript ensamblado</a> con estas simples reglas:</p>
<ul>
<li>La mayoría del texto es tratado como salida e incluido en el flujo de salida.</li>
<li>Las expresiones y variables JavaScript pueden insertarse en el flujo de salida con estos bloques:
<ul>
<li><code><%= expr %></code> — el valor de la expresión JavaScript es escapado por el HTML antes de incluirse en la salida (por ejemplo, caracteres como <code><</code> y <code>></code> se convierten en <code>&lt;</code> y <code>&gt;</code>).</li>
<li><code><%- expr %></code> — el valor de una expresión JavaScript es incluído en la salida pero sin escape. (usa esto si quieres construir etiquetas HTML o usar los resultados de otra plantilla que puedan incluir etiquetas HTML.)</li>
<li>Es un error incluir punto y coma dentro de los bloques.</li>
</ul>
</li>
<li>Cualquier cosa dentro de un bloque <code><% %></code> se interpreta como JavaScript. Esto puede incluir bucles, condiciones, etc.</li>
<li>No hay nada dentro de un bloque <code><% %></code> que pueda contribuir al flujo de salida. Pero puedes hacer la transición desde el modo JS al modo de salida usando <code><% %> </code>—Por ejemplo:
<pre class="notranslate"><% for (var i = 0; i < $0; i++) { %>
Hello #<%= i %>
<% } %>
</pre>
<p>Nota como el JS está contenido entre <code><% ... %></code>, y la salida va en el espacio entre <code>%> ... <%</code>. El bucle <em>for</em> en JS puede comenzar en un bloque <code><% %></code> , luego el flujo de salida, y terminar en un segundo bloque JS <code><% %></code>.</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>
<h2 id="Características_avanzadas">Características avanzadas</h2>
<p>Más allá de los aspectos básicos, el sistema KumaScript ofrece algunas características avanzadas.</p>
<h3 id="Variables_de_entorno">Variables de entorno</h3>
<p>Cuando la wiki hace una llamada al servicio KumaScript, <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">pasa por una part del contexto del documento actual</a> que KumaScript pone a disposición de las plantillas como variables:</p>
<dl>
<dt><code>env.path</code></dt>
<dd>La ruta del documento wiki actual</dd>
<dt><code>env.url</code></dt>
<dd>La URL completa del documento wiki actual</dd>
<dt><code>env.id</code></dt>
<dd>Un ID único corto para el documento wiki actual</dd>
<dt><code>env.files</code></dt>
<dd>Un arreglo de archivos adjuntos para el documento wiki actual. Cada objeto en el arreglo se describe como {{ anch("File objects") }} debajo</dd>
<dt><code>env.review_tags</code></dt>
<dd>Un arreglo con las etiquetas de revisión del artículo ("technical", "editorial", etc.)</dd>
<dt><code>env.locale</code></dt>
<dd>El sitio del documento wiki actual</dd>
<dt><code>env.title</code></dt>
<dd>El título del documento wiki actual</dd>
<dt><code>env.slug</code></dt>
<dd>Una URL amigable del documento wiki actual</dd>
<dt><code>env.tags</code></dt>
<dd>Una lista de nombers de etiquetas para el documento wiki actual</dd>
<dt><code>env.modified</code></dt>
<dd>El último timestamp modificado para el documento wiki actual</dd>
<dt><code>env.cache_control</code></dt>
<dd><code>El encabezado Cache-Control</code> henviado en la solicitud para el documento wiki actual, útil para decidir si invalidar los caches</dd>
</dl>
<h4 id="Objetos_de_archivos">Objetos de archivos</h4>
<p>Cada objeto de archivo tiene los siguientes campos:</p>
<dl>
<dt><code>title</code></dt>
<dd>El título del archivo adjunto</dd>
<dt><code>description</code></dt>
<dd>Una descripción textual de la revisión actual del archivo</dd>
<dt><code>filename</code></dt>
<dd>El nombre del archivo</dd>
<dt><code>size</code></dt>
<dd>El tamaños del archivo en bytes</dd>
<dt><code>author</code></dt>
<dd>El nombre de usuario de la persona que subió el archivo</dd>
<dt><code>mime</code></dt>
<dd>El tipo MIME del archivo</dd>
<dt><code>url</code></dt>
<dd>La URL en la que se puede encontrar el archivo</dd>
</dl>
<h4 id="Trabajando_con_listas">Trabajando con listas</h4>
<p>Las variables <code>env.tags</code> y <code>env.review_tags</code> devuelven colecciones de etiqutas. Puedes trabajar con estas de varias maneras, por supuesto, pero aquí se dan un par de sugerencias.</p>
<h5 id="Buscar_si_se_colocó_una_etiqueta_específica">Buscar si se colocó una etiqueta específica</h5>
<p>Se puede buscar si una etiqueta específica existe en una página, así:</p>
<pre class="brush: js notranslate">if (env.tags.indexOf("tag") != −1) {
// The page has the tag "tag"
}
</pre>
<h5 id="Iterar_recorrer_todas_las_etiquetas_de_la_página">Iterar (recorrer) todas las etiquetas de la página</h5>
<p>Se pueden recorrer todas las etiquetas de la página, así:</p>
<pre class="brush: js notranslate">env.tag.forEach(function(tag) {
// haz cualquier cosa que necesites, tal como:
if (tag.indexOf("a") == 0) {
// esta etiqueta empieza con "a" - woohoo!
}
});</pre>
<h3 id="APIs_y_Módulos">APIs y Módulos</h3>
<p>KumaScript ofrece algunas APIs de utilidad incorporadas, como también la capacidad para definir nuevas APIs en módulos editables como documentos wiki.</p>
<h4 id="Métodos_incorporados">Métodos incorporados</h4>
<p>Es probable que esta documentación mantenida manualmente quede desactualizada con respecto al código. Teniendo en cuanta eso, <a class="link-https" href="https://github.com/mozilla/kumascript/blob/master/lib/kumascript/api.js#L208" title="https://github.com/mozilla/kumascript/blob/master/lib/kumascript/api.js#L208">siempre puedes verificar el último estado de las APIs incorporadas en la fuente de KumaScript</a>. Pero hay una selección de métodos útiles expuestos a plantillas:</p>
<dl>
<dt><code>md5(string)</code></dt>
<dd>Devuelve un resumen de hexadecimal MD5 de determinada cadena.</dd>
<dt><code>template("name", ["arg0", "arg1", ..., "argN"])</code></dt>
<dd>Ejecuta y devuelve el resultado de las plantillas mencionadas con la lista de parámetros provistos.</dd>
<dd>Utilizado en plantillas así: <code><%- template("warning", ["foo", "bar", "baz"]) %></code>.</dd>
<dd>Esta es una función JavaScript. Así que, si uno de los parámetroses una variable arg como $2, no lo pongas entre comillas. Así: <code><%- template("warning", [$1, $2, "baz"]) %></code>. Si necesitas llamar otra plantilla desde el interior de un bloque e código, no uses <code><%</code> ... <code>%></code>. Ejemplo: <code>myvar = "<li>" + template("LXRSearch", ["ident", "i", $1]) + "</li>";</code></dd>
<dt><code>require(name)</code></dt>
<dd>Carga otra plantilla como un módulo. Cualquier resultadu es ignorado. Devuelce cualquier cosa asignada a <code>module.exports</code> en la plantilla.</dd>
<dd>Utilizado en plantillas así: <code><% var my_module = require('MyModule'); %></code>.</dd>
<dt><code>cacheFn(key, timeout, function_to_cache)</code></dt>
<dd>Usando la key y duración de entrada de caché proporcionadas, cachea los resultados de la función proporcionada. Prioriza el valor de <code>env.cache_control</code> para invalidar el cache en <code>no-cache</code>, que puede ser enviado por un usuario logueado que tipee shift-refresh.</dd>
<dt><code>request</code></dt>
<dd>Acceso al <a class="link-https" href="https://github.com/mikeal/request" title="https://github.com/mikeal/request"><code>mikeal/request</code></a>, una librería para hacer consultas HTTP. Usar este módulo en las plantillas KumaScriptno es muy amigable, así que quizá desees envolver uso en APIs de módulo que simplifiquen las cosas.</dd>
</dl>
<h4 id="Módulos_de_API_incorporados">Módulos de API incorporados</h4>
<p>Sólo hay una API incorporada por el momento, en el espacio de nombres <code>kuma</code>:</p>
<dl>
<dt><code>kuma.htmlEscape(string)</code></dt>
<dd>Escapa los caracteres <code>&, <, >, "</code> a <code>&amp, &lt;, &gt;, &quot;</code>, respectivamente.</dd>
<dt> </dt>
<dt><code>kuma.include(path)</code></dt>
<dd>Incluye contenido de la página en la ruta proporcionada. Cacheo pesado.</dd>
</dl>
<dl>
<dt><code>kuma.pageExists(path)</code></dt>
<dd>Indica si existe la página en la ruta proporcionada. Cacheo pesado.</dd>
</dl>
<h4 id="Creando_módulos">Creando módulos</h4>
<p>Usando el mátodo incorporado <code>require()</code>, puedes cargar una plantilla como módulo para compartir variables y métodos comunes entre plantillas. Un módulo puede definirse como una plantilla de la siguiente manera:</p>
<pre class="notranslate"><%
module.exports = {
add: function (a, b) {
return a + b;
}
}
%>
</pre>
<p>Asumiendo que esta plantilla está guardada como <code>/en-US/docs/Template:MathLib</code>, puedes utilizarla en otra plantilla, así:</p>
<pre class="notranslate"><%
var math_lib = require("MathLib");
%>
El resultado de 2 + 2 = <%= math_lib.add(2, 2) %>
</pre>
<p>Y, el resultado de esta plantilla será:</p>
<pre class="notranslate">el resultado de 2 + 2 = 4
</pre>
<h4 id="Módulos_cargados_automáticamente">Módulos cargados automáticamente</h4>
<p>Hay un grupo de módulos editables como plantillas wiki que se cargan automáticamente y quedan disponibles para cada plantilla. Este grupo está definido en el archivo de configuración para el servicio KumaScript. Cualquier cambio a este requiere un bug IT para editar la configuración y el reinicio del servicio.</p>
<p>Para la mayor parte, estos intentos de proveer sustitutos para 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>Culture.*</code> - <a class="link-https" href="/en-US/docs/Template:DekiScript:Culture" title="/en-US/docs/Template:DekiScript:Culture">Template:DekiScript:Culture</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>Json.*</code> - <a class="link-https" href="/en-US/docs/Template:DekiScript:Json" title="/en-US/docs/Template:DekiScript:Json">Template:DekiScript:Json</a></li>
<li><code>List.*</code> - <a class="link-https" href="/en-US/docs/Template:DekiScript:List" title="/en-US/docs/Template:DekiScript:List">Template:DekiScript:List</a></li>
<li><code>Map.*</code> - <a class="link-https" href="/en-US/docs/Template:DekiScript:Map" title="/en-US/docs/Template:DekiScript:Map">Template:DekiScript:Map</a></li>
<li><code>Meta.*</code> - <a class="link-https" href="/en-US/docs/Template:DekiScript:Meta" title="/en-US/docs/Template:DekiScript:Meta">Template:DekiScript:Meta</a></li>
<li><code>Num.*</code> - <a class="link-https" href="/en-US/docs/Template:DekiScript:Num" title="/en-US/docs/Template:DekiScript:Num">Template:DekiScript:Num</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>
<li><code>Xml.*</code> - <a class="link-https" href="/en-US/docs/Template:DekiScript:Xml" title="/en-US/docs/Template:DekiScript:Xml">Template:DekiScript:Xml</a></li>
</ul>
<p>The best way to see the current state and offerings of these modules is to <a class="link-https" href="/en-US/docs/tag/dekiscript" title="/en-US/docs/tag/dekiscript">take a look at their source directly</a>.</p>
<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"><% module.exports = buildAPI({
StartsWith: function (str, sub_str) {
return (''+str).indexOf(sub_str) === 0;
}
}); %>
</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>
<p>With that in mind, please do not use <code>buildAPI()</code> in new modules.</p>
<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"><%- log.debug("Some text goes here"); %>
</pre>
<p>You can, of course, create more complex output using script code if it's helpful.</p>
<h3 id="Limitations_of_content_migration_from_MindTouch">Limitations of content migration from MindTouch</h3>
<p>When we make the move to Kuma, we will migrate content from the old MindTouch-based wiki to the new Kuma-based one. This script will do some basic work to attempt to convert scripts. But, there are many common code patterns that migration can't fix.</p>
<p>So, this means that we'll need human intervention to carry template scripts over the rest of the way to being functional.</p>
<p>To find templates in need of review and repair, <a class="link-https" href="/en-US/docs/needs-review/template" title="/en-US/docs/needs-review/template">check here</a>: <a class="link-https" href="/en-US/docs/needs-review/template" rel="freelink">/en...eview/template</a>.</p>
<p>To find examples of templates that have already been repaired, <a class="link-https" href="/en-US/docs/tag/ks-fixed" title="/en-US/docs/tag/ks-fixed">check here</a>: <a class="link-https" href="/en-US/docs/tag/ks-fixed" rel="freelink">/en...s/tag/ks-fixed</a>.</p>
<p>Check the <a class="link-https" href="https://bugzilla.mozilla.org/show_bug.cgi?id=714804">template usage stats bug</a> file attachments to help prioritize templates to fix. If you know your way around <code>gzip</code> and <code>grep</code>, <a class="link-https" href="https://bugzilla.mozilla.org/attachment.cgi?id=591545" title="https://bugzilla.mozilla.org/attachment.cgi?id=591545">this attachment</a> (a 1.5MB tab-delimited file listing template/document pairs) can help tell you what templates are used on which pages.</p>
<p>As you repair templates, please uncheck the "Template" review checkbox and add the tag "ks-fixed", which will keep the above lists accurate.</p>
<p>You can also find templates in need of repair by simply browsing through wiki content and spotting where content looks garbled with code or otherwise incorrect. Editing the page should show you the name of a macro that's in need of help. You may also see scripting errors on pages, which should offer editing links to the templates causing issues.</p>
<h3 id="Keyword_Shortcut_for_quick_template_editing">Keyword Shortcut for quick template editing</h3>
<p>If you spend time editing a lot of KumaScript templates (e.g., to fix partly-migrated legacy DekiScript templates), you may find this keyword shortcut bookmark handy:</p>
<table style="width: 100%;">
<tbody>
<tr>
<th>Name</th>
<td><code>edit mdn template</code></td>
</tr>
<tr>
<th>Location</th>
<td><code><a class="link-https" href="/en-US/docs/Template:%s$edit" rel="freelink">/en...mplate:%s$edit</a></code></td>
</tr>
<tr>
<th>Keyword</th>
<td><code>te</code></td>
</tr>
</tbody>
</table>
<p>Armed with this bookmarklet, you can copy the name of a template, open a new tab, and type "te [Ctrl-V][Return]" to start editing the template. This helps when a template is misbehaving, yet not badly enough to cause a scripting error message.</p>
<h3 id="Changing_Locale_Identifiers">Changing Locale Identifiers</h3>
<p>The identifiers for various locales have changed from MindTouch to Kuma:</p>
<ul>
<li><code>en</code> -> <code>en-US</code></li>
<li><code>cn</code> -> <code>zh-CN</code></li>
<li><code>zh_cn</code> -> <code>zh-CN</code></li>
<li><code>zh_tw</code> -> <code>zh-TW</code></li>
<li><code>pt</code> -> <code>pt-PT</code></li>
</ul>
<p>This list should not change in the future, assuming we've not missed any. These locale identifier changes become significant in legacy DekiWIki templates.</p>
<h3 id="URL_pattern_changes">URL pattern changes</h3>
<p>The URL pattern for all wiki documents has changed:</p>
<ul>
<li><code>/{locale}/{slug}</code> -> <code>/{locale}/docs/{slug}</code></li>
</ul>
<p>So, for example:</p>
<ul>
<li><code>/en/JavaScript</code> -> <code>/en-US/docs/JavaScript</code></li>
<li><code>/de/JavaScript</code> -> <code>/de/docs/JavaScript</code></li>
<li><code>/ja/JavaScript</code> -> <code>/ja/docs/JavaScript</code></li>
</ul>
<p>To avoid breaking links, there is an attempt to automatically redirect requests to the legacy-style URLs to new-style URLs. But, efforts should be made to change links to the new-style URLs whenever possible.</p>
<h3 id="Differences_from_DekiScript">Differences from DekiScript</h3>
<p>It's useful to note a few changes from templates in DekiScript, in case you encounter these in migrated content:</p>
<ul>
<li>No more <code><span class="script"></code></li>
<li>No more <code>template.</code> nor <code>wiki.template</code> prefixing</li>
<li>No more <code>template({name}[, arguments])</code> syntax</li>
<li>Arguments must be quoted - e.g., <code>bug(123456)</code> becomes <code>bug("123456")</code> - unless you are calling the template from within another template, and the argument is one of the passed-in args like <code>$1</code> in this example: <code>template("LXRSearch", ["ident", "i", $1])</code>.</li>
</ul>
<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>
<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: <class 'httplib.BadStatusLine'></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&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><!-- --></code> to preserve the information, like so:</p>
<pre class="notranslate"><!-- wiki.languages({ "zh-tw": "zh_tw/Core_JavaScript_1.5_教學/JavaScript_概要", ... }) -->
</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="Unconverted_inline_script_blocks">Unconverted inline script blocks</h3>
<p>Occasionally, you'll find some text like this at the bottom of a page, or even somewhere in the middle:</p>
<pre class="notranslate">ottoPreviousNext("JSGChapters");
wiki.languages({
"fr": "fr/Guide_JavaScript_1.5/Expressions_rationnelles",
"ja": "ja/Core_JavaScript_1.5_Guide/Regular_Expressions"
});
</pre>
<p>This is a script block that didn't get converted to a KumaScript macro during migration. It happens, unfortunately. If you switch to HTML source editing mode, you'll see this, a <code><pre class="script"></code> element:</p>
<pre class="notranslate"><pre class="script" style="font-size: 16px;">
ottoPreviousNext(&quot;JSGChapters&quot;);
wiki.languages({
&quot;fr&quot;: &quot;fr/Guide_JavaScript_1.5/Expressions_rationnelles&quot;,
&nbsp;&quot;ja&quot;: &quot;ja/Core_JavaScript_1.5_Guide/Regular_Expressions&quot;
});
</pre>
</pre>
<p>This is an inline script - previously allowed by DekiScript, no longer supported by KumaScript.</p>
<p>For this particular example, common to the JavaScript Guide, you can fix it by removing the wiki.languages part (see <a href="/en-US/docs/Project:Introduction_to_KumaScript#Broken_wiki.languages()_macros" title="Project:Introduction_to_KumaScript#Broken_wiki.languages()_macros">previous section</a>) and change the ottoPreviousNext() into a macro like so:</p>
<pre class="notranslate">\{{ ottoPreviousNext("JSGChapters") }}
</pre>
<p>If you see a block of code that's more complex than the above, you will need to create a new template, move the code there, and replace the code in its previous spot with a macro calling the new template.</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>In legacy DekiScript templates, coming up with the locale was a bit harder. You'll see chunks of code like this:</p>
<pre class="notranslate">/* accepts as input one required parameter: MathML element to create an xref to */
var u = uri.parts(Page.uri);
var lang = string.tolower(u.path[0]);
if (string.contains(lang, "project") || string.contains(lang, "Project")) {
lang = string.substr(lang, 8);
}
/* fall back to page.language on a user page */
else if (string.StartsWith(lang, "user:")) {
lang = page.language;
}
</pre>
<p>Please replace code like the above with the new KumaScript example. 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"><%
var contents = mdn.getFileContent(fileUrl);
... do stuff with the contents ...
%>
</pre>
<p>or</p>
<pre class="notranslate"><%-mdn.getFileContent(fileObject)%>
</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"><%-mdn.getFileContent(env.files[0])%>
</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"><% if ("fr" == env.locale) { %>
<%- template("CSSRef") %> « <a title="Référence_CSS/Extensions_Mozilla" href="/fr/docs/Référence_CSS/Extensions_Mozilla">Référence CSS:Extensions Mozilla</a>
<% } else if ("ja" == env.locale) { %>
<%- template("CSSRef") %> « <a title="CSS_Reference/Mozilla_Extensions" href="/ja/docs/CSS_Reference/Mozilla_Extensions">CSS リファレンス:Mozilla 拡張仕様</a>
<% } else if ("pl" == env.locale) { %>
<%- template("CSSRef") %> « <a title="Dokumentacja_CSS/Rozszerzenia_Mozilli" href="/pl/docs/Dokumentacja_CSS/Rozszerzenia_Mozilli">Dokumentacja CSS:Rozszerzenia Mozilli</a>
<% } else if ("de" == env.locale) { %>
<%- template("CSSRef") %> « <a title="CSS_Referenz/Mozilla_CSS_Erweiterungen" href="/de/docs/CSS_Referenz/Mozilla_CSS_Erweiterungen">CSS Referenz: Mozilla Erweiterungen</a>
<% } else { %>
<%- template("CSSRef") %> « <a title="CSS_Reference/Mozilla_Extensions" href="/en-US/docs/CSS_Reference/Mozilla_Extensions">CSS Reference:Mozilla Extensions</a>
<% } %>
</pre>
<h5 id="Legacy_DekiScript"><strong>Legacy DekiScript</strong></h5>
<p>A similar way this was done in DekiScript was using <code><span></code>'s with <code>lang="{locale}"</code> attributes, like so:</p>
<pre class="notranslate"><p><span lang="*" class="lang lang-*"><span class="script">CSSRef()</span> « <a title="en/CSS_Reference/Mozilla_Extensions" href="/en/CSS_Reference/Mozilla_Extensions">CSS Reference:Mozilla Extensions</a></span>
<span lang="en" class="lang lang-en"><span class="script">CSSRef()</span> « <a title="en/CSS_Reference/Mozilla_Extensions" href="/en/CSS_Reference/Mozilla_Extensions">CSS Reference:Mozilla Extensions</a>
<span lang="fr" class="lang lang-fr"><span class="script">CSSRef()</span> « <a title="fr/Référence_CSS/Extensions_Mozilla" href="/fr/Référence_CSS/Extensions_Mozilla">Référence CSS:Extensions Mozilla</a></span>
<span lang="ja" class="lang lang-ja"><span class="script">CSSRef()</span> « <a title="ja/CSS_Reference/Mozilla_Extensions" href="/ja/CSS_Reference/Mozilla_Extensions">CSS リファレンス:Mozilla 拡張仕様</a></span>
<span lang="pl" class="lang lang-pl"> <span class="script">CSSRef()</span> « <a title="pl/Dokumentacja_CSS/Rozszerzenia_Mozilli" href="/pl/Dokumentacja_CSS/Rozszerzenia_Mozilli">Dokumentacja CSS:Rozszerzenia Mozilli</a></span>
<span lang="de" class="lang lang-de"><span class="script">CSSRef()</span> « <a title="de/CSS_Referenz/Mozilla_CSS_Erweiterungen" href="/de/CSS_Referenz/Mozilla_CSS_Erweiterungen">CSS Referenz: Mozilla Erweiterungen</a></span></span></p>
</pre>
<p>This is no longer supported. If you encounter templates built using the legacy DekiScript approach, revise them to use the new KumaScript pattern.</p>
<p>Depending on what text editor is your favorite, you may be able to copy & 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#<span#^M<span#g
%s#<span lang="\(.*\)" .*>#<% } else if ("\1" == env.locale) { %>#g
%s#<span class="script">template.Cssxref(#<%- template("Cssxref", [#
%s#)</span> </span>#]) %>
</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"><%
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;
};
%>
<span class="title"><%= s_title %></span>
</pre>
<p>You'll see examples of this in legacy DekiScript templates. For the most part, this pattern should work as-is, but you may need to adjust the expected values of locales (e.g., <code>en</code>, <code>cn</code>, <code>pt</code> become <code>en-US</code>, <code>zh-CN</code>, <code>pt-PT</code> respectively).</p>
<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"><%
var s_title = mdn.localString({
"en-US": "Firefox for Developers",
"de": "Firefox für Entwickler",
"es": "Firefox para desarrolladores"
});
%>
<span class="title"><%= s_title %></span>
</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>
<h4 id="Before_and_after_examples">Before and after examples</h4>
<p>Carriage returns added here and there for clarity.</p>
<pre class="notranslate">// Before: DOM0() template Dekiscript
<p><span class="lang lang-en" lang="en">DOM Level 0. Not part of any standard. </span>
<span class="lang lang-es" lang="es">DOM Nivel 0. No es parte de ninguna norma. </span>
<span class="lang lang-*" lang="*">DOM Level 0. Not part of any standard. </span>
<span class="lang lang-fr" lang="fr">DOM Level 0. Ne fait partie d'aucune spécification. </span>
<span class="lang lang-ja" lang="ja">DOM Level 0。どの標準にも属しません。 </span>
<span class="lang lang-pl" lang="pl">DOM Level 0. Nie jest częścią żadnego standardu. </span>
<span class="lang lang-zh-cn" lang="zh-cn">DOM Level 0 不属于任何标准.</span></p>
// After: Kumascript version
<% if ("fr" == env.locale) { %>
<p>DOM Level 0. Ne fait partie d'aucune spécification.</p>
<% } else if ("ja" == env.locale) { %>
<p>DOM Level 0。どの標準にも属しません。 </p>
<% } else if ("pl" == env.locale) { %>
<p>DOM Level 0. Nie jest częścią żadnego standardu.</p>
<% } else if ("es" == env.locale) { %>
<p>DOM Nivel 0. No es parte de ninguna norma.</p>
<% } else if ("zh-CN" == env.locale) { %>
<p>DOM Level 0 不属于任何标准.</p>
<% } else { %>
<p>DOM Level 0. Not part of any standard.</p>
<% } %></pre>
<pre class="notranslate">// From ReleaseChannelInfo() template
// Before:
web.html("<p>Firefox " + $0 + ", based on Gecko " + $1 + ", will ship in " + $2 + ".
This article provides information about the changes in this release that will
affect developers. Nightly builds of what will become Firefox " + $0 + " are "
+ web.link(url, "currently available") + " on the " + string.ToUpperFirst($3)
+ " channel.</p>");
// After:
<p>Firefox <%= $0 %>, based on Gecko <%= $1 %>, will ship in <%= $2 %>. This
article provides information about the changes in this release that will
affect developers. Nightly builds of what will become Firefox <%= $0 %>
are <%- web.link(url, "currently available")%> on the
<%= string.ToUpperFirst($3) %> channel.</p></pre>
<pre class="notranslate">// Before: old Dekiscript snippet
if ($1 && string.length($1)) {
optionsText = optionsText + "<li>" + LXRSearch("ident", "i", $1) + "</li>";
}
// After: new Kumascript. Quote parameters to template() unless it is an arg variable (like $1).
if ($1 && string.length($1)) {
optionsText = optionsText + "<li>" + template("LXRSearch", ["ident", "i", $1]) + "</li>";
}
// Note that template() within <% ... %> outputs nothing directly. If you want to call another
// template and display its output, use <%= %> or <%- %> like this:
<%- template("LXRSearch", ["ident", "i", $1]) %></pre>
<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>
|