Puedes mezclar código de Apps Script y HTML para producir páginas dinámicas con un esfuerzo. Si usaste un lenguaje de plantillas que combina código y HTML, como PHP, ASP o JSP, la sintaxis debe resultarte familiar.
Scriptlets
Las plantillas de Apps Script pueden contener tres etiquetas especiales llamadas scriptlets. Interior un scriptlet, puedes escribir cualquier código que funcione en un scriptlet : los scriptlets pueden llamar a funciones definidas en otros archivos de código, referencia variables globales o usar cualquiera de las APIs de Apps Script. Incluso puedes definir funciones y variables en los scriptlets, con la salvedad de que no pueden realizan llamadas con funciones definidas en archivos de código o en otras plantillas.
Si pegas el siguiente ejemplo en el editor de secuencias de comandos, el contenido del
La etiqueta <?= ... ?>
(un scriptlet de impresión) aparecerá en
cursiva. El código en cursiva se ejecuta en el servidor antes de que se publique la página.
para el usuario. Debido a que el código scriptlet se ejecuta antes de que se entregue la página,
solo se pueden ejecutar una vez por página; a diferencia de JavaScript o Apps Script del cliente
funciones que llamas mediante
google.script.run
, los scriptlets no pueden
volverá a ejecutarse luego de que se cargue la página.
Code.gs
function doGet() {
return HtmlService
.createTemplateFromFile('Index')
.evaluate();
}
Index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
Hello, World! The time is <?= new Date() ?>.
</body>
</html>
Ten en cuenta que la función doGet()
para el código HTML de plantilla difiere de los ejemplos.
para crear y publicar HTML básico. La función
que se muestra aquí genera un
El objeto HtmlTemplate
de HTML
y, luego, llama a su
evaluate()
para
ejecutar los scriptlets y convertir la plantilla en
HtmlOutput
que la secuencia de comandos
puede entregar al usuario.
Scriptlets estándar
Los scriptlets estándar, que usan la sintaxis <? ... ?>
, ejecutan código sin
y que muestre explícitamente
el contenido en la página. Sin embargo, como se muestra en este ejemplo,
El result del código dentro de un scriptlet puede afectar el contenido HTML
fuera del scriptlet:
Code.gs
function doGet() {
return HtmlService
.createTemplateFromFile('Index')
.evaluate();
}
Index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<? if (true) { ?>
<p>This will always be served!</p>
<? } else { ?>
<p>This will never be served.</p>
<? } ?>
</body>
</html>
Cómo imprimir scriptlets
La impresión de scriptlets, que usan la sintaxis <?= ... ?>
, generan los resultados de
su código a la página mediante el escape contextual.
El escape contextual significa que Apps Script realiza un seguimiento del contexto del resultado
en la página (en un atributo HTML o en una etiqueta script
del cliente)
en cualquier otro lugar y agrega automáticamente caracteres de escape
para brindar protección contra ataques de secuencias de comandos entre sitios (XSS).
En este ejemplo, el primer scriptlet de impresión genera una cadena directamente: Está seguido de un scriptlet estándar que configura un array y un bucle, otro scriptlet de impresión para obtener el contenido del array.
Code.gs
function doGet() {
return HtmlService
.createTemplateFromFile('Index')
.evaluate();
}
Index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<?= 'My favorite Google products:' ?>
<? var data = ['Gmail', 'Docs', 'Android'];
for (var i = 0; i < data.length; i++) { ?>
<b><?= data[i] ?></b>
<? } ?>
</body>
</html>
Observa que un scriptlet de impresión solo muestra el valor de su primera sentencia;
las demás sentencias se comportan como si estuvieran en un
scriptlet. Por ejemplo, el scriptlet <?= 'Hello, world!'; 'abc' ?>
solo
imprime "Hello, World!"
Impresión forzada de scriptlets
La impresión forzada de los scriptlets, que usan la sintaxis <?!= ... ?>
, son como la impresión
scriptlets, excepto que evitan el escape contextual.
El escape contextual es importante si la secuencia de comandos permite la entrada de usuarios que no son de confianza. De el contraste, deberás forzar la impresión si la salida del scriptlet contiene HTML o secuencias de comandos que deseas insertar exactamente como se especifica.
Como regla general, usa scriptlets de impresión en lugar de scriptlets de impresión forzada. a menos que sepas que debes imprimir HTML o JavaScript sin cambios.
Código de Apps Script en scriptlets
Los Scriptlets no están restringidos a ejecutar JavaScript normal. también puedes usar cualquier de las siguientes tres técnicas para otorgarles a tus plantillas acceso a Apps Script de datos no estructurados.
Sin embargo, recuerda que, dado que el código de la plantilla se ejecuta antes de que
al usuario, estas técnicas solo pueden introducir contenido inicial en una página. Cómo acceder
Apps Script de una página de forma interactiva, usa el
google.script.run
en su lugar.
Llama a funciones de Apps Script desde una plantilla
Scriptlets pueden llamar a cualquier función definida en un archivo de código o una biblioteca de Apps Script. Este ejemplo muestra una manera de extraer datos de una hoja de cálculo a una plantilla, luego construir una tabla HTML a partir de los datos.
Code.gs
function doGet() {
return HtmlService
.createTemplateFromFile('Index')
.evaluate();
}
function getData() {
return SpreadsheetApp
.openById('1234567890abcdefghijklmnopqrstuvwxyz')
.getActiveSheet()
.getDataRange()
.getValues();
}
Index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<? var data = getData(); ?>
<table>
<? for (var i = 0; i < data.length; i++) { ?>
<tr>
<? for (var j = 0; j < data[i].length; j++) { ?>
<td><?= data[i][j] ?></td>
<? } ?>
</tr>
<? } ?>
</table>
</body>
</html>
Llama directamente a las APIs de Apps Script
También puedes usar el código de Apps Script directamente en scriptlets. En este ejemplo, logra el mismo resultado que el ejemplo anterior cargando los datos en el plantilla en sí, en lugar de hacerlo a través de una función separada.
Code.gs
function doGet() {
return HtmlService
.createTemplateFromFile('Index')
.evaluate();
}
Index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<? var data = SpreadsheetApp
.openById('1234567890abcdefghijklmnopqrstuvwxyz')
.getActiveSheet()
.getDataRange()
.getValues(); ?>
<table>
<? for (var i = 0; i < data.length; i++) { ?>
<tr>
<? for (var j = 0; j < data[i].length; j++) { ?>
<td><?= data[i][j] ?></td>
<? } ?>
</tr>
<? } ?>
</table>
</body>
</html>
Envía variables a plantillas
Por último, puedes enviar variables a una plantilla asignándolas como propiedades
del objeto HtmlTemplate
. Una vez
de nuevo, este ejemplo logra el mismo resultado que los ejemplos anteriores.
Code.gs
function doGet() {
var t = HtmlService.createTemplateFromFile('Index');
t.data = SpreadsheetApp
.openById('1234567890abcdefghijklmnopqrstuvwxyz')
.getActiveSheet()
.getDataRange()
.getValues();
return t.evaluate();
}
Index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<table>
<? for (var i = 0; i < data.length; i++) { ?>
<tr>
<? for (var j = 0; j < data[i].length; j++) { ?>
<td><?= data[i][j] ?></td>
<? } ?>
</tr>
<? } ?>
</table>
</body>
</html>
Plantillas de depuración
Puede ser difícil depurar las plantillas porque el código que escribes no se ejecuta directly; En su lugar, el servidor transforma la plantilla en código y, luego, la ejecuta ese código resultante.
Si no es evidente cómo la plantilla interpreta tus {i>scriptlets<i}, dos
de los métodos de depuración
HtmlTemplate
puede ayudarte
entender mejor lo que está pasando.
getCode()
getCode()
muestra un
o una cadena que contiene el código que el servidor crea a partir de la plantilla. Si
registra
código y, luego, pégalo en el editor de secuencias de comandos, puedes ejecutarlo y
depurarlo como de costumbre.
Código de Apps Script
Esta es la plantilla sencilla
que muestra una lista de productos de Google
seguida del resultado de getCode()
:
Code.gs
function myFunction() {
Logger.log(HtmlService
.createTemplateFromFile('Index')
.getCode());
}
Index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<?= 'My favorite Google products:' ?>
<? var data = ['Gmail', 'Docs', 'Android'];
for (var i = 0; i < data.length; i++) { ?>
<b><?= data[i] ?></b>
<? } ?>
</body>
</html>
REGISTRO (EVALUADO)
(function() { var output = HtmlService.initTemplate(); output._ = '<!DOCTYPE html>\n';
output._ = '<html>\n' +
' <head>\n' +
' <base target=\"_top\">\n' +
' </head>\n' +
' <body>\n' +
' '; output._$ = 'My favorite Google products:' ;
output._ = ' '; var data = ['Gmail', 'Docs', 'Android'];
for (var i = 0; i < data.length; i++) { ;
output._ = ' <b>'; output._$ = data[i] ; output._ = '</b>\n';
output._ = ' '; } ;
output._ = ' </body>\n';
output._ = '</html>';
/* End of user code */
return output.$out.append('');
})();
getCodeWithComments()
getCodeWithComments()
es similar a getCode()
, pero muestra el código evaluado como comentarios que
aparecerán en paralelo con la plantilla original.
Explicación del código evaluado
Lo primero que notarás en cualquiera de las muestras de código evaluado es la
Objeto output
creado por el método HtmlService.initTemplate()
Este método
está indocumentado porque solo las plantillas necesitan usarlo. output
es un
un objeto HtmlOutput
especial con dos
propiedades con nombres inusuales, _
y _$
, que son la abreviatura para llamar
append()
y
appendUntrusted()
.
output
tiene una propiedad más especial, $out
, que hace referencia a una propiedad normal
Un objeto HtmlOutput
que no posee estas propiedades especiales. La plantilla
devuelve el objeto normal al final del código.
Ahora que comprendes esta sintaxis, el resto del código debería ser bastante fácil
de seguir. Se agrega contenido HTML fuera de los scriptlets (como la etiqueta b
)
con output._ =
(sin escapar contextual)
y scriptlets se agregan como JavaScript (con o sin escape contextual,
según el tipo de {i>scriptlet<i}).
Ten en cuenta que el código evaluado conserva los números de línea de la plantilla. Si se produce un error mientras se ejecuta el código evaluado, la línea corresponderá al equivalente en la plantilla.
Jerarquía de los comentarios
Debido a que el código evaluado conserva los números de línea, es posible que los comentarios dentro de scriptlets para comentar otros scriptlets y hasta código HTML. Estos Los ejemplos muestran algunos efectos sorprendentes de los comentarios:
<? var x; // a comment ?> This sentence won't print because a comment begins inside a scriptlet on the same line. <? var y; // ?> <?= "This sentence won't print because a comment begins inside a scriptlet on the same line."; output.append("This sentence will print because it's on the next line, even though it's in the same scriptlet.”) ?> <? doSomething(); /* ?> This entire block is commented out, even if you add a */ in the HTML or in a <script> */ </script> tag, <? until you end the comment inside a scriptlet. */ ?>