Template Engine Pada Node Js - CRUDPRO

Template Engine Pada Node Js

Pug.js adalah template engine pada node Js. Ini berarti Anda dapat menulis kode Pug yang jauh lebih sederhana yang dapat dipahami oleh browser Anda. Kompiler Pug mengkompilasi ini menjadi kode HTML. Tapi mengapa tidak menulis kode HTML di tempat pertama?

Pug memiliki fitur canggih seperti condition, loop, include, mixin, dll. yang dapat merender kode HTML berdasarkan input pengguna atau data referensi. Pug juga mendukung JavaScript secara native, sehingga Anda dapat menggunakan ekspresi JavaScript untuk memformat kode HTML Anda.

Aplikasi akan menjadi template email untuk mengirim email yang disesuaikan untuk pengguna tertentu. Anda dapat menggunakan Pug untuk membuat template email dengan variabel yang dapat dimodifikasi berdasarkan pengguna yang menerima email tersebut. Sebelum mengirim email, Anda dapat menggunakan data pengguna Anda untuk mengkompilasi Pug ke dalam kode HTML dan mengisi kekosongan di mana informasi dinamis diperlukan. Percayalah, ini akan menghemat banyak waktu Anda.

Ada banyak aplikasi yang perlu menghasilkan kode HTML di server atau browser, dan Pug sangat cocok dengan lingkungan seperti itu. Mari kita mulai.

Pug.js, sesuai namanya, adalah library JavaScript. Jadi Anda bisa menjalankannya di browser Anda atau di node.js. Berikut adalah beberapa contoh menggunakan node.js.

Pug menyediakan dua paket npm, yaitu viz.pug dan pug-cli. pug adalah paket generik dan pug-cli adalah antarmuka baris perintah untuk mengkompilasi kode pug dari baris perintah ke kode HTML tanpa menulis kode JavaScript. Ini sangat mudah sehingga kita mulai dengan pug-cli.

Oleh karena itu, Anda perlu menginstalnya secara global untuk mengakses perintah Pug dari command prompt atau terminal, jadi mari kita instal paket pug-cli menggunakan perintah npm install -g pug-cli, -g. File pug diakhiri dengan ekstensi .pug dan dikompilasi menjadi file dengan ekstensi .html

Jika Anda memiliki file index.pug di folder Anda, buka terminal di sana dan jalankan perintah pug index.pug untuk mengkompilasi index.pug menjadi file index.html. Jika Anda memiliki folder terpisah untuk semua file .pug (misalnya, src), Anda harus menggunakan perintah pug src untuk meletakkan semua file .html yang dikompilasi dalam folder yang sama. Saya suka semua file yang dikompilasi untuk ditempatkan di folder terpisah seperti dist. Oleh karena itu, saya menggunakan perintah pug src --pretty --outdist. Anda dapat mengetahui lebih lanjut tentang flag perintah pugCLI dengan mengunjungi halaman repositori GitHub (https://github.com/pugjs/pug-cli). Mari kita lihat seperti apa kode pug itu.

doctype html
html
    head
        //- Invisible comment in head section which will not appear in rendered html
        // Visible comment in head block which will appear in rendered html
        
        <!-- html comment will work fine too, but I don't get the idea! -->
    body
        //-
            Block invisible comment in body section
            which will not appear in rendered html
        //  "Comment can start from this line as well."
            Visible comment in head block 
            which will appear in rendered html.

code-structure.pug

Seperti yang Anda lihat dari atas, itu tidak masuk akal untuk pemula. Tapi beri aku kesempatan untuk menjelaskannya. Untuk html doctype, Pug adalah , html, head dan body adalah tag yang biasa dikompilasi ke <html> </ html>, <head> </head>, dan <body> </body>. Seperti Python, Pug menggunakan tab untuk membuat blok kode. Jadi tag head dan body berada di dalam blok tab html, jadi head dan body adalah saudara kandung, tetapi termasuk dalam tag html. Kebanyakan hal dijelaskan dalam bentuk komentar dalam kode itu sendiri, jadi baca kode dan komentar dengan cermat mulai sekarang.

Kompilasi kode di atas terlihat seperti ini:

<!DOCTYPE html>
<html>
  <head>
    <!-- Visible comment in head block which will appear in rendered html--><!-- html comment will work fine too, but I don't get the idea! -->
  </head>
  <body>
    <!--  "Comment can start from this line as well."
    Visible comment in head block 
    which will appear in rendered html.
    -->
  </body>
</html>

code-structure.html

Setelah ini semuanya begitu sederhana, luangkan waktu sejenak untuk memahami bagaimana hal itu terjadi.

Kode HTML terutama tentang tag, atribut, dan teks. Oleh karena itu, Pug terutama berfokus padanya dan dapat dibuat menggunakan data dinamis. Mari kita lihat cara kerja tag dan teks. Jangan khawatir, Pug menggunakan tag HTML yang sama.

//- Simple inline paragraph text
p I am inline text

//- These two pipes will create 2 new lines
|
|
//- This will add empty line between above code and below code
//-  
    Literal html will also work.
    Pug will simply ignore any text starting with `<` left angle bracket.
    Hence you need to manually close tag.
<p align="justify">I am literal html code </p>

//-
    Unlike block comments, we can not add more text in new lines.
    Because any text inside a tag is valid pug code and pug will try to compile it.
    Hence, we need to use `.` dot or `|` pipe character.
//- Using pipe character in every line, we can span text over multiple lines.
//- Pipe character will treat text as normal text and add new line.
//- But we can mix any valid pug code in new line using this style.
p
    | Hello World!
    | I am Pug, your buddy to write simple HTML templates.
    em Let's explore the world, shall we?
    | Very nice to meet you :)

