모질라의 자바스크립트 템플릿 언어인 nunjucks을 gulp로 활용해서 HTML작업을 하는 방법을 소개합니다. 이 글에서는 마크업 작업자의 HTML산출물 관리를 위한 측면에서 관련 내용을 다룹니다.
샘플프로젝트의 디렉토리 구조
소스파일의 HTML디렉토리는 레이아웃과 본문 페이지, 그리고 공통으로 사용되는 common 디렉토리로 구성됩니다.
{ "name": "html-tpl", "scripts": { "start": "gulp default" }, "devDependencies": { "del": "^2.2.2", "gulp": "^3.9.1", "gulp-nunjucks-render": "^2.2.1", "gulp-watch": "^4.3.11", "run-sequence": "^1.2.2" } }
샘플에서는 위와같은 모듈을 사용했습니다.
'use strict'; var gulp = require('gulp'), runSequence = require('run-sequence'), watch = require('gulp-watch'), nunjucksRender = require('gulp-nunjucks-render'), del = require('del'); /* ---------------------------------------------------------------------------------- */ // Clean html gulp.task('clean-html', function() { return del('./dist/html'); }); // html-tpl gulp.task('html-tpl', function() { var manageEnvironment = function(environment) { environment.addFilter('tabIndent', function(str, numOfIndents, firstLine) { str = str.replace(/^(?=.)/gm, new Array(numOfIndents + 1).join('\t')); if(!firstLine) { str = str.replace(/^\s+/,""); } return str; }); }; return gulp.src('./src/html/page/**/*.html') .pipe(nunjucksRender({ envOptions: { autoescape: false }, manageEnv: manageEnvironment, path: [ './src/html' ] })) .on('error', function(e) { console.log(e); this.emit('end'); }) .pipe(gulp.dest('./dist/html')); }); // html gulp.task('html', function() { runSequence('clean-html', 'html-tpl'); }); gulp.task('watch', function() { watch(['./src/**/*.html'], function() { gulp.start('html'); }); }); gulp.task('default', [ 'html', 'watch' ]);
nunjucks에서 indent필터를 지원하지만 space만 지원합니다.
템플릿이 랜더링될때 들여쓰기 출력이 신경쓰여서 gulpfile.js 에 manageEnv옵션을 이용해서 tabIndent이라는 필터를 추가했습니다. 템플릿 내에서 tabIndent로 탭문자 들여쓰기 필터를 사용할 수 있습니다.
{% macro include(fileName) -%} {% include fileName ignore missing -%} {% endmacro -%} <!DOCTYPE html> <html> <head> <title>{{ pageVar.title }}</title> </head> <body> <div class="wrap"> <!-- header --> {{ include("common/header.html") | tabIndent(1) }} <!-- content --> {% filter tabIndent(1) %} {% block content %}{% endblock %} {%- endfilter %} <!-- footer --> {{ include("common/footer.html") | tabIndent(1) }} </div> </body> </html>
최상위 레이아웃에서는 include 를 랩핑하는 매크로를 선언했습니다.
include할 때 tabIndent 필터를 적용해서 코드를 간결히 하려는 목적입니다.
{% block content %}{% endblock %} 영역은 각 페이지 본문 내용이 출력되는 block입니다. filter tabIndent로 감싸서 들여쓰기 적용한 모습입니다.
{% set pageVar = { title: 'Home', pageNum: '1' } %} {% extends "layout/layout.html" %} {% block content -%} <section> <h2>hello {{ include("common/world.html") }}</h2> <p>welcome</p> </section> {%- endblock %}
본문 파일에서는 set 태그로 현재 페이지의 변수를 지정하고 레이아웃이나 코드조각에서 활용할 수 있습니다. 그리고 현재 페이지에 적용할 레이아웃 템플릿을 지정합니다. 본문 내부에서도 다른 코드조각을 include할 수 있습니다.
<header> <h1>Site</h1> {{ include("common/nav.html") | tabIndent(1) }} </header>
<nav> <a href="#"{%if pageVar.pageNum == '1' %} class="active"{% endif %}>Home</a> <a href="#"{%if pageVar.pageNum == '2' %} class="active"{% endif %}>About</a> <a href="#"{%if pageVar.pageNum == '3' %} class="active"{% endif %}>Contact</a> </nav>
header파일에서 nav파일을 include했고, nav파일에서는 페이지에서 선언한 변수인 pageVar를 참조해서 현재 페이지에 해당하는 링크에 active클래스를 출력해주고 있습니다.
nunjucks 템플릿 관련 설명은 https://mozilla.github.io/nunjucks/templating.html 에서 참조할 수 있습니다.