官术网_书友最值得收藏!

Creating your first template

In the following example, you will create a Diet template from the HTML page using various techniques. The template syntax is concise and easy to read, which is a great advantage over using plain HTML.

Turning the HTML page into a Diet template

Let's start with a one-to-one translation of the HTML page into a Diet template. The syntax that we will use is based on Jade templates ( familiar with. It looks similar to the following:

doctype html
html
  head
    meta(charset='utf-8')
    title Demo site
    link(rel='stylesheet', type='text/css', href='demo.css')
  body
    header
      | Header
    nav
      ul
        li
          a(href='link1') Link 1
        li
          a(href='link2') Link 2
        li
          a(href='link3') Link 3
    article
      h1 Title
      p Some content here.
    footer
      | Footer

The template resembles the HTML page. Here are the basic syntax rules for a template:

  • The first word on a line is an HTML tag
  • The attributes of an HTML tag are written as a comma-separated list surrounded by parentheses
  • A tag may be followed by plain text that may contain the HTML code
  • Any plain text on a new line starts with the pipe symbol
  • Nesting of elements is done by adding indentation

If you want to see the result of this template, save the code as index.dt and put it together with the demo.css file in the views folder of the template application from Chapter 1, Getting Started with Your First Web Application.

Now, you need to create a small application to see the result of the template, as shown in the following:

  1. Create a new template project with dub:
    $ dub init template --type=vibe.d
    
  2. Save the template as the views/index.dt file.
  3. Copy the demo.css file in the public folder.
  4. Change the contents of the generated source/app.d application to the following:
    import vibe.d;
    
    shared static this()
    {
        auto router = new URLRouter;
        router.get("/", staticTemplate!"index.dt");
        router.get("*", serveStaticFiles("public/"));
      
        auto settings = new HTTPServerSettings;
        settings.port = 8080;
        settings.bindAddresses = ["::1", "127.0.0.1"];
        listenHTTP(settings, router);
      
        logInfo("Please open http://127.0.0.1:8080/ in your browser.");
    }
  1. Run dub in the project folder to start the application and then go to http://127.0.0.1:8080/ to see the resulting page.

The application uses a new URLRouter class. This class is used to map a URL to a web page. With the router.get("/", staticTemplate!"index.dt"); statement, every request for the base URL is responded by rendering of the index.dt template. The router.get("*", serveStaticFiles("public/")); statement uses a wildcard to serve all other requests as static files stored in the public folder.

Adding inheritance

Up to now, the template was only a one-to-one translation of the HTML page. The next step is to split the index.dt file from the previous section in two, layout.dt and index.dt. The layout.dt file will define the general structure of a page while index.dt inherits from this file and adds new content.

The key to using the template inheritance is in the definition of a block. A block has a name and contains some template code. A child template may replace the block, append or prepend content to a block. In the following layout.dt file, there are four blocks defined: header, navigation, content, and footer. For all the blocks except the content, a default text entry is defined, as shown in the following:

doctype html
html
    head
        meta(charset='utf-8')
        title Demo site
        link(rel='stylesheet', type='text/css', href='demo.css')
    body
        block header
            header Header
        block navigation
            nav
                ul
                    li <a href="link1">Link 1</a>
                    li <a href="link2">Link 2</a>
                    li <a href="link3">Link 3</a>
        block content
        block footer
            footer Footer

The template in the index.dt file inherits this layout and replaces the content block, as follows:

extends layout
block content
    article
        h1 Title
        p Some content here.

You can put both the files in the views folder and run dub again. The rendered page in your browser will still look the same as before.

You can now add more pages and reuse the layout. It is also possible to change the common elements that you have defined in the header, footer, and navigation blocks.

There is no restriction on the level of inheritance used. This allows you to construct very sophisticated template systems.

Using includes

Inheritance is not the only way to avoid repetition of template code. With the include keyword, you can insert the contents of another file. This allows you to place the reusable template code in separate files. As an example, just put the navigation in a separate navigation.dt file, as follows:

nav
    ul
        li <a href="link1">Link 1</a>
        li <a href="link2">Link 2</a>
        li <a href="link3">Link 3</a>

The layout.dt file uses the include keyword to insert the navigation.dt file, as shown in the following code:

doctype html
html
  head
    meta(charset='utf-8')
    title Demo site
    link(rel='stylesheet', type='text/css', href='demo.css')
  body
    block header
      header Header
    block navigation
 include navigation
    block content
    block footer
      footer Footer

Just as with the inheritance example, you can put both the files in the views folder and run dub again. The rendered page in your browser will look the same as before.

Integrating other languages with blocks and filters

So far, the templates only used the HTML content. However, a web application is usually built with a combination of languages that are often integrated in a single document, as shown in the following:

  • CSS styles are placed in the style element
  • The JavaScript code is kept in the the script element
  • The content is typically written in a simplified markup language, such as Markdown

Diet templates have two mechanisms that can be used for integration of other languages.

If a tag is followed by a dot, then the block is treated as plain text. For example, look at the following template code:

p.
    Some text
    And some more text

This is translated into:

<p>
    Some text
    And some more text
</p>

The same can be used for scripts and styles, too. For example, look at the following script tag with JavaScript code in it:

script(type='text/javascript').
    console.log('D is awesome')

It translates into the following code:

<script type="text/javascript">
    console.log('D is awesome')
</script>