//- To create block of text with auto line break, we can use `.` character.
//- There should not be any space between tag name and `.` dot character.
//- Any text in this block is not processed by Pug, hence you need to use HTML literal unline previous example.
//- Dot character must start right after the tag name, 
    or after the closing parenthesis `)` if the tag has attributes.
p.
    Hello World!
    I am Pug, your buddy to write simple HTML templates.
    <em>Let's explore the world, shall we?</em>
    Very nice to meet you :)
//- Using `.` dot character, we can make use of block of text to write style or script code,
//- since, all text in this block will not be processed by pug.
script.
    if(window.navigator.geolocation){
        console.log("Geolocation available!")
    }
    else{
        console.warn("Geolocation not available!")
    }
style(type="text/css").
    html, body{
        padding: 0;
        margin: 0;
    }

//- We can also create a dot block of plain text after other tags within the parent tag.
div
    p Hello World! I am in a paragraph. I am optional here :(
    .
        Hey there!
        I am in a block but in `div` tag.
        Because, dot without a tag will put me in parent tag.

//- Pug provided tag interpolation.
//- syntax for tag interploation is like `#[tagName content]`
p
    b Hi there! I am #[strong John Doe].

//- Pug provided `:` operator to make block expression into inline.
p: b Hi there! I am inline #[strong John Doe].

//- Pug automatically closes self closing tags like `img`, `br`, `link` etc.
//- But to force pug to self close a custom tag is to put `/` forward slash at the end of the tag
double-break/

tags.pug

<p align="justify">I am inline text</p>
<p align="justify">I am literal html code </p>
<p align="justify">
  Hello World!
  I am Pug, your buddy to write simple HTML templates.<em>Let's explore the world, shall we?</em>Very nice to meet you :)
</p>
<p align="justify">
  Hello World!
  I am Pug, your buddy to write simple HTML templates.
  <em>Let's explore the world, shall we?</em>
  Very nice to meet you :)
</p>
<script>
  if(window.navigator.geolocation){
      console.log("Geolocation available!")
  }
  else{
      console.warn("Geolocation not available!")
  }
</script>
<style type="text/css">
  html, body{
      padding: 0;
      margin: 0;
  }
  
