Write a simple JS template replacement tool RTT----Replace templete tools

Source: Internet
Author: User
Tags html comment

Recently, I have been revising my personal online resume for some time.  This online resume uses CSS3 to make 3D rotation effect, so there will be compatibility issues, for non-CSS3 3D perspective browser, such as IE, 360, etc., I use another set of CSS files compatible.  For the mobile browser, although the basic is the WebKit kernel, but the test found that the 3D effect is not smooth, so the mobile is to identify useragent switch to another set of non-3D pages. Because no database, then the problem comes, mobile and PC two sets of pages is a common set of data, I think of the method has two: first, after the page loaded with Ajax request the same data file, and then JS in the page display when the data is populated, but this method to increase the HTTP request, What happens when you need to request a hyper-data file?  The load speed naturally needs to be affected.   Method two in the HTML to write directly, so that no additional requests, but in case the data to be modified, multiple pages you go slowly to find it ... So you want to implement your own set of template replacement tools, like PHP inserted, and then you can print directly. Just recently learning Nodejs, it can operate files, for us jser like artifact! So I just wanted to emulate PHP insert tags to implement a simple template replacement tool RTT----Replace templete tools, manipulate HTML files through Nodejs, and then replace the output to the target file

In HTML insert <%%> type tags, then inside you can use the JS code:

