Serviço HTML: HTML a partir de modelo

Você pode combinar código e HTML do Apps Script para produzir páginas dinâmicas com o mínimo esforço de Se você usou uma linguagem de modelagem que mistura código e HTML, como a sintaxe deve parecer familiar para PHP, ASP ou PHP.

Scriptlets

Os modelos do Apps Script podem conter três tags especiais, chamadas "scriptlets". Interior um scriptlet, você pode escrever qualquer código que funcione em um Apps Script normal file: os scriptlets podem chamar funções definidas em outros arquivos de código, referenciar variáveis globais ou usar uma das APIs do Apps Script. É possível até definir e variáveis dentro de scriptlets, com a ressalva de que não podem ser chamados por funções definidas em arquivos de código ou outros modelos.

Se você colar o exemplo abaixo no editor de script, o conteúdo da A tag <?= ... ?> (um scriptlet de impressão) vai aparecer em itálico. Esse código em itálico é executado no servidor antes da veiculação da página para o usuário. Como o código scriptlet é executado antes da exibição da página, só pode ser executado uma vez por página. diferentemente do JavaScript do lado do cliente ou do Apps Script chamadas por meio de google.script.run, os scripts não podem será executado novamente após o carregamento da 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>

A função doGet() para HTML modelo é diferente dos exemplos para criar e exibir HTML básico. A função mostrado aqui gera uma Objeto HtmlTemplate do HTML arquivo e, em seguida, chama evaluate() para execute os scriptlets e converta o modelo em um HtmlOutput que o script que podem ser veiculados para o usuário.

Scriptlets padrão

Scriptlets padrão, que usam a sintaxe <? ... ?>, executam o código sem gerando explicitamente conteúdo para a página. No entanto, como mostra o exemplo, result do código dentro de um scriptlet ainda pode afetar o conteúdo HTML fora do 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>

Como imprimir scripts

A impressão de scriptlets, que usam a sintaxe <?= ... ?>, gera os resultados de o código na página usando escape contextual.

Escape contextual significa que o Apps Script monitora o contexto da saída na página: em um atributo HTML, em uma tag script do lado do cliente ou em qualquer outro lugar, e adiciona automaticamente caracteres de escape. para proteção contra ataques de scripting em vários locais (XSS).

Neste exemplo, o primeiro scriptlet de impressão gera uma string diretamente. ele é seguido por um scriptlet padrão que configura uma matriz e um loop, seguidos por outro scriptlet de impressão para gerar o conteúdo da matriz.

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>

Um scriptlet de impressão emite apenas o valor da primeira instrução. as instruções restantes se comportam como se estivessem contidas em um padrão scriptlet. Por exemplo, o scriptlet <?= 'Hello, world!'; 'abc' ?> exibe "Hello, world!"

Como forçar a impressão de scriptlets

Os scriptlets de impressão forçada, que usam a sintaxe <?!= ... ?>, são como imprimir scriptlets, exceto que eles evitam escape contextual.

O escape contextual é importante se o script permite entradas não confiáveis do usuário. De será necessário forçar a impressão se a saída do scriptlet for intencionalmente contém HTML ou scripts que você deseja inserir exatamente como especificado.

Como regra geral, use a impressão de scriptlets em vez de forçar a impressão de scriptlets. a menos que você saiba que precisa imprimir HTML ou JavaScript inalterado.

Código do Apps Script em scriptlets

Os scriptlets não estão restritos à execução de JavaScript normal. você também pode usar qualquer das três técnicas a seguir para dar aos modelos acesso ao Apps Script dados.

Lembre-se, porém, que, como o código do modelo é executado antes da exibição da página, para o usuário, essas técnicas só podem alimentar o conteúdo inicial da página. Para acessar dados de uma página do Google Apps Script de forma interativa, use google.script.run.

Como chamar funções do Apps Script usando um modelo

Os scripts podem chamar qualquer função definida em um arquivo ou biblioteca de código do Apps Script. Este exemplo mostra uma forma de extrair dados de uma planilha para um modelo e construa uma tabela HTML a partir dos dados.

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>

Chamar APIs do Apps Script diretamente

Também é possível usar o código do Apps Script diretamente nos scriptlets. Neste exemplo, realiza o mesmo resultado do exemplo anterior, carregando os dados no o modelo em si, e não por meio de uma função 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>

Como enviar variáveis para modelos

Por fim, é possível enviar variáveis para um modelo atribuindo-as como propriedades do objeto HtmlTemplate. Uma vez novamente, este exemplo alcança o mesmo resultado dos exemplos 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>

Modelos de depuração

A depuração dos modelos pode ser um desafio, porque o código que você escreve não é executado diretamente Em vez disso, o servidor transforma o modelo em código e o executa o código resultante.

Se não for óbvio como o modelo está interpretando seus scriptlets, duas de depuração na classe A turma HtmlTemplate pode ajudar você a entender melhor o que está acontecendo.

getCode()

getCode() retorna um string que contém o código que o servidor cria a partir do modelo. Se você registre o código, cole-o no editor de script, execute-o e depurar normalmente código do Apps Script.

Este é o modelo simples que mostra novamente uma lista de produtos do Google seguido pelo 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 (AVALIADO)

(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() é semelhante a getCode(), mas retorna o código avaliado como comentários que aparecem lado a lado com o modelo original.

Orientações sobre o código avaliado

A primeira coisa que você nota em um exemplo de código avaliado é a abordagem implícita Objeto output criado pelo método HtmlService.initTemplate(). Esse método não é documentado porque apenas os próprios modelos precisam usá-lo. output é um objeto HtmlOutput especial com dois propriedades com nomes incomuns, _ e _$, que são abreviações de chamadas append() e appendUntrusted()

output tem mais uma propriedade especial, $out, que se refere a uma classe Objeto HtmlOutput que não tem essas propriedades especiais. O modelo retorna esse objeto normal ao final do código.

Agora que você entende essa sintaxe, o restante do código será bastante fácil a serem seguidas. O conteúdo HTML fora dos scriptlets (como a tag b) é anexado. usando output._ = (sem escape contextual), e scriptlets são anexados como JavaScript (com ou sem escape contextual, dependendo do tipo de scriptlet).

O código avaliado preserva os números de linha do modelo. Se você receber um erro ao executar o código avaliado, a linha corresponderá conteúdo equivalente no modelo.

Hierarquia de comentários

Como o código avaliado preserva os números de linha, é possível que comentários dentro dos scriptlets para comentar outros scriptlets e até mesmo códigos HTML. Esses os exemplos mostram alguns efeitos surpreendentes dos comentários:

<? 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. */ ?>