HTML Hizmeti: Şablonlu HTML

Az çabayla dinamik sayfalar oluşturmak için Apps Komut Dosyası kodunu ve HTML'yi birlikte kullanabilirsiniz. PHP, ASP veya JSP gibi kod ile HTML'yi karıştıran bir şablonlama dili kullandıysanız söz dizimi size tanıdık gelecektir.

Komut Dosyaları

Apps Script şablonları, komut dosyası küçük programları adı verilen üç özel etiket içerebilir. Komut dosyacığınıza normal bir Apps Komut Dosyası dosyasında çalışacak herhangi bir kod yazabilirsiniz: Komut dosyacıklar diğer kod dosyalarında tanımlanan işlevleri çağırabilir, genel değişkenlere referans verebilir veya Apps Komut Dosyası API'lerinden herhangi birini kullanabilir. Hatta komut dosyalarında işlevleri ve değişkenleri tanımlayabilirsiniz. Ancak bunların kod dosyalarında veya diğer şablonlarda tanımlı işlevler tarafından çağrılamayacağına dikkat edin.

Aşağıdaki örneği komut dosyası düzenleyiciye yapıştırırsanız <?= ... ?> etiketinin (yazdırma komut dosyası) içeriği italik yazı tipiyle görünür. İtalik olarak yazılmış bu kod, sayfa kullanıcıya sunulmadan önce sunucuda çalışır. Komut dosyası kodu, sayfa sunulmadan önce yürütüldüğü için sayfa başına yalnızca bir kez çalıştırılabilir. google.script.run aracılığıyla çağırdığınız istemci tarafı JavaScript veya Apps Script işlevlerinin aksine, komut dosyaları sayfa yüklendikten sonra tekrar yürütülemez.

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>

Şablonlu HTML için doGet() işlevinin temel HTML oluşturma ve sunma örneklerinden farklı olduğunu unutmayın. Burada gösterilen işlev, HTML dosyasından bir HtmlTemplate nesnesi oluşturur ve ardından komut dosyalarını yürütmek ve şablonu komut dosyasının kullanıcıya sunabileceği bir HtmlOutput nesnesine dönüştürmek için evaluate() yöntemini çağırır.

Standart komut dosyaları

<? ... ?> söz dizimini kullanan standart komut dosyaları, sayfaya içerik açıkça göndermeden kodu yürütür. Ancak, bu örnekte gösterildiği gibi, bir komut dosyası içindeki kodun sonucu, komut dosyası dışındaki HTML içeriğini yine de etkileyebilir:

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>

Komut dosyası yazdırma

<?= ... ?> söz dizimini kullanan baskı komut dosyaları, kodlarının sonuçlarını bağlama dayalı kaçış karakteri kullanarak sayfaya gönderir.

Bağlamsal kaçış, Apps Script'in sayfadaki çıktının bağlamını (HTML özelliği içinde, istemci tarafı script etiketi içinde veya başka bir yerde) takip ettiği ve siteler arası komut dosyası çalıştırma (XSS) saldırılarına karşı koruma sağlamak için otomatik olarak kaçış karakterleri eklediği anlamına gelir.

Bu örnekte, ilk yazdırma komut dosyası doğrudan bir dize döndürür. Ardından bir dizi ve döngü oluşturan standart bir komut dosyası, ardından da dizinin içeriğini döndüren başka bir yazdırma komut dosyası gelir.

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>

Yazdırma komut dosyasının yalnızca ilk ifadesinin değerini çıkardığını unutmayın. Geri kalan tüm ifadeler, standart bir komut dosyası içindeymiş gibi davranır. Örneğin, <?= 'Hello, world!'; 'abc' ?> komut dosyası yalnızca "Merhaba dünya!" yazdırır.

Komut dosyalarını zorla yazdırma

<?!= ... ?> söz dizimini kullanan zorla yazdırma komut dosyaları, bağlama göre kaçış karakteri kullanmamaları dışında yazdırma komut dosyalarına benzer.

Komut dosyanız güvenilir olmayan kullanıcı girişine izin veriyorsa bağlamsal çıkış önemlidir. Buna karşılık, komut dosyanızın çıkışı tam olarak belirtildiği gibi eklemek istediğiniz HTML veya komut dosyaları içeriyorsa zorla yazdırmanız gerekir.

Genel bir kural olarak, HTML veya JavaScript'i değiştirmeden yazdırmanız gerektiğini bilmiyorsanız komut dosyalarını zorla yazdırmak yerine komut dosyası uygulamalarını kullanın.

