- D Web Development
- Kai Nacke
- 1752字
- 2021-07-16 09:35:32
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:
- Create a new
template
project with dub:$ dub init template --type=vibe.d
- Save the template as the
views/index.dt
file. - Copy the
demo.css
file in thepublic
folder. - 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."); }
- Run
dub
in the project folder to start the application and then go tohttp://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: <a href="url target">text to display</a> </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:
- First, create a new project with
dub
, as shown here:$ dub init filter --type=vibe.d
- Then, create an
index.dt
template file in theviews
folder. Implement a new filter calleddcode
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; }
- Place the filter function in the
app.d
file in thesource
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 theif
andreturn
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 thestd.regex
andstd.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 thetext
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 thereplicate()
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.
- C++程序設(shè)計教程
- Mobile Application Development:JavaScript Frameworks
- Mastering Adobe Captivate 2017(Fourth Edition)
- Linux核心技術(shù)從小白到大牛
- Cocos2d-x游戲開發(fā):手把手教你Lua語言的編程方法
- 圖解Java數(shù)據(jù)結(jié)構(gòu)與算法(微課視頻版)
- 零基礎(chǔ)學Scratch少兒編程:小學課本中的Scratch創(chuàng)意編程
- Vue.js快速入門與深入實戰(zhàn)
- JMeter 性能測試實戰(zhàn)(第2版)
- Wireshark Network Security
- Bootstrap Essentials
- Python機器學習編程與實戰(zhàn)
- Java:High-Performance Apps with Java 9
- 搞定J2EE:Struts+Spring+Hibernate整合詳解與典型案例
- Mastering Python Design Patterns