</style>
<div>
  <p align="justify">Hello World! I am in a paragraph. I am optional here :(</p>Hey there!
  I am in a block but in `div` tag.
  Because, dot without a tag will put me in parent tag.
  
</div>
<p align="justify"><b>Hi there! I am <strong>John Doe</strong>.</b></p>
<p align="justify"><b>Hi there! I am inline <strong>John Doe</strong>.</b></p>
<double-break/>

tags.html

Menulis atribut di Pug bisa sedikit rumit. Tapi saya yakin itu tidak terlalu sulit untuk dipahami bahkan setelah membaca komentar.

//- An attribute but be added inside parentheses.
//- They might look similar to plain HTML attributes but value of an attribute is actually a JavaScript exprssion.
//- Below is string used as JavaScript expression.
a(href="https://google.com") google.com

//- An example of actual JavaScript expression.
//- You can separate multiple attributes using `,` or ` ` space character.
a(href="https://" + "google" +  ".com", target="_blank") google.com

//- Using inline JavaScript variable
//- Read more about inline JavaScript code in `inline JavaScript` topic below.
//- Below, we used ` ` space character to separate multiple attributes
- var srcLink = "https://design.google.com/logo.png"
img(src=srcLink alt="google logo")

//- using ES6 string interpolcation.
- var size = "medium"
img(src=`https://design.google.com/logo-${size}.png` alt="google logo")

//- Using boolean value.
input(type='checkbox' checked)
input(type='checkbox' checked=true)
input(type='checkbox' checked=false)

//- If you have huge list of attributes, you can span attributes over multiple lines.
//- We can also use single-quotes `''` or double-quotes `""` to wrap attribute name. 
input(
    type="text"
    "name"="username"
    'placeholder'="Enter your username"
    readonly=false
    required
)

//- Pug.js escapes all attributes by default
img(src="<code></code>")

//- To prevent attribute value escape, use `!=` syntax instead of `=` for attribute value assignment
img(src!="<code></code>")

//- Adding style attribute is just like any other attribute using string value.
a(href="some-link", style="color:red;font-size:12px;") Click Me!
//- But Pug.js provides `Object` literal syntax as well.
a(href="some-link", style={color: "Red", "font-size": "12px"}) Click Me!

//- Adding class attribute is also just like any other attribute using string value.
a(href="some-link", class="link special") Click Me!
//- But Pug.js provides `Object` and `Array` syntax as well.
a(href="some-link", class=["link", "special"]) Click Me!
a(href="some-link", class=["link", "special"] class="general") Click Me!
a(href="some-link", class={link: true, special: true, hidden: false}) Click Me!
//- Class literal is also valid
button.btn.btn-sm Click Me
p.simple.
    Hello World!
    I am in a block
.general.div I am in default tag is `div`.
//- Like class literal, id literal is also valid.
a#main-link Click Me!
a.link#main-link Click Me!
#main-link I am in default tag is `div`.

attributes.pug

Sekarang kita akan memformat kodenya sedikit sehingga kita dapat membandingkan kode Pug dengan HTML.

<a href="https://google.com">google.com</a>
<a href="https://google.com" target="_blank">google.com</a>
<img src="https://design.google.com/logo.png" alt="google logo" />
<img src="https://design.google.com/logo-medium.png" alt="google logo" />
<input type="checkbox" checked="checked" />
<input type="checkbox" checked="checked" />
<input type="checkbox" />
<input type="text" name="username" placeholder="Enter your username" required="required" />
<img src="&lt;code&gt;&lt;/code&gt;" />
<img src="<code></code>" />
<a href="some-link" style="color:red;font-size:12px;">Click Me!</a>
<a href="some-link" style="color:Red;font-size:12px;">Click Me!</a>
<a class="link special" href="some-link">Click Me!</a>
<a class="link special" href="some-link">Click Me!</a>
<a class="link special general" href="some-link">Click Me!</a>
<a class="link special" href="some-link">Click Me!</a>
<button class="btn btn-sm">Click Me</button>
<p class="simple">
    Hello World! I am in a block
</p>
<div class="general div">I am in default tag is `div`.</div>
<a id="main-link">Click Me!</a>
<a class="link" id="main-link">Click Me!</a>
<div id="main-link">I am in default tag is `div`.</div>

attributes.html

Kekuatan Pug adalah kode JavaScript sebaris. Ini adalah sumber data dinamis. Mengikat data dinamis ini ke HTML bisa jadi sulit menggunakan pendekatan khusus, tetapi dengan Pug itu tidak mudah.

//- Pug.js allow writing inline JavaScript code.
//- Unbuffered JavaScript code does not output any results.
//- Unbuffered code must start with `-` hyphen.
- var fieldName = "username"
- var required = false
input(type="text", name=fieldName, required=required)

//- Pug.js also support block Unbuffered code.
-
    // JavaScript comment inside the block
    var classes = [
        "general",
        "link",
        "active"
    ];
a(href="some-link", class=classes)
    
//- Buffered JavaScript code output results.
//- Buffered code starts with `=`
p= "Hello World! I am <b>Pug.js!</b>"

//- Buffered code is escaped by default.
//- Like attributes, you can use `!=` syntax to prevent that.
p!= "Hello World! I am <b>Pug.js!</b>"

//- Pug.js provided built in conditional `if-else` syntax.
//- Paranthese are optional.
- var gender = "MALE"
if(gender == "MALE")
    p I am male.
else if gender == "FEMALE"
    p I am female.
else
    p I am non-binary.

//- Pug also provides `unless` conditional syntax which works like a negated if.
//- This will work only when condition is true.
- var loggedin = false
unless loggedin
    p
        a.link(href="some-link") Click to log in.

//- For loops, Pug has for, `for in`, `each in` and `while` loop.
//- While, in case of `for` loop, `-` hyphen is necessary.
ul
    - for (var i = 0; i < 3; i++)
        li= `current value is ${i}`


- var i = 0
ul
    while i < 3
        li= `current value using while is ${i++}`

- var list = [0,1,2]
ul
    for i in list
        li= `current value using for-in is ${i}`

ul
    each i in list
        li= `current value using each-in is ${i}`

//- Pug does not a `switch` statement but support similar `case-when` statement.
//- You can also write when expression in single line or block.
- var gender = "MALE"
case gender
    when "MALE"
        p I am male.
    when "FEMALE": p I am female.
    default
        p I am non-binary.


//- Interpolation in Pug is very easy.
//- Like ES6 uses `${variable}` syntax, Pug uses `#{variable}` syntax.
- var name="John Doe"
p Hi, My name is #{name}.

//- Any code inside curly braces of `#{}` is valid javascript expression
- var name="John <b>Doe</b>"
p Hi, My name is #{name.toLowerCase()}.

//- By default, value inside curely brace is escaped.
//- To prevent that, use `!` operator.
- var name="John <b>Doe</b>"
p Hi, My name is !{name.toLowerCase()}.

inline-code.pug

Jika Anda terbiasa dengan Angular atau React, ini seharusnya tidak membuat Anda ketagihan.

<input type="text" name="username"/><a class="general link active" href="some-link"></a>
<p align="justify">Hello World! I am &lt;b&gt;Pug.js!&lt;/b&gt;</p>
<p align="justify">Hello World! I am <b>Pug.js!</b></p>
<p align="justify">I am male.</p>
<p align="justify"><a class="link" href="some-link">Click to log in.</a></p>
<ul>
  <li>current value is 0</li>
  <li>current value is 1</li>
  <li>current value is 2</li>
</ul>
<ul>
  <li>current value using while is 0</li>
  <li>current value using while is 1</li>
  <li>current value using while is 2</li>
</ul>
<ul>
  <li>current value using for-in is 0</li>
  <li>current value using for-in is 1</li>
  <li>current value using for-in is 2</li>
</ul>
<ul>
  <li>current value using each-in is 0</li>
  <li>current value using each-in is 1</li>
  <li>current value using each-in is 2</li>
</ul>
<p align="justify">I am male.</p>
<p align="justify">Hi, My name is John Doe.</p>
<p align="justify">Hi, My name is john &lt;b&gt;doe&lt;/b&gt;.</p>
<p align="justify">Hi, My name is john <b>doe</b>.</p>

inline-code.html

Dalam kebanyakan kasus, Anda tidak melakukan hard-code data dalam kode Pug Anda. Data ini sebagian besar dinamis dan dapat diperoleh dari sumber apa pun seperti database SQL atau REST API. Setelah Anda memiliki semua fitur Pug, Anda akan mempelajari cara memasukkan data ke dalam template Pug Anda di topik berikutnya.

Jika Anda sudah familiar dengan PHP, Anda perlu tahu bahwa Anda dapat memasukkan file PHP lain dalam kode Anda. Pug juga mendukung termasuk kode dari file Pug dan non-Pug lainnya.

//- Like PHP, we can include content of another file in a file.
//- If another file extension is `.pug`, then it's content will be compiled.
//- If another files is non-pug file, then it's content will be included as raw text.
//- If no file extenstion is given, `.pug` is automatically appended to the file name.
doctype html
html
    head
        title Includes Example
        include includes/resources.pug

        style
            include includes/style.css
    body
        h1 Hello World

includes.pug

//- located in includes folder
link(rel="stylesheet", href="http://website.com/style.css")
script(src="http://website.com/script.js")

resources.pug

/* located in includes folder */
html,
body {
    padding: 0;
    margin: 0;
    font-size: 14px;
}

style.css

<!DOCTYPE html>
<html>

<head>
    <title>Includes Example</title>
    <link rel="stylesheet" href="http://website.com/style.css">
    <script src="http://website.com/script.js"></script>
    <style>
        /* located in includes folder */

        html,
        body {
            padding: 0;
            margin: 0;
            font-size: 14px;
        }
    </style>
</head>

<body>
    <h1>Hello World</h1>
</body>

</html>

includes.html

Jika Anda bertanya-tanya apakah Anda perlu menggunakan kode yang sama berulang kali, jangan khawatir. Jika Anda akrab dengan SASS, Anda perlu tahu tentang mixin. Pug juga menyediakan fungsionalitas serupa untuk menambahkan penggunaan kembali kode ke program. Pug Mixin adalah blok atau pembungkus fitur untuk kode Pug.

//- Mixin is used to create reusable block of code.
//- Mixin is just a wrapper around proper Pug code.
//- Mixin can also be a function with arguments.
mixin notAllowed
    p: b You are not allowed here

mixin user(data)
    li
        p.name= data.name
        p.city= data.city

//- to use mixin, just use `+` plus operator with mixin name
.critical-section
    +notAllowed

-
    var users = [
        {name: "Ross Geller", city: "New York"},
        {name: "Monica Geller", city: "Little Rock"},
    ]
ul.user-list
    for data in users
        +user(data)

//- Mixin has a internal `block` variable which refers to the content of mixin.
//- If mixin is used like a tag, then `block` variable will have that content, else it will be empty.
mixin user(data)
    li
        p.name= data.name
        p.city= data.city

        .meta
            if block
                block
            else
                p This user has no meta information.
        
ul.user-list
    +user({name: "Ross Geller", city: "New York"})
        p Ross likes Rachel.

    +user({name: "Monica Geller", city: "Little Rock"})
        
//- Mixin has a internal `attributes` variable.
mixin user(data)
    li(class!=attributes.class)
        p.name= data.name
        p.city= data.city

        .meta
            if block
                block
            else
                p This user has no meta information.
        
ul.user-list
    +user({name: "Ross Geller", city: "New York"})(class="active")
        p Ross likes Rachel.

    +user({name: "Monica Geller", city: "Little Rock"})

mixin.pug

<div class="critical-section">
    <p align="justify">
        <b>You are not allowed here</b>
    </p>
</div>
<ul class="user-list">
    <li>
        <p class="name">Ross Geller</p>
        <p class="city">New York</p>
    </li>
    <li>
        <p class="name">Monica Geller</p>
        <p class="city">Little Rock</p>
    </li>
</ul>
<ul class="user-list">
    <li>
        <p class="name">Ross Geller</p>
        <p class="city">New York</p>
        <div class="meta">
            <p align="justify">Ross likes Rachel.</p>
        </div>
    </li>
    <li>
        <p class="name">Monica Geller</p>
        <p class="city">Little Rock</p>
        <div class="meta">
            <p align="justify">This user has no meta information.</p>
        </div>
    </li>
</ul>
<ul class="user-list">
    <li class="active">
        <p class="name">Ross Geller</p>
        <p class="city">New York</p>
        <div class="meta">
            <p align="justify">Ross likes Rachel.</p>
        </div>
    </li>
    <li>
        <p class="name">Monica Geller</p>
        <p class="city">Little Rock</p>
        <div class="meta">
            <p align="justify">This user has no meta information.</p>
        </div>
    </li>
</ul>

mixin.html

Merupakan ide bagus untuk mendefinisikan mixin dalam file terpisah dan memasukkannya ke dalam file saat Anda benar-benar membutuhkannya agar dapat digunakan kembali.

Saya telah melihat kode JavaScript sebaris sejauh ini, tapi percayalah. Anda akan kesulitan menggunakannya. Sebaliknya, data dapat diambil dari sumber apa pun dan dapat bersifat dinamis. Oleh karena itu, saat menjalankan aplikasi seperti server email, Anda bisa mendapatkan kode email yang dikompilasi dengan data pengguna yang di-hard-code dan mengirim email itu ke pengguna saat terjadi peristiwa. Pug-cli tidak membantu di sini. Untuk mengkompilasi kode Pug menjadi HTML dengan cepat, Anda perlu menggunakan paket pug.

Namun, kompilasi menghabiskan banyak CPU dan memori. Apakah benar-benar bijaksana untuk mengkompilasi template 1000 kali per menit untuk 1000 permintaan email dari 1000 pengguna? tolong jangan khawatir. Pug memperbaikinya dengan men-cache template.

Ini dijelaskan dengan baik di https://pugjs.org/api/getting-started.html

Saya telah banyak meneliti dengan Pug sejauh ini, dan sekarang saya merasa nyaman bekerja. Namun, Pug.js memiliki banyak hal untuk dijelajahi, jadi Anda harus memeriksa dokumentasi resmi di https://pugjs.org.