HTML Hizmeti: Şablonlu HTML

Minimum çabayla dinamik sayfalar oluşturmak için Apps Komut Dosyası kodu ile HTML'yi bir arada kullanabilirsiniz. Kod ile HTML'yi bir araya getiren bir şablon dili (PHP, ASP veya JSP gibi) kullandıysanız söz diziminin tanıdık olması gerekir.

Komut Dosyaları

Apps Komut Dosyası şablonları, komut dosyası adı verilen üç özel etiket içerebilir. Bir komut dosyası içinde, normal bir Apps Komut Dosyası dosyasında çalışacak herhangi bir kodu yazabilirsiniz: Komut dosyası uygulamaları diğer kod dosyalarında tanımlanan işlevleri çağırabilir, genel değişkenlere başvurabilir veya Apps Komut Dosyası API'lerinden herhangi birini kullanabilir. Kod dosyalarında veya diğer şablonlarda tanımlanan işlevler tarafından çağrılamayacağına dikkat ederek, komut dosyaları içinde işlevleri ve değişkenleri bile tanımlayabilirsiniz.

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 yazılmış 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ışabilir. google.script.run üzerinden çağırdığınız istemci taraflı JavaScript veya Apps Komut Dosyası 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, ardından komut dosyalarını çalıştırmak 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 açıkça içerik çıkarmadan 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 dosyalarını yazdırma

<?= ... ?> söz dizimini kullanan komut dosyası yazdırma işlemleri, bağlamsal çıkış yöntemini kullanarak kodlarının sonuçlarını sayfaya yönlendirir.

Bağlamsal çıkış, Apps Komut Dosyası'nın sayfadaki çıkış bağlamını (HTML özelliği içinde, istemci tarafı script etiketinin içinde veya başka herhangi bir yerde) izlediğ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 çıktısı verir. Bunu da dizi ve döngü oluşturan standart bir komut dosyası izler. Ardından, dizinin içeriğini üreten başka bir yazdırma komut dosyası izler.

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. Dolayısıyla, örneğin <?= 'Hello, world!'; 'abc' ?> komut dosyası yalnızca "Hello, world!"

Komut dosyalarını zorla yazdırma

<?!= ... ?> söz dizimini kullanan komut dosyaları, zorla yazdırma komut dosyaları gibidir. Tek fark, bağlamsal kod dışına alma işleminden kaçınmalarıdır.

Komut dosyanız güvenilir olmayan kullanıcı girişine izin veriyorsa bağlamsal çıkış önemlidir. Buna karşılık, komut dosyası çıktınız, tam olarak belirtildiği şekilde eklemek istediğiniz HTML'yi veya komut dosyalarını bilinçli olarak 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ındaki Apps Komut Dosyası kodu

Komut dosyası uygulamaları normal JavaScript çalıştırmakla sınırlı değildir. Şablonlarınızın Apps Komut Dosyası verilerine erişmesine izin vermek için aşağıdaki üç teknikten birini de kullanabilirsiniz.

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

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

Komut dosyası uygulamaları, Apps Komut Dosyası kod dosyasında veya kitaplığında tanımlanan herhangi bir işlevi çağırabilir. Bu örnekte, bir e-tablodan bir şablona veri çekmenin ve ardından verilerden bir 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 Komut Dosyası API'lerini doğrudan çağırma

Apps Komut Dosyası kodunu doğrudan komut dosyalarında da kullanabilirsiniz. Bu örnekte, verileri ayrı bir işlev aracılığıyla yüklemek yerine şablonun kendi içinde yükleyerek önceki örnekle aynı sonucu elde edersiniz.

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 aktarma

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

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ğinden şablonlar hata ayıklaması zor olabilir. Bunun yerine sunucu, şablonunuzu koda dönüştürür ve ardından oluşturulan kodu yürütür.

Şablonun komut dosyalarınızı nasıl yorumladığı tam olarak anlaşılmıyorsa HtmlTemplate sınıfındaki iki hata ayıklama yöntemi, sorunun ne 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 kaydeder ve ardından komut dosyası düzenleyiciye yapıştırırsanız normal Apps Komut Dosyası kodunda olduğu gibi kodu çalıştırabilir ve hata ayıklama yapabilirsiniz.

Aşağıda, Google ürünlerinin listesini ve ardından getCode() sonucunun sonucunu gösteren basit şablonu tekrar görebilirsiniz:

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>

GÜNLÜK (DEĞERLENDİRİLDİ)

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

Değerlendirilen kodların üzerinden geçme

Her iki değerlendirilen kod örneğinde de ilk fark edeceğiniz şey, HtmlService.initTemplate() yöntemi tarafından oluşturulan örtülü output nesnesidir. Bu yöntem yalnızca şablonların kullanması gerektiği için belgelenmemiştir. 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 sonundaki normal nesneyi döndürür.

Bu söz dizimini anladığınıza göre, kodun geri kalanı kolayca takip edilebilir. Komut dosyası uygulamalarının dışındaki HTML içeriği (b etiketi gibi), output._ = kullanılarak eklenir (içeriğe dayalı çıkışsız) ve komut dosyaları, JavaScript olarak eklenir (komut dosyası türüne bağlı olarak, bağlamsal çıkış karakteriyle veya bu olmadan).

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

Yorum 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. Bu örneklerde, yorumların birkaç şaşırtıcı etkisi görülüyor:

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