diff --git a/CHANGELOG.md b/CHANGELOG.md index 9870d9c..d65a3fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,20 @@ +### Feature + +- Add template partial + - A partial is a template whose name starts by “_”. It won't be rendered directly (so it doesn't need meta like “prismic-api”) but is included in other +templates using the helper `partial`. (`[%- partial('footer') %]` will include +the partial “_footer.html.erb”) +- Add helper to change ref +- Add OAuth2 authentication +- Use [EJS](https://github.com/visionmedia/ejs) for template rendering + - Its HTML escaping and filters are available + +### Incompatible changes + +- Because EJS is now used, every template returning HTML have to be fixed +(by replacing `[%= ... %]` by `[%- ... %]`) in order to stop escaping the HTML +twice. + ## 0.0.4 ### Feature diff --git a/README.md b/README.md index a5fbda2..90b093d 100644 --- a/README.md +++ b/README.md @@ -179,9 +179,12 @@ It is possible to customize the URL as well. To do so, just add a `` tag ## Internals -baked.js is built on top of [Node.js](nodejs.org) and use [dom.js](https://github.com/andreasgal/dom.js/) to emulate the DOM. +baked.js is built on top of [Node.js](nodejs.org). -It uses [Q](https://github.com/kriskowal/q) and [lodash](http://lodash.com), and let [Gulp](gulpjs.com) and [browserify](browserify.org) handle the generation of the browser library. +It uses [Q](https://github.com/kriskowal/q) and [lodash](http://lodash.com), +let [Gulp](gulpjs.com) and [browserify](browserify.org) handle the generation +of the browser library and uses [EJS](https://github.com/visionmedia/ejs) for +the template rendering. ### Dynamic browser mode @@ -192,7 +195,7 @@ The generation can actually be performed at 2 places: - It allows to send proper content the browsers and search engines. - Dynamically by the browser - Every statically rendered page is able to re-generate itself, and then to emulate the navigation in the others pages (using [HTML5's History API](http://www.whatwg.org/specs/web-apps/current-work/multipage/history.html#the-history-interface)). - - It allows to specify specific `access_token` and `ref`, in order to render the content using a specific prismic.io's release. + - It allows to specify specific `access_token` and `ref`, in order to render the content using a specific prismic.io's release. These can be set automatically using the [OAuth2 authentication](#auth2-authentication). The dynamic mode needs some specific components: @@ -204,10 +207,59 @@ The dynamic mode needs some specific components: - find the template to use, its parameters and the given argument in case of non-statically-rendered page (routing) - This case can happen when loading a page that is created only with a specific release. -## Notes +#### Specific ref to use -- the server build a DOM structure (using JSDOM) in order to navigate inside it, so: - - The tags `<% %>` can't be used, because JSDOM doesn't like them +baked.js provides a helper to easilly switch between refs. + +It listen changes made on elements containing the attribute +“`data-prismic-action="update"`” and update the ref (and re-generate) +accordingly. + +Here an example of use: + +```ejs + +``` + +#### OAuth2 authentication + +baked.js provides a helper to authenticate to your prismic.io application +using OAuth2. + +It listen the “click” events on elements containing attributes +“`data-prismic-action="signout"`” or “`data-prismic-action="signin"`.” + +In order to work, this feature needs a meta tag “`prismic-oauth-client-id`” +to be defined. + +Here an example: + +```ejs + +... +[% if (loggedIn) { %] + + +[% } else { %] + +[% } %] +``` ### Licence diff --git a/example/to_generate/_footer.html b/example/to_generate/_footer.html new file mode 100644 index 0000000..d3d4c46 --- /dev/null +++ b/example/to_generate/_footer.html @@ -0,0 +1,18 @@ +
index
+ +

+ [% if (loggedIn) { %] + + + [% } else { %] + + [% } %] +

diff --git a/example/to_generate/blog/index.html b/example/to_generate/blog/index.html index ad1144c..cc25975 100644 --- a/example/to_generate/blog/index.html +++ b/example/to_generate/blog/index.html @@ -7,6 +7,7 @@ + @@ -36,7 +37,7 @@

[% }) %] - index + [%- partial('/footer') %] diff --git a/example/to_generate/blog/post.html b/example/to_generate/blog/post.html index 219e4b2..c6d9b4b 100644 --- a/example/to_generate/blog/post.html +++ b/example/to_generate/blog/post.html @@ -7,6 +7,7 @@ + @@ -28,7 +29,7 @@

[%= blogPost.getStructuredText("blog-post.body").getTitle().text %]

[%= blogPost.getStructuredText("blog-post.body").getFirstParagraph().text %] - index + [%- partial('/footer') %] diff --git a/example/to_generate/index.html b/example/to_generate/index.html index ad89a80..fb2425d 100644 --- a/example/to_generate/index.html +++ b/example/to_generate/index.html @@ -7,6 +7,7 @@ + @@ -18,7 +19,7 @@
blog
-
index
+ [%- partial('/footer') %] diff --git a/example/to_generate/product.html b/example/to_generate/product.html index bc43921..2a549e6 100644 --- a/example/to_generate/product.html +++ b/example/to_generate/product.html @@ -7,6 +7,7 @@ + @@ -27,7 +28,7 @@

[%= product.getText('product.name') %]

