Servizio HTML: HTML basato su modello

Puoi combinare codice Apps Script e HTML per produrre pagine dinamiche con impegno. Se hai utilizzato un linguaggio di creazione di modelli che mescola codice e HTML, ad esempio PHP, ASP o JSP, la sintassi dovrebbe essere familiare.

Scriptlet

I modelli Apps Script possono contenere tre tag speciali, chiamati scriptlet. Interno uno scriptlet, puoi scrivere qualsiasi codice che funzioni in un normale Apps Script file: gli scriptlet possono chiamare funzioni definite in altri file di codice, fare riferimento variabili globali o utilizzare una qualsiasi delle API Apps Script. Puoi anche definire funzioni e variabili all'interno degli scriptlet, con l'avvertenza che non possono chiamato da funzioni definite nei file di codice o in altri modelli.

Se incolli l'esempio riportato di seguito nell'editor di script, i contenuti del Verrà visualizzato il tag <?= ... ?> (uno scriptlet di stampa) corsivo. Il codice in corsivo viene eseguito sul server prima che la pagina venga pubblicata. all'utente. Poiché il codice scriptlet viene eseguito prima della pubblicazione della pagina, può essere eseguito una sola volta per pagina; a differenza di JavaScript lato client o Apps Script che chiami tramite google.script.run, gli scriptlet non possono di nuovo in esecuzione dopo il caricamento della pagina.

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>

Tieni presente che la funzione doGet() per l'HTML basato su modelli è diversa dagli esempi per creare e pubblicare codice HTML di base. La funzione mostrato qui genera l'oggetto HtmlTemplate dall'HTML , quindi chiama evaluate() per eseguire gli scriptlet e convertire il modello in HtmlOutput che lo script possono essere mostrati all'utente.

Scriptlet standard

Gli scriptlet standard, che utilizzano la sintassi <? ... ?>, eseguono il codice senza di inviare esplicitamente i contenuti alla pagina. Tuttavia, come mostra questo esempio, risultato del codice all'interno di uno scriptlet può comunque influire sui contenuti HTML al di fuori dello 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>

Stampa degli scriptlet

La stampa degli scriptlet, che utilizzano la sintassi <?= ... ?>, restituisce i risultati di il codice nella pagina tramite l'utilizzo di caratteri di escape contestuale.

L'utilizzo di escape contestuale significa che Apps Script tiene traccia del contesto dell'output. Sulla pagina: all'interno di un attributo HTML, in un tag script lato client altrove e aggiunge automaticamente caratteri di escape per proteggere gli utenti dagli attacchi cross-site scripting (XSS).

In questo esempio, il primo scriptlet di stampa restituisce una stringa direttamente; è seguito da uno scriptlet standard che configura un array e un loop, seguito da un altro scriptlet di stampa per restituire i contenuti dell'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>

Tieni presente che uno scriptlet di stampa restituisce solo il valore della sua prima istruzione; eventuali istruzioni rimanenti si comportano come se fossero contenute in un scriptlet. Quindi, ad esempio, solo lo scriptlet <?= 'Hello, world!'; 'abc' ?> visualizza la scritta "Hello, world!"

Stampa forzata degli scriptlet

Gli scriptlet per la stampa forzata, che utilizzano la sintassi <?!= ... ?>, sono come la stampa gli scriptlet, tranne che per evitare l'utilizzo di caratteri di escape contestuali.

L'utilizzo di escape contestuale è importante se lo script consente l'input dell'utente non attendibile. Di devi eseguire la stampa forzata se l'output dello scriptlet viene intenzionalmente contiene codice HTML o script da inserire esattamente come specificato.

Come regola generale, utilizza gli scriptlet di stampa anziché quelli a stampa forzata a meno che tu non sappia di dover stampare il codice HTML o JavaScript invariato.

Codice di Apps Script negli scriptlet

Gli scriptlet non sono limitati all'esecuzione di JavaScript normale. puoi anche utilizzare qualsiasi delle tre tecniche seguenti per concedere ai tuoi modelli l'accesso ad Apps Script e i dati di Google Cloud.

Ricorda tuttavia che, poiché il codice del modello viene eseguito prima della pubblicazione della pagina, all'utente, queste tecniche possono indirizzare solo i contenuti iniziali di una pagina. Per accedere per i dati di Apps Script da una pagina in modo interattivo, utilizza google.script.run.

Chiamata a funzioni Apps Script da un modello

Gli scriptlet possono chiamare qualsiasi funzione definita in un file di codice o in una libreria di Apps Script. Questo esempio mostra un modo per estrarre i dati da un foglio di lavoro a un modello creare una tabella HTML a partire dai dati.

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>

Chiamata diretta alle API Apps Script

Puoi anche utilizzare il codice di Apps Script direttamente negli scriptlet. Questo esempio ottiene lo stesso risultato dell'esempio precedente caricando i dati nella anziché tramite una funzione separata.

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>

Push delle variabili ai modelli

Infine, puoi eseguire il push delle variabili in un modello assegnandole come proprietà. dell'oggetto HtmlTemplate. Una volta di nuovo, questo esempio ottiene lo stesso risultato degli esempi precedenti.

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>

Modelli di debug

Il debug dei modelli può essere difficile perché il codice che scrivi non viene eseguito direttamente; il server trasforma il tuo modello in codice, quindi esegue del codice risultante.

Se il modo in cui il modello interpreta i tuoi scriptlet non è chiaro, i metodi di debug Il corso HtmlTemplate può aiutarti a capire meglio cosa sta succedendo.

getCode()

getCode() restituisce un stringa contenente il codice che il server crea a partire dal modello. Se registra il codice, quindi incollalo nell'editor di script, puoi eseguirlo esegui il debug come al solito il codice Apps Script.

Ecco un semplice modello che mostra di nuovo un elenco di prodotti Google, seguito dal risultato di 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>

LOG (VALUTATO)

(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() è simile a getCode(), ma restituisce il codice valutato come commenti che vengono visualizzati affiancati al modello originale.

Presentazione del codice valutato

La prima cosa che noterai in entrambi gli esempi di codice valutato è Oggetto output creato con il metodo HtmlService.initTemplate(). Questo metodo non è documentato perché è necessario utilizzarlo solo dai modelli. output è un oggetto HtmlOutput speciale con due proprietà con nomi insoliti, _ e _$, che sono un'abbreviazione per chiamare append() e appendUntrusted().

output ha un'altra proprietà speciale, $out, che si riferisce a una normale proprietà HtmlOutput oggetto che non possiede queste proprietà speciali. Il modello restituisce l'oggetto normale alla fine del codice.

Ora che hai compreso questa sintassi, il resto del codice dovrebbe essere abbastanza semplice da seguire. Vengono aggiunti i contenuti HTML al di fuori degli scriptlet (come il tag b) utilizzando output._ = (senza carattere di escape contestuale), e gli scriptlet vengono aggiunti come JavaScript (con o senza escape contestuale, a seconda del tipo di scriptlet).

Tieni presente che il codice valutato conserva i numeri di riga del modello. Se ricevi un errore durante l'esecuzione del codice valutato, la riga corrisponderà contenuti equivalenti nel modello.

Gerarchia dei commenti

Poiché il codice valutato conserva i numeri di riga, è possibile che i commenti all'interno di scriptlet per commentare altri scriptlet e persino codice HTML. Questi esempi mostrano alcuni effetti sorprendenti dei commenti:

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