An alternative is to use a filter. You can specify a filter with a colon that is followed by the filter name. The script example can be written with a filter as follows:

:javascript
    console.log('D is awesome')

This is translated into the following:

<script type="text/javascript">
    //<![CDATA[
    console.log('D is awesome')
    //]]>
</script>

The following filters are provided by vibe.d:

  • The javascript filter for the JavaScript code
  • The css filter for CSS styles
  • The markdown filter for the content that is written in the Markdown syntax
  • The htmlescape filter to escape HTML symbols

The css filter works in the same way as the javascript filter.

The markdown filter accepts the text written in the Markdown syntax and translates it into HTML. Markdown is a simplified markup language for web authors, among other things. The syntax is available on the web at http://daringfireball.net/projects/markdown/syntax. The following is our previous template; however, using the markdown filter for the navigation and article content this time. The navigation.dt file now contains the following code:

nav
  ul
    :markdown
      - [Link 1](link1)
      - [Link 2](link2)
      - [Link 3](link3)

The content of the index.dt file will look as shown in the following:

extends layout
block content
  article
    :markdown
      Title
      =====
      
      Some content here.

The rendered HTML page remains the same. The advantage is that you have significantly less to type, which is beneficial if you produce a lot of content. The syntax is also easy to read, which helps in order to concentrate on the topic.

A normal plain text block can contain HTML tags, as follows:

p.
    Click this <a href="link">link</a>

This is rendered as the following:

<p>
    Click this <a href="link">link</a>
</p>

There are situations where you may want to treat HTML tags as plain text, for example, if you want to explain the HTML syntax to the reader. In this case, you can use the htmlescape filter:

p
    :htmlescape
        Link syntax: <a href="url target">text to display</a>

This will be rendered as the following:

<p>
    Link syntax: &lt;a href="url target"&gt;text to display&lt;/a&gt;
</p>

You can also add your own filters; vibe.d provides the registerDietTextFilter()function to register new filters. This function takes the name of the filter and a pointer to the filter function. The filter function itself is called with the text to filter and level of indentation, and returns the filtered text. The level of indentation tells you by how many tabs a HTML tag would be indented at this line of the output. This is important if you want to output a visually correct indentation. For example, you can use this functionality for pretty printing of D code, as follows:

  1. First, create a new project with dub, as shown here:
    $ dub init filter --type=vibe.d
    
  2. Then, create an index.dt template file in the views folder. Implement a new filter called dcode to format the D code:
    doctype html
    head
      title Code filter example
      :css
        .keyword { color: #0000ff;
             font-weight: bold; }
    body
      p You can create your own functions.
      :dcode
        T max(T)(T a, T b) {
          if (a > b) return a;
          return b;
        }
  3. Place the filter function in the app.d file in the source folder. The filter function outputs the text in a <pre> tag. Identifier keywords are inserted in the <span class="keyword"> element in order to allow custom formatting. For simplicity, this implementation only matches the if and return D keywords. If you want to complete the filter, then you can use the D keyword list provided at http://dlang.org/lex.html#Keyword. The whole application is then as shown in the following code:
    import vibe.d;
    
    string filterDCode(string text, size_t indent)
    {
        import std.regex;
        import std.array;
      
        auto dst = appender!string;
        filterHTMLEscape(dst, text,
                         HTMLEscapeFlags.escapeQuotes);
        auto regex = regex(r"(^|\s)(if|return)(;|\s)");
        text = replaceAll(dst.data, regex,
                    `$1<span class="keyword">$2</span>$3`);
    
        auto indent_string = "\n" ~ "\t".replicate(indent);
    
        auto ret = appender!string();
        ret ~= indent_string ~ "<pre>\n"
               ~ text
               ~ indent_string ~ "</pre>";
    
        return ret.data;
    }
    
    shared static this()
    {
        registerDietTextFilter("dcode", &filterDCode);
    
        auto settings = new HTTPServerSettings;
        settings.port = 8080;
        settings.bindAddresses = ["::1", "127.0.0.1"];
        listenHTTP(settings, staticTemplate!"index.dt");
    
        logInfo("Please open http://127.0.0.1:8080/ in your browser.");
    }

    The filterDCode()function uses scoped imports. Functions and types from the std.regex and std.array modules are imported in the function. This limits the scope of the imported symbols; however, it also emphasizes that the function is using these symbols.

    The overall structure of the filterDCode()function is simple. First, the whole input text in the text parameter is escaped using an HTML filter. This replaces all characters with a special meaning in HTML with HTML entities. Then the <span> elements are inserted with the help of a regular expression and a global replace. Next, the indentation string for the <pre> tag is created using the replicate() function. The last step is to append all the strings together and return the result.

Compile and run this application to see that the keywords are shown in bold and colorized blue.

主站蜘蛛池模板: 延庆县| 额济纳旗| 易门县| 新巴尔虎右旗| 镇江市| 神木县| 桐庐县| 华阴市| 古交市| 上虞市| 灵璧县| 城口县| 三亚市| 尖扎县| 绥中县| 盐边县| 曲麻莱县| 萍乡市| 邓州市| 万州区| 贵阳市| 固原市| 大安市| 正蓝旗| 乌拉特前旗| 周宁县| 滨州市| 通榆县| 阳高县| 呈贡县| 泌阳县| 龙游县| 太湖县| 新绛县| 湟源县| 汨罗市| 延寿县| 吴堡县| 项城市| 武强县| 介休市|