Komut dosyalarında Apps Komut Dosyası kodu

Komut dosyaları, normal JavaScript çalıştırmakla sınırlı değildir. Şablonlarınıza Apps Script verilerine erişim vermek için aşağıdaki üç teknikten herhangi birini de kullanabilirsiniz.

Ancak şablon kodu sayfa kullanıcıya sunulmadan önce yürütüldüğü için bu tekniklerin yalnızca bir sayfaya ilk içeriği besleyebileceğini unutmayın. Bir sayfadaki Apps Script verilerine etkileşimli olarak erişmek için bunun yerine google.script.run API'yi kullanın.

Apps Komut Dosyası işlevlerini şablondan çağırma

Komut dosyaları, Apps Komut Dosyası kod dosyasında veya kitaplığında tanımlanan tüm işlevleri çağırabilir. Bu örnekte, e-tablodan bir şablona veri çekmenin ve ardından verilerden HTML tablosu oluşturmanın bir yolu gösterilmektedir.

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>

Apps Script API'lerini doğrudan çağırma

Apps Komut Dosyası kodunu doğrudan komut dosyalarında da kullanabilirsiniz. Bu örnekte, veriler ayrı bir işlev yerine şablonun içine yükleyerek önceki örnekle aynı sonuç elde edilir.

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>

Değişkenleri şablonlara gönderme

Son olarak, değişkenleri HtmlTemplate nesnesinin özellikleri olarak atayarak şablona gönderebilirsiniz. Bu örnekte de önceki örneklerle aynı sonuç elde edilir.

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>

Hata ayıklama şablonları

Yazdığınız kod doğrudan yürütülmediği için şablonlarda hata ayıklama işlemi zor olabilir. Bunun yerine sunucu, şablonunuzu koda dönüştürür ve elde edilen kodu yürütür.

Şablonun komut dosyalarınızı nasıl yorumladığı net değilse HtmlTemplate sınıfındaki iki hata ayıklama yöntemi, neler olduğunu daha iyi anlamanıza yardımcı olabilir.

getCode()

getCode(), sunucunun şablondan oluşturduğu kodu içeren bir dize döndürür. Kodu günlüğe kaydedip komut dosyası düzenleyiciye yapıştırırsanız normal Apps Komut Dosyası kodları gibi çalıştırabilir ve hata ayıklayabilirsiniz.

Aşağıda, Google ürünlerinin listesini ve ardından getCode() sonucunu gösteren basit şablon verilmiştir:

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 (DEĞERLENDİRİLEN)

(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(), getCode()'a benzer ancak değerlendirilen kodu orijinal şablonla yan yana görünen yorumlar olarak döndürür.

Değerlendirilen kodu inceleme

Değerlendirilen kod örneklerinin her birinde ilk fark edeceğiniz şey, HtmlService.initTemplate() yöntemi tarafından oluşturulan örtülü output nesnesi olacaktır. Yalnızca şablonların kullanması gerektiği için bu yöntemle ilgili doküman yoktur. output, append() ve appendUntrusted() çağrılarının kısaltılmış hali olan _ ve _$ adlı iki özelliğe sahip özel bir HtmlOutput nesnesidir.

output öğesinin bir tane daha özel özelliği daha vardır: $out. Bu özellik, bu özel özelliklere sahip olmayan normal bir HtmlOutput nesnesini belirtir. Şablon, kodun sonunda bu normal nesneyi döndürür.

Bu söz dizimini anladığınıza göre, kodun geri kalanını takip etmek oldukça kolay olacaktır. Komut dosyası dışındaki HTML içeriği (b etiketi gibi), output._ = kullanılarak (bağlamdan kaçınma olmadan) eklenir ve komut dosyaları JavaScript olarak eklenir (komut dosyası türüne bağlı olarak bağlamdan kaçınma ile veya olmadan).

Değerlendirilen kodda şablondaki satır numaralarının korunduğunu unutmayın. Değerlendirilmiş kodu çalıştırırken hata alırsanız satır, şablondaki eşdeğer içeriğe karşılık gelir.

Yorumların hiyerarşisi

Değerlendirilen kod satır numaralarını koruduğundan, komut dosyası içindeki yorumların diğer komut dosyaları ve hatta HTML kodları için yorum yapması mümkündür. Aşağıdaki örneklerde, yorumların şaşırtıcı etkilerinden bazıları gösterilmektedir:

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