- index + [%- partial('/footer') %] diff --git a/example/to_generate/search.html b/example/to_generate/search.html index 9086e46..5ac7d23 100644 --- a/example/to_generate/search.html +++ b/example/to_generate/search.html @@ -7,6 +7,7 @@ + @@ -60,7 +61,7 @@

[% }) %] - index + [%- partial('/footer') %] diff --git a/package.json b/package.json index 3f6bed8..d3d5d3a 100644 --- a/package.json +++ b/package.json @@ -7,12 +7,12 @@ ], "devDependencies": { "ecstatic": "~0.5.3", - "gulp": "~3.6.2", + "ejs": "~1.0.0", + "gulp": "~3.7.0", "gulp-browserify": "~0.5.0", "gulp-concat": "~2.2.0", "gulp-watch": "~0.6.4", "http-server": "~0.6.1", - "jsdom": "~0.10.5", "lodash": "~2.4.1", "moment": "~2.6.0", "prismic.io": "~1.0.9", diff --git a/src/baked.js b/src/baked.js index dd33bf2..cd4c176 100644 --- a/src/baked.js +++ b/src/baked.js @@ -1,6 +1,7 @@ +var _ = require("lodash"); +var ejs = require("ejs"); var Prismic = require("prismic.io").Prismic; var Q = require("q"); -var _ = require("lodash"); (function (exporter, undefined) { "use strict"; @@ -8,8 +9,8 @@ var _ = require("lodash"); function getAPI(conf) { var deferred = Q.defer(); Prismic.Api(conf.api, function(err, api) { - if(err) { - conf.logger.error("Error while fetching Api at %s", conf.api, err); + if (err) { + err.url = conf.api; deferred.reject(err); } else deferred.resolve(api); @@ -34,11 +35,11 @@ var _ = require("lodash"); function renderTemplate(content, env, global) { var clean = cleanEnv(global); - return _.template(content, null, { - escape: /\[%-([\s\S]+?)%\]/g, - evaluate: /\[%([\s\S]+?)%\]/g, - interpolate: /\[%=([\s\S]+?)%\]/g, - }).call(env, _.assign({}, clean, env)); + return ejs.render(content, _.assign({}, env, { + scope: env, + open: '[%', + close: '%]' + })); } function renderContent(global, content, env) { @@ -67,74 +68,80 @@ var _ = require("lodash"); }); } - function initConf(global, window, opts) { - var document = window.document; + function initConf(global, opts) { var conf = { env: opts.env || {}, helpers: opts.helpers || {}, - logger: opts.logger || window.console, + logger: opts.logger, args: opts.args || {}, ref: opts.ref, accessToken: opts.accessToken, - api: opts.api + api: opts.api, + tmpl: opts.tmpl, + setEnv: opts.setEnv || _.noop }; // The Prismic.io API endpoint if (!conf.api) { - try { - conf.api = document.querySelector('head meta[name="prismic-api"]').content; - } catch(e) { - conf.logger.error('Please define your api endpoint in the element. For example: '); return; - } + conf.logger.error( + 'Please define your api endpoint in the element. ' + + 'For example: ' + + ''); + return; } // Extract the bindings conf.bindings = {}; - var queryScripts = document.querySelectorAll('script[type="text/prismic-query"]'); function toUpperCase(str, l) { return l.toUpperCase(); } - _.each(queryScripts, function(node) { + var scriptRx = /'; + return result.content.replace(/(<\/body>)/i, scriptTag + "\n$1"); + }); + }, ctx).then(function (result) { + return logAndTime("generate file '" + src + "' => '" + dst + "'", function () { + return createPath(dst, ctx).then(function () { + return Q.ninvoke(fs, 'writeFile', dst, result, "utf8"); }); }, ctx).then(function () { - return logAndTime("generate file '" + src + "' => '" + dst + "'", function () { - return Q.ninvoke(fs, 'writeFile', dst, window.document.innerHTML, "utf8"); - }, ctx).then(function () { - return dst; - }); + return dst; }); }); } @@ -151,7 +143,7 @@ var Router = require("./router"); return Q .ninvoke(fs, 'readFile', src, "utf8") .then(function (content) { - if (!router.isTemplate(src)) { + if (!router.isBakedTemplate(src)) { return copyFile(name, src, content, dst, ctx); } else if (!router.isDynamic(src)) { var file = src @@ -176,10 +168,7 @@ var Router = require("./router"); function saveTemplate(name, src, content, dst, ctx) { var tmpl_dst = dst + ".tmpl"; return logAndTime("create template '" + src + "' => '" + tmpl_dst + "'", function () { - return withWindow(content) - .then(function (window) { - return copyFile(name, src, window.document.body.innerHTML, tmpl_dst, ctx); - }); + return copyFile(name, src, content, tmpl_dst, ctx); }, ctx); } @@ -247,7 +236,11 @@ var Router = require("./router"); function buildRouterForFile(name, src, ctx) { return logAndTime("Build router for file '" + src + "'", function () { - if (/\.html$/.test(name)) { + if (Router.isPartial(name)) { + var result = {}; + result[src] = {partial: true}; + return result; + } else if (Router.isTemplate(name)) { return Q .ninvoke(fs, 'readFile', src, "utf8") .then(function (content) {