유희정

change jade to ejs

...@@ -9,9 +9,9 @@ var usersRouter = require('./routes/users'); ...@@ -9,9 +9,9 @@ var usersRouter = require('./routes/users');
9 9
10 var app = express(); 10 var app = express();
11 11
12 -// view engine setup 12 +// view engine setup (뷰 폴더 경로 설정)
13 app.set('views', path.join(__dirname, 'views')); 13 app.set('views', path.join(__dirname, 'views'));
14 -app.set('view engine', 'jade'); 14 +app.set('view engine', 'ejs');
15 15
16 app.use(logger('dev')); 16 app.use(logger('dev'));
17 app.use(express.json()); 17 app.use(express.json());
......
This diff is collapsed. Click to expand it.
1 +# EJS
2 +
3 +Embedded JavaScript templates
4 +
5 +[![Build Status](https://img.shields.io/travis/mde/ejs/master.svg?style=flat)](https://travis-ci.org/mde/ejs)
6 +[![Developing Dependencies](https://img.shields.io/david/dev/mde/ejs.svg?style=flat)](https://david-dm.org/mde/ejs?type=dev)
7 +[![Known Vulnerabilities](https://snyk.io/test/npm/ejs/badge.svg?style=flat)](https://snyk.io/test/npm/ejs)
8 +
9 +## Installation
10 +
11 +```bash
12 +$ npm install ejs
13 +```
14 +
15 +## Features
16 +
17 + * Control flow with `<% %>`
18 + * Escaped output with `<%= %>` (escape function configurable)
19 + * Unescaped raw output with `<%- %>`
20 + * Newline-trim mode ('newline slurping') with `-%>` ending tag
21 + * Whitespace-trim mode (slurp all whitespace) for control flow with `<%_ _%>`
22 + * Custom delimiters (e.g., use `<? ?>` instead of `<% %>`)
23 + * Includes
24 + * Client-side support
25 + * Static caching of intermediate JavaScript
26 + * Static caching of templates
27 + * Complies with the [Express](http://expressjs.com) view system
28 +
29 +## Example
30 +
31 +```ejs
32 +<% if (user) { %>
33 + <h2><%= user.name %></h2>
34 +<% } %>
35 +```
36 +
37 +Try EJS online at: https://ionicabizau.github.io/ejs-playground/.
38 +
39 +## Usage
40 +
41 +```javascript
42 +let template = ejs.compile(str, options);
43 +template(data);
44 +// => Rendered HTML string
45 +
46 +ejs.render(str, data, options);
47 +// => Rendered HTML string
48 +
49 +ejs.renderFile(filename, data, options, function(err, str){
50 + // str => Rendered HTML string
51 +});
52 +```
53 +
54 +It is also possible to use `ejs.render(dataAndOptions);` where you pass
55 +everything in a single object. In that case, you'll end up with local variables
56 +for all the passed options. However, be aware that your code could break if we
57 +add an option with the same name as one of your data object's properties.
58 +Therefore, we do not recommend using this shortcut.
59 +
60 +## Options
61 +
62 + - `cache` Compiled functions are cached, requires `filename`
63 + - `filename` The name of the file being rendered. Not required if you
64 + are using `renderFile()`. Used by `cache` to key caches, and for includes.
65 + - `root` Set project root for includes with an absolute path (/file.ejs).
66 + - `context` Function execution context
67 + - `compileDebug` When `false` no debug instrumentation is compiled
68 + - `client` When `true`, compiles a function that can be rendered
69 + in the browser without needing to load the EJS Runtime
70 + ([ejs.min.js](https://github.com/mde/ejs/releases/latest)).
71 + - `delimiter` Character to use with angle brackets for open/close
72 + - `debug` Output generated function body
73 + - `strict` When set to `true`, generated function is in strict mode
74 + - `_with` Whether or not to use `with() {}` constructs. If `false`
75 + then the locals will be stored in the `locals` object. Set to `false` in strict mode.
76 + - `destructuredLocals` An array of local variables that are always destructured from
77 + the locals object, available even in strict mode.
78 + - `localsName` Name to use for the object storing local variables when not using
79 + `with` Defaults to `locals`
80 + - `rmWhitespace` Remove all safe-to-remove whitespace, including leading
81 + and trailing whitespace. It also enables a safer version of `-%>` line
82 + slurping for all scriptlet tags (it does not strip new lines of tags in
83 + the middle of a line).
84 + - `escape` The escaping function used with `<%=` construct. It is
85 + used in rendering and is `.toString()`ed in the generation of client functions.
86 + (By default escapes XML).
87 + - `outputFunctionName` Set to a string (e.g., 'echo' or 'print') for a function to print
88 + output inside scriptlet tags.
89 + - `async` When `true`, EJS will use an async function for rendering. (Depends
90 + on async/await support in the JS runtime.
91 +
92 +This project uses [JSDoc](http://usejsdoc.org/). For the full public API
93 +documentation, clone the repository and run `npm run doc`. This will run JSDoc
94 +with the proper options and output the documentation to `out/`. If you want
95 +the both the public & private API docs, run `npm run devdoc` instead.
96 +
97 +## Tags
98 +
99 + - `<%` 'Scriptlet' tag, for control-flow, no output
100 + - `<%_` 'Whitespace Slurping' Scriptlet tag, strips all whitespace before it
101 + - `<%=` Outputs the value into the template (escaped)
102 + - `<%-` Outputs the unescaped value into the template
103 + - `<%#` Comment tag, no execution, no output
104 + - `<%%` Outputs a literal '<%'
105 + - `%%>` Outputs a literal '%>'
106 + - `%>` Plain ending tag
107 + - `-%>` Trim-mode ('newline slurp') tag, trims following newline
108 + - `_%>` 'Whitespace Slurping' ending tag, removes all whitespace after it
109 +
110 +For the full syntax documentation, please see [docs/syntax.md](https://github.com/mde/ejs/blob/master/docs/syntax.md).
111 +
112 +## Includes
113 +
114 +Includes either have to be an absolute path, or, if not, are assumed as
115 +relative to the template with the `include` call. For example if you are
116 +including `./views/user/show.ejs` from `./views/users.ejs` you would
117 +use `<%- include('user/show') %>`.
118 +
119 +You must specify the `filename` option for the template with the `include`
120 +call unless you are using `renderFile()`.
121 +
122 +You'll likely want to use the raw output tag (`<%-`) with your include to avoid
123 +double-escaping the HTML output.
124 +
125 +```ejs
126 +<ul>
127 + <% users.forEach(function(user){ %>
128 + <%- include('user/show', {user: user}) %>
129 + <% }); %>
130 +</ul>
131 +```
132 +
133 +Includes are inserted at runtime, so you can use variables for the path in the
134 +`include` call (for example `<%- include(somePath) %>`). Variables in your
135 +top-level data object are available to all your includes, but local variables
136 +need to be passed down.
137 +
138 +NOTE: Include preprocessor directives (`<% include user/show %>`) are
139 +still supported.
140 +
141 +## Custom delimiters
142 +
143 +Custom delimiters can be applied on a per-template basis, or globally:
144 +
145 +```javascript
146 +let ejs = require('ejs'),
147 + users = ['geddy', 'neil', 'alex'];
148 +
149 +// Just one template
150 +ejs.render('<?= users.join(" | "); ?>', {users: users}, {delimiter: '?'});
151 +// => 'geddy | neil | alex'
152 +
153 +// Or globally
154 +ejs.delimiter = '$';
155 +ejs.render('<$= users.join(" | "); $>', {users: users});
156 +// => 'geddy | neil | alex'
157 +```
158 +
159 +## Caching
160 +
161 +EJS ships with a basic in-process cache for caching the intermediate JavaScript
162 +functions used to render templates. It's easy to plug in LRU caching using
163 +Node's `lru-cache` library:
164 +
165 +```javascript
166 +let ejs = require('ejs'),
167 + LRU = require('lru-cache');
168 +ejs.cache = LRU(100); // LRU cache with 100-item limit
169 +```
170 +
171 +If you want to clear the EJS cache, call `ejs.clearCache`. If you're using the
172 +LRU cache and need a different limit, simple reset `ejs.cache` to a new instance
173 +of the LRU.
174 +
175 +## Custom file loader
176 +
177 +The default file loader is `fs.readFileSync`, if you want to customize it, you can set ejs.fileLoader.
178 +
179 +```javascript
180 +let ejs = require('ejs');
181 +let myFileLoad = function (filePath) {
182 + return 'myFileLoad: ' + fs.readFileSync(filePath);
183 +};
184 +
185 +ejs.fileLoader = myFileLoad;
186 +```
187 +
188 +With this feature, you can preprocess the template before reading it.
189 +
190 +## Layouts
191 +
192 +EJS does not specifically support blocks, but layouts can be implemented by
193 +including headers and footers, like so:
194 +
195 +
196 +```ejs
197 +<%- include('header') -%>
198 +<h1>
199 + Title
200 +</h1>
201 +<p>
202 + My page
203 +</p>
204 +<%- include('footer') -%>
205 +```
206 +
207 +## Client-side support
208 +
209 +Go to the [Latest Release](https://github.com/mde/ejs/releases/latest), download
210 +`./ejs.js` or `./ejs.min.js`. Alternately, you can compile it yourself by cloning
211 +the repository and running `jake build` (or `$(npm bin)/jake build` if jake is
212 +not installed globally).
213 +
214 +Include one of these files on your page, and `ejs` should be available globally.
215 +
216 +### Example
217 +
218 +```html
219 +<div id="output"></div>
220 +<script src="ejs.min.js"></script>
221 +<script>
222 + let people = ['geddy', 'neil', 'alex'],
223 + html = ejs.render('<%= people.join(", "); %>', {people: people});
224 + // With jQuery:
225 + $('#output').html(html);
226 + // Vanilla JS:
227 + document.getElementById('output').innerHTML = html;
228 +</script>
229 +```
230 +
231 +### Caveats
232 +
233 +Most of EJS will work as expected; however, there are a few things to note:
234 +
235 +1. Obviously, since you do not have access to the filesystem, `ejs.renderFile()` won't work.
236 +2. For the same reason, `include`s do not work unless you use an `include callback`. Here is an example:
237 + ```javascript
238 + let str = "Hello <%= include('file', {person: 'John'}); %>",
239 + fn = ejs.compile(str, {client: true});
240 +
241 + fn(data, null, function(path, d){ // include callback
242 + // path -> 'file'
243 + // d -> {person: 'John'}
244 + // Put your code here
245 + // Return the contents of file as a string
246 + }); // returns rendered string
247 + ```
248 +
249 +See the [examples folder](https://github.com/mde/ejs/tree/master/examples) for more details.
250 +
251 +### IDE Integration with Syntax Highlighting
252 +
253 +VSCode:Javascript EJS by *DigitalBrainstem*
254 +
255 +## Related projects
256 +
257 +There are a number of implementations of EJS:
258 +
259 + * TJ's implementation, the v1 of this library: https://github.com/tj/ejs
260 + * Jupiter Consulting's EJS: http://www.embeddedjs.com/
261 + * EJS Embedded JavaScript Framework on Google Code: https://code.google.com/p/embeddedjavascript/
262 + * Sam Stephenson's Ruby implementation: https://rubygems.org/gems/ejs
263 + * Erubis, an ERB implementation which also runs JavaScript: http://www.kuwata-lab.com/erubis/users-guide.04.html#lang-javascript
264 + * DigitalBrainstem EJS Language support: https://github.com/Digitalbrainstem/ejs-grammar
265 +
266 +## License
267 +
268 +Licensed under the Apache License, Version 2.0
269 +(<http://www.apache.org/licenses/LICENSE-2.0>)
270 +
271 +- - -
272 +EJS Embedded JavaScript templates copyright 2112
273 +mde@fleegix.org.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
1 +var fs = require('fs');
2 +var execSync = require('child_process').execSync;
3 +var exec = function (cmd) {
4 + execSync(cmd, {stdio: 'inherit'});
5 +};
6 +
7 +/* global jake, task, desc, publishTask */
8 +
9 +task('build', ['lint', 'clean', 'browserify', 'minify'], function () {
10 + console.log('Build completed.');
11 +});
12 +
13 +desc('Cleans browerified/minified files and package files');
14 +task('clean', ['clobber'], function () {
15 + jake.rmRf('./ejs.js');
16 + jake.rmRf('./ejs.min.js');
17 + console.log('Cleaned up compiled files.');
18 +});
19 +
20 +desc('Lints the source code');
21 +task('lint', ['clean'], function () {
22 + exec('./node_modules/.bin/eslint "**/*.js"');
23 + console.log('Linting completed.');
24 +});
25 +
26 +task('browserify', function () {
27 + exec('./node_modules/browserify/bin/cmd.js --standalone ejs lib/ejs.js > ejs.js');
28 + console.log('Browserification completed.');
29 +});
30 +
31 +task('minify', function () {
32 + exec('./node_modules/uglify-js/bin/uglifyjs ejs.js > ejs.min.js');
33 + console.log('Minification completed.');
34 +});
35 +
36 +desc('Generates the EJS API docs');
37 +task('doc', function (dev) {
38 + jake.rmRf('out');
39 + var p = dev ? '-p' : '';
40 + exec('./node_modules/.bin/jsdoc ' + p + ' -c jsdoc.json lib/* docs/jsdoc/*');
41 + console.log('Documentation generated.');
42 +});
43 +
44 +desc('Publishes the EJS API docs');
45 +task('docPublish', ['doc'], function () {
46 + fs.writeFileSync('out/CNAME', 'api.ejs.co');
47 + console.log('Pushing docs to gh-pages...');
48 + exec('./node_modules/.bin/git-directory-deploy --directory out/');
49 + console.log('Docs published to gh-pages.');
50 +});
51 +
52 +desc('Runs the EJS test suite');
53 +task('test', ['lint'], function () {
54 + exec('./node_modules/.bin/mocha');
55 +});
56 +
57 +publishTask('ejs', ['build'], function () {
58 + this.packageFiles.include([
59 + 'jakefile.js',
60 + 'README.md',
61 + 'LICENSE',
62 + 'package.json',
63 + 'postinstall.js',
64 + 'ejs.js',
65 + 'ejs.min.js',
66 + 'lib/**'
67 + ]);
68 +});
69 +
70 +jake.Task.publish.on('complete', function () {
71 + console.log('Updating hosted docs...');
72 + console.log('If this fails, run jake docPublish to re-try.');
73 + jake.Task.docPublish.invoke();
74 +});
This diff is collapsed. Click to expand it.
1 +/*
2 + * EJS Embedded JavaScript templates
3 + * Copyright 2112 Matthew Eernisse (mde@fleegix.org)
4 + *
5 + * Licensed under the Apache License, Version 2.0 (the "License");
6 + * you may not use this file except in compliance with the License.
7 + * You may obtain a copy of the License at
8 + *
9 + * http://www.apache.org/licenses/LICENSE-2.0
10 + *
11 + * Unless required by applicable law or agreed to in writing, software
12 + * distributed under the License is distributed on an "AS IS" BASIS,
13 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 + * See the License for the specific language governing permissions and
15 + * limitations under the License.
16 + *
17 +*/
18 +
19 +/**
20 + * Private utility functions
21 + * @module utils
22 + * @private
23 + */
24 +
25 +'use strict';
26 +
27 +var regExpChars = /[|\\{}()[\]^$+*?.]/g;
28 +
29 +/**
30 + * Escape characters reserved in regular expressions.
31 + *
32 + * If `string` is `undefined` or `null`, the empty string is returned.
33 + *
34 + * @param {String} string Input string
35 + * @return {String} Escaped string
36 + * @static
37 + * @private
38 + */
39 +exports.escapeRegExpChars = function (string) {
40 + // istanbul ignore if
41 + if (!string) {
42 + return '';
43 + }
44 + return String(string).replace(regExpChars, '\\$&');
45 +};
46 +
47 +var _ENCODE_HTML_RULES = {
48 + '&': '&amp;',
49 + '<': '&lt;',
50 + '>': '&gt;',
51 + '"': '&#34;',
52 + "'": '&#39;'
53 +};
54 +var _MATCH_HTML = /[&<>'"]/g;
55 +
56 +function encode_char(c) {
57 + return _ENCODE_HTML_RULES[c] || c;
58 +}
59 +
60 +/**
61 + * Stringified version of constants used by {@link module:utils.escapeXML}.
62 + *
63 + * It is used in the process of generating {@link ClientFunction}s.
64 + *
65 + * @readonly
66 + * @type {String}
67 + */
68 +
69 +var escapeFuncStr =
70 + 'var _ENCODE_HTML_RULES = {\n'
71 ++ ' "&": "&amp;"\n'
72 ++ ' , "<": "&lt;"\n'
73 ++ ' , ">": "&gt;"\n'
74 ++ ' , \'"\': "&#34;"\n'
75 ++ ' , "\'": "&#39;"\n'
76 ++ ' }\n'
77 ++ ' , _MATCH_HTML = /[&<>\'"]/g;\n'
78 ++ 'function encode_char(c) {\n'
79 ++ ' return _ENCODE_HTML_RULES[c] || c;\n'
80 ++ '};\n';
81 +
82 +/**
83 + * Escape characters reserved in XML.
84 + *
85 + * If `markup` is `undefined` or `null`, the empty string is returned.
86 + *
87 + * @implements {EscapeCallback}
88 + * @param {String} markup Input string
89 + * @return {String} Escaped string
90 + * @static
91 + * @private
92 + */
93 +
94 +exports.escapeXML = function (markup) {
95 + return markup == undefined
96 + ? ''
97 + : String(markup)
98 + .replace(_MATCH_HTML, encode_char);
99 +};
100 +exports.escapeXML.toString = function () {
101 + return Function.prototype.toString.call(this) + ';\n' + escapeFuncStr;
102 +};
103 +
104 +/**
105 + * Naive copy of properties from one object to another.
106 + * Does not recurse into non-scalar properties
107 + * Does not check to see if the property has a value before copying
108 + *
109 + * @param {Object} to Destination object
110 + * @param {Object} from Source object
111 + * @return {Object} Destination object
112 + * @static
113 + * @private
114 + */
115 +exports.shallowCopy = function (to, from) {
116 + from = from || {};
117 + for (var p in from) {
118 + to[p] = from[p];
119 + }
120 + return to;
121 +};
122 +
123 +/**
124 + * Naive copy of a list of key names, from one object to another.
125 + * Only copies property if it is actually defined
126 + * Does not recurse into non-scalar properties
127 + *
128 + * @param {Object} to Destination object
129 + * @param {Object} from Source object
130 + * @param {Array} list List of properties to copy
131 + * @return {Object} Destination object
132 + * @static
133 + * @private
134 + */
135 +exports.shallowCopyFromList = function (to, from, list) {
136 + for (var i = 0; i < list.length; i++) {
137 + var p = list[i];
138 + if (typeof from[p] != 'undefined') {
139 + to[p] = from[p];
140 + }
141 + }
142 + return to;
143 +};
144 +
145 +/**
146 + * Simple in-process cache implementation. Does not implement limits of any
147 + * sort.
148 + *
149 + * @implements Cache
150 + * @static
151 + * @private
152 + */
153 +exports.cache = {
154 + _data: {},
155 + set: function (key, val) {
156 + this._data[key] = val;
157 + },
158 + get: function (key) {
159 + return this._data[key];
160 + },
161 + remove: function (key) {
162 + delete this._data[key];
163 + },
164 + reset: function () {
165 + this._data = {};
166 + }
167 +};
1 +{
2 + "_from": "ejs",
3 + "_id": "ejs@3.0.1",
4 + "_inBundle": false,
5 + "_integrity": "sha512-cuIMtJwxvzumSAkqaaoGY/L6Fc/t6YvoP9/VIaK0V/CyqKLEQ8sqODmYfy/cjXEdZ9+OOL8TecbJu+1RsofGDw==",
6 + "_location": "/ejs",
7 + "_phantomChildren": {},
8 + "_requested": {
9 + "type": "tag",
10 + "registry": true,
11 + "raw": "ejs",
12 + "name": "ejs",
13 + "escapedName": "ejs",
14 + "rawSpec": "",
15 + "saveSpec": null,
16 + "fetchSpec": "latest"
17 + },
18 + "_requiredBy": [
19 + "#USER",
20 + "/"
21 + ],
22 + "_resolved": "https://registry.npmjs.org/ejs/-/ejs-3.0.1.tgz",
23 + "_shasum": "30c8f6ee9948502cc32e85c37a3f8b39b5a614a5",
24 + "_spec": "ejs",
25 + "_where": "C:\\Users\\LG\\Desktop\\4-1\\Reminder-Talk",
26 + "author": {
27 + "name": "Matthew Eernisse",
28 + "email": "mde@fleegix.org",
29 + "url": "http://fleegix.org"
30 + },
31 + "bugs": {
32 + "url": "https://github.com/mde/ejs/issues"
33 + },
34 + "bundleDependencies": false,
35 + "dependencies": {},
36 + "deprecated": false,
37 + "description": "Embedded JavaScript templates",
38 + "devDependencies": {
39 + "browserify": "^13.1.1",
40 + "eslint": "^4.14.0",
41 + "git-directory-deploy": "^1.5.1",
42 + "jake": "^10.3.1",
43 + "jsdoc": "^3.4.0",
44 + "lru-cache": "^4.0.1",
45 + "mocha": "^5.0.5",
46 + "uglify-js": "^3.3.16"
47 + },
48 + "engines": {
49 + "node": ">=0.10.0"
50 + },
51 + "homepage": "https://github.com/mde/ejs",
52 + "keywords": [
53 + "template",
54 + "engine",
55 + "ejs"
56 + ],
57 + "license": "Apache-2.0",
58 + "main": "./lib/ejs.js",
59 + "name": "ejs",
60 + "repository": {
61 + "type": "git",
62 + "url": "git://github.com/mde/ejs.git"
63 + },
64 + "scripts": {
65 + "postinstall": "node ./postinstall.js",
66 + "test": "mocha"
67 + },
68 + "version": "3.0.1"
69 +}
1 +#!/usr/bin/env node
2 +
3 +'use strict';
4 +
5 +function isTrue(value) {
6 + return !!value && value !== '0' && value !== 'false';
7 +}
8 +
9 +let envDisable = isTrue(process.env.DISABLE_OPENCOLLECTIVE) || isTrue(process.env.CI);
10 +let logLevel = process.env.npm_config_loglevel;
11 +let logLevelDisplay = ['silent', 'error', 'warn'].indexOf(logLevel) > -1;
12 +
13 +if (!envDisable && !logLevelDisplay) {
14 + console.log('Thank you for installing \u001b[35mEJS\u001b[0m: built with the \u001b[32mJake\u001b[0m JavaScript build tool (\u001b[32mhttps://jakejs.com/\u001b[0m)\n');
15 +}
16 +
17 +
...@@ -225,6 +225,11 @@ ...@@ -225,6 +225,11 @@
225 "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 225 "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
226 "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 226 "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
227 }, 227 },
228 + "ejs": {
229 + "version": "3.0.1",
230 + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.0.1.tgz",
231 + "integrity": "sha512-cuIMtJwxvzumSAkqaaoGY/L6Fc/t6YvoP9/VIaK0V/CyqKLEQ8sqODmYfy/cjXEdZ9+OOL8TecbJu+1RsofGDw=="
232 + },
228 "encodeurl": { 233 "encodeurl": {
229 "version": "1.0.2", 234 "version": "1.0.2",
230 "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 235 "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
8 "dependencies": { 8 "dependencies": {
9 "cookie-parser": "~1.4.4", 9 "cookie-parser": "~1.4.4",
10 "debug": "~2.6.9", 10 "debug": "~2.6.9",
11 + "ejs": "^3.0.1",
11 "express": "~4.16.1", 12 "express": "~4.16.1",
12 "http-errors": "~1.6.3", 13 "http-errors": "~1.6.3",
13 "jade": "~1.11.0", 14 "jade": "~1.11.0",
......
1 +<h1><%= message %></h1>
2 +<h2><%= error.status %></h2>
3 +<pre><%= error.stack %></pre>
...\ No newline at end of file ...\ No newline at end of file
1 -extends layout
2 -
3 -block content
4 - h1= message
5 - h2= error.status
6 - pre #{error.stack}
1 +<!DOCTYPE html>
2 +<html>
3 + <head>
4 + <title><%= title %></title>
5 + <link rel='stylesheet' href='/stylesheets/style.css' />
6 + </head>
7 + <body>
8 + <h1><%= title %></h1>
9 + <p>Welcome to <%= title %></p>
10 + </body>
11 +</html>
...\ No newline at end of file ...\ No newline at end of file
1 -extends layout
2 -
3 -block content
4 - h1= title
5 - p Welcome to #{title}
1 -doctype html
2 -html
3 - head
4 - title= title
5 - link(rel='stylesheet', href='/stylesheets/style.css')
6 - body
7 - block content