<div class= "Face Info" ><%for (var i=0, m=data.info.length; i<m; i++) {%><div class= "Info-kind" > 

After the substitution, the resulting content is as follows:

<div class= "Face info" >    <div class= "Info-kind" >        

  

Implementing the template Replacement tool

How to implement a tool like this? In fact, the principle is very simple, is to run in node in the JS read file, will use the Fs.readfilesync method, and then the resulting string with regular matching, through <%%> as a delimiter, JS can be divided into what is the direct output, which needs to be calculated, Finally, the output is done using the Fs.writefilesync method. Because you've implemented a complex DOM selector before, you'll want to use regular break special characters and then put them in an array to traverse.

To create a new Rtt.js file:

var fs = require (' FS ');   Get the FS module var srchtml = Fs.readfilesync (' a.src.html ');    Read a.src.html file data  srchtml = srchtml.tostring (' utf-8 ');    Converts the read binary data into a string srchtml = Srchtml.replace (/[\r\n\t]+/g, ");    Remove the line and tab//can be merged with the above, convenient to watch the separate write, remove the HTML and js comments srchtml = srchtml.replace (/<!--. *?-->|\/\*.*?\*\//g, ");// Disconnect srchtml with <%%>//if  abc<% alert (1),%>def will output [' abc ', ' <% alert (1);%> ', ' def ']var arr = Srchtml.match (/<%={0,2}.*?%>|. *? (? =<%) |. *? (? =$)/g)

So get arr is similar to [' <div> ', ' <% data.name%> ', ' </div> ', ' <% data.age%> ', ' <ul> ' ...]

Finally, we need to pass eval to read the JS statement in <%%>, so we need to set up an S variable for eval, and the res variable in s variable will eventually be eval out and iterate over the array to output

var s = "res="; "; For (var i=0, m=arr.length; i<m; i++) {/    * When iterating through an array, it is a JS statement if it is the beginning of the <%, if not the direct output */if    (Arr[i].indexof (' <% ') = = = 0) {        if (Arr[i].charat (2) = = = ' && arr[i].charat (3)!== ' = ') {            ///If it is a JS variable,            s + = ' res+= ' + arr[i] + '; ';        }         else {             //JS statement when             s + = Arr[i];         }    }    else {        S + = ' res+= ' + arr[i] + ' "; ';    }} Eval (s);    Generate res variable and execute fs.writefilesync (a.html, res);    Output the RES variable to the target file

  

Now, a simple template replacement tool is finished, each time the arr[i] also need to test, escaped here will not repeat, declare a function call.

Add an include function to introduce additional file content

The above template substitution allows only substitution variables, generating multiple specified labels through an array, but we often need to introduce some external module files, PHP require and include are very useful, but now is Nodejs.

For example, the introduction of m.tpl.html in A.src.html, M.tpl.html introduced X.tpl.js and y.tpl.html, y.tpl.html was introduced.

The principle is not that difficult, first encapsulate the above code into a function.

/*SRC---Source file path dest---Generate file path datapath---JSON data path dataname object name in---src file delimiter---delimiter */function rtt (SRC, dest, data Path, Dataname, delimiter) {    //Set object name defaults to DataPath filename    dataname = Dataname | | datapath.split ('/') [ Datapath.split ('/'). Length-1].replace (/\.[ A-z0-9]+$/gi, ");    The set delimiter is <%%> by default, and then separated in the middle is saved as [' <% ', '%> ']    delimiter = Delimiter | | ' <%%> ';    Delimiter = (function () {        var n = math.floor (DELIMITER.LENGTH/2);        return [Delimiter.substr (0, N), Delimiter.substr (-N)];    }) ();    Call the Replace function, the final output is replaced by the string, generated to the Dest file    //Here Most of the replacement logic has been encapsulated in replace, replace only read the source file generation target final string    // Because the various variables in the RTT are used in replace, the    fs.writefilesync (dest, replace (SRC)) is written using the closure form;    Console.log (' compile finished! ');    print ' compile finished '    function replace (SRC) {
Pass in a SRC path, return the replaced string ... }

  

Replace most of the same as the previous interview, just encapsulated into a function, and then the include extension:

function replace (SRC) {eval ("var" +dataname+ "=" + data);    var s = "res="; ", FS = require (" FS "), location = GetLocation (SRC);    Read the source file HTML and get the string, and then put the string in \r\n\t var srchtml = Fs.readfilesync (src). toString (' Utf-8 '). Replace (/[\r\n\t]+/g, ');    Remove the HTML comment, JS comment/**/type srchtml = Srchtml.replace (/<!--. *?-->|\/\*.*?\*\//g, '); Split the string in the HTML file var reg = new RegExp (delimiter[0] + "={0,2}.*?" +delimiter[1]+ "|. *? (? = "+delimiter[0]+") |. *?    (? =$) "," G ");    var arr = Srchtml.match (reg); For (var i=0, m=arr.length; i<m; i++) {if (Arr[i].indexof (' <% ') = = = 0) {if (Arr[i].charat (2) = = = ' = ' &             amp;& Arr[i].charat (3)!== ' = ') {//JS variable when s + = ' res+= ' + trim (arr[i]) + '; '; } else if (Arr[i].charat (2) = = = ' && Arr[i].charat (3) = = = ') {//js variable, if two < replace it with &lt; Replace > to &gt;             s + = ' res+= ' + eshtml (Trim (arr[i])) + '; ';           }  else if (/^<%\s*include\ (. *\) \s*;? \s*%>$/.test (Arr[i])) {//If it is recognized as an include (' abc.html ') type format, recursively calls the Replace function, passing in abc.html var                 NewPath = Genpath (src, arr[i].replace (/.+[' "] (. +) ['"].+/g, function (A, b) {return B;}));             s + = ' res+= ' + es (replace (newpath)) + ' "; ';}             else{//JS statement when s + = Trim (Arr[i]);     }} else{S + = ' res+= ' + es (arr[i]) + ' "; ';}}     Eval (s); Returns the variable that was obtained by Eval res return res;}

The Replace function above uses the recursive implementation of multi-layered references, but there is a problem, if the a.src.html reference tpl/b.html, tpl/b.html and refer to the./css/c.css, then the path will be problematic, because the referenced file, referencing its The path to his file is relative to himself, and node reads the file location where the src file is located:

When node executes to the include (' css/c.html '), it will read the/css/c.css file according to the location of the src file, so there will be an error, so it is necessary to use a function to generate a new path relative to SRC in order to get the/tpl/css/c.css file

Pass in a file path, returning the directory where function getLocation (src) {if (Src.charat (src.length-1) = = =/') return Src;else if (src.indexof ('/') = = = 0) return './'; else if (Src.indexof ('/') < 0) return './'; Else{var temp = src.split ('/'); Temp.pop (); return Temp.join ('/') + '/';}}

You will then need to generate a function for the new path:

Pass in the current file path, and the file path of include, generate relative path relative to index function Genpath (cur, dest) {if (Dest.charat (0)!== '. ' && Dest.charat (0)!== '/') {return getLocation (cur) + dest.replace (/^\//, ');} else if (dest.indexof ('./') = = = 0) {return getLocation (cur) + dest.replace (/^\.\//, ');} else{//if the target path is: /.. /.. /a/b/c.html type var cur = getLocation (cur). Match (/[^\/]+\//g); var m = Cur.length;var n = dest.match (/\.\.\//g). Length;if (M >n) {return Cur.slice (0, M-n). Join (') + dest.replace (/\.\.\//g, ');} else if (m = = = N) return './' + dest.replace (/\.\.\//g, '); else if (M < n) {for (var res= ", i=0; i<n-m; i++) res+= '. /'; return res + dest.replace (/\.\.\//g, ');}}}

  

At this point, a template that can reference other files has been completed and can be installed via NPM install RTT--save-dev, then create a new Replace.js file and enter:

var RTT = require (' RTT '); RTT (' a.src.html ', ' a.html ', ' Data.json ');

It can be said that the a.src.html source file <%%> contains the use of the data namespace output to a.html, allowing multiple layers to introduce files, note: <%include (");%>

Since I study Nodejs time is not long, have any questions please point out, thank you

Write a simple JS template replacement tool RTT----Replace templete tools

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.