Example #1
0
            fetchContent(_.bind(function(err, content) {
                if (err) {
                    if (typeof(err) == "object") {
                        this._renderError(err.code, err.description, req, res);  
                    } else {
                        this._renderError(500, "Not authorized", req, res);  
                    }
                } else {
                    blog.app.loadResources(req, abind(function(err, results) {
                        this._compileTemplates(abind(function(err) {
                            handlebars.registerPartial('content', this.templates[templateName]);

                            var stylesheets = results.stylesheets;
                            _.each(content.stylesheets, function(url) {
                                var tag = '<link rel="stylesheet" href="' + url + '">';
                                stylesheets += '\n' + tag;
                            });

                            var scripts = results.scripts;
                            _.each(content.scripts, function(url) {
                                var tag = '<script type="text/javascript" src="' + url + '"></script>';
                                scripts += '\n' + tag;
                            });

                            content.scripts = scripts;
                            content.stylesheets = stylesheets;

                            var url = 'http://' + blog.host + req.url;
                            var templateData = {
                                blog: blog,
                                url: url,
                                description: '',
                                icon: '',
                                scripts: scripts,
                                stylesheets: stylesheets,
                                icons: results.icons
                            };
                            for (var name in content.data) {
                                templateData[name] = content.data[name];
                            }

                            var template = this.templates['index'];
                            var html = template(templateData);

                            var deps = [];
                            // deps.push.apply(deps, content.dependencies);
                            deps.push.apply(deps, this.templateDependencies);

                            if (content.error) {
                                cb({error: content.error}, {mimeType: htmlMimeType, body: html});
                            } else {
                                cb(0, {
                                    dependencies: deps,
                                    mimeType: htmlMimeType,
                                    body: html});
                            }
                        }, cb, this));
                    }, cb, this));
                }
            }, this));
Example #2
0
        this._renderPage(templateName, req, res, _.bind(function(cb) {
            fetchPosts(abind(function(err, posts) {
                if (!posts.length) {
                    cb({code: 404});
                } else {
                    var isPost = req.url != '/' && posts.length == 1;

                    var title = isPost
                        ? posts[0].title
                        : blog.title;

                    var pageTitle = isPost
                        ? posts[0].title + ' - ' + blog.title
                        : blog.title;

                    var description = isPost
                        ? posts[0].description
                        : blog.description;

                    var icon = isPost
                        ? posts[0].icon
                        : '';

                    var scripts = [];
                    var stylesheets = [];
                    _.each(posts, function(post) {
                        _.each(post.stylesheets, function(url) {
                            stylesheets.push(url);
                        });
                    });

                    var deps = _.map(posts, function(post) {
                        return {path: post.path, mtime: post.mtime.getTime()}
                    });

                    cb(0, {
                        dependencies: deps,
                        stylesheets: stylesheets,
                        scripts: scripts,
                        data: {
                            title: title,
                            description: description,
                            icon: icon,
                            pageTitle: pageTitle,
                            posts: posts
                        }
                    });
                }
            }, cb, this));
        }));
Example #3
0
 ibind(function(next) {
     hascan.getFeatureDB(_.keys(deps.has), abind(function(err, featureDB) {
         this.featureDB = featureDB;
         next(0);
     }, next, this));                        
 }, cb, this),
Example #4
0
 _loadPolyfills: function(renderer, options, cb) {
     renderer.renderPolyfills(options, abind(function(err, result) {
         cb(0, {path: result.path, body: result.source, dependencies: result.dependencies});
     }, cb));
 },
Example #5
0
 pkg.searchScript(this.client, searchPaths, abind(function(err, findings) {
     pkg.findPackageInfo(findings.path, abind(function(err, result) {
         this.packageName = result.info.name;
         next(0);
     }, cb, this));
 }, cb, this));
Example #6
0
 loadResources: function(req, cb) {
     var options = readOptions(req, this);
     this._prepare(abind(function(err) {
         this.renderer.renderResources(options, cb);            
     }, cb, this));
 },
Example #7
0
 fs.stat(filePath, abind(function(err, stat) {
     var dependencies = [{path: filePath, mtime: stat.mtime.getTime()}];
     fs.readFile(filePath, abind(function(err, source) {
         send.call(this, {path: filePath, body: source, error: err}, !!err);
     }, next, this));                  
 }, next, this));
Example #8
0
 _statAndParsePosts: function(fileBody, filePath, cb) {
     fs.lstat(filePath, abind(function(err, stat) {
         this._parsePosts(fileBody, filePath, stat, cb);
     }, cb, this));
 },
Example #9
0
 _parsePostsFile: function(filePath, cb) {
     fs.readFile(filePath, abind(function(err, fileBody) {
         this._statAndParsePosts(fileBody, filePath, cb);
     }, cb, this));
 },
Example #10
0
 function returnResult(result) {
     fs.lstat(result.path, abind(function(err, stat) {
         result.timestamp = stat.mtime.getTime();
         cb(0, result);
     }, cb, this));
 }
Example #11
0
    reload: function(cb) {
        if (!this.isInvalid) {
            if (cb) cb(0);
            return;
        }

        var firstLoad = !this.posts;
        var postMap = {};

        if (this.posts) {
            this.posts.forEach(function(post) {
               if (post.path in postMap) {
                    postMap[post.path].push(post);
                } else {
                    postMap[post.path] = [post];
                }
            });
        }

        var newPosts = [];
        var events = [];

        this.statPosts(abind(function(err, statMap) {
            var remaining = _.keys(statMap).length;
            if (!remaining) {
                complete.apply(this);
            }

            _.each(statMap, ibind(function(mtime, filePath) {
                if (!postMap[filePath]) {
                    this._parsePostsFile(filePath, abind(function(err, posts) {
                        newPosts.push.apply(newPosts, posts);

                        if (!firstLoad) {
                            posts.forEach(ibind(function(post) {
                                D&&D('post created', post.title);

                                events.push({event: 'postCreated', post: post});
                            }, cb, this));
                        }
                        next.apply(this);
                    }, cb, this));
                } else {
                    var previousPosts = postMap[filePath];
                    var previousPost = previousPosts[0];
                    if (mtime > previousPost.mtime) {
                        this._parsePostsFile(filePath, abind( function(err, posts) {
                            newPosts.push.apply(newPosts, posts);

                            _.each(posts, ibind(function(post, index) {
                                var existingPost = _.detect(previousPosts, function(oldPost) {
                                    return oldPost.url == post.url;
                                });
                                if (existingPost) {
                                    var index = previousPosts.indexOf(existingPost);
                                    previousPosts.splice(index, 1);
                                    if (!this._postsAreEqual(post, existingPost)) {
                                        D&&D('post changed', post.title);
                                        events.push({name: 'postChanged', post: post});
                                    }
                                } else {
                                    D&&D('post created', post.title);
                                    events.push({name: 'postCreated', post: post});
                                }
                            }, cb, this));

                            // Delete posts that have been removed from their file
                            _.each(previousPosts, ibind(function(oldPost) {
                                D&&D('post deleted', oldPost.title);
                                events.push({name: 'postDeleted', post: oldPost});
                            }, cb, this));
    
                            delete postMap[filePath];
                            next.apply(this);
                        }, cb, this));
                    } else {
                        newPosts.push.apply(newPosts, previousPosts);
                        delete postMap[filePath];
                        next.apply(this);
                    }
                }
           }, cb, this));

           function next() {
               if (!--remaining) {
                   complete.apply(this);
               }
           }

           function complete() {
                // Delete posts in files that have been deleted
                _.each(postMap, ibind(function(posts, path) {
                    _.each(posts, ibind(function(oldPost) {
                        D&&D('post deleted', oldPost.title);
                        events.push({name: 'postDeleted', post: oldPost});
                    }, cb, this));
               }, cb, this));

               this._assignPosts(newPosts);

               _.each(events, _.bind(function(event) {
                   this.emit(event.name, event.post);
                   this.onPostModified(event.post);
               }, this));

               if (!this.isMonitoring) {
                   this.monitorAll(cb);
               } else {
                   cb(0);
               }
           }
        }, cb, this));
    },
Example #12
0
    renderPost: function(post, mode, cb) {
        // Performs nerve-specific parsing
        var transformer = new NerveTransformer(this);
        transformer.visit(post.tree);

        post.definitions = transformer.definitions
        if (post.definitions.icon) {
            post.icon = this.normalizeImageURL(post.definitions.icon);
        }

        // Asynchronously render each of the embeds
        async.mapSeries(transformer.embeds,
            _.bind(function(embed, cb2) {
                this.renderEmbed(embed, post, cb2);
            }, this),

            abind(function(err, embeds) {
                step2.apply(this);
            }, cb, this)
        );

        function step2() {
            async.mapSeries(transformer.figures, _.bind(function(node, cb2) {
                this._findScript(node.attributes['require'], _.bind(function(err, result) {
                    if (err) {
                        node.addClass('figureNotFound');
                        node.removeAttribute('figure');
                        node.removeAttribute('require');
                        cb2(0);
                    } else {
                        if (process.env.NODE_ENV == "production") {
                            node.setAttribute('timestamp', result.timestamp);
                        }
                        node.setAttribute('require', result.name);
                        cb2(0);
                    }
                }));
            }, this),
            _.bind(function(err) {
                step3.apply(this);
            }, this));
        }

        function step3() {
            if (mode == 'rss') {
                var rssTransformer = new RSSTransformer(this);
                var rssTree = post.tree.clone();
                rssTransformer.visit(rssTree);

                post.rssBody = markdom.toHTML(rssTree);
            } else {
                post.body = markdom.toHTML(post.tree);
            }

            if (post.stylesheetName) {
                this._findStylesheet(post.stylesheetName, _.bind(function(err, result) {
                    if (!err) {
                        var stylesheetURL = this.app.staticPath + '/' + result.path;
                        stylesheetURL = this.app.normalizeURL(stylesheetURL, null, result.timestamp);
                        post.stylesheets = [stylesheetURL];
                    }
                    cb(0, post);
                }, this));
            } else {
                cb(0, post);
            }
        }
    },
Example #13
0
 exports.findPackagePath(scriptPath, abind(function(err, packagePath) {
     fs.readFile(packagePath, abind(function(err, packageJSON) {
         var packageInfo = JSON.parse(packageJSON);
         cb(0, {path: packagePath, info: packageInfo});
     }, cb));
 }, cb));
Example #14
0
 renderHas: function(options, cb) {
     var deps = this.app.dependencies;
     hascan.buildHasWithTests(_.keys(deps.has), abind(function(err, source) {
         cb(0, {path: 'has.js', source: source, dependencies: _.values(deps.js)});
     }, cb, this))
 },
Example #15
0
 this._renderPage({}, options, abind(function(err, html) {
     this.renderContent(URL, html, options, abind(function(err, html) {
         cb(0, {source: html, dependencies: this.app.dependencies.js});
     }, cb, this));
 }, cb, this));
Example #16
0
    renderScriptInline: function(scriptPath, modulePath, options, cb) {
        var sandbox = [];
        var headers = [];
        var bodies = [];
        var deps = [];

        async.waterfall([
            ibind(function(next) {
                options.featureMap = options.userAgent && this.app.featureDB
                    // For client-side rendering, attempt to find a precomputed feature map
                    ? this.app.featureDB.getFeatureMap(options.userAgent, true)
                    // For server-side rendering, the only feature supported is "appjs"
                    : {appjs: 1};

                this._loadURL(this.app.polyfillsPath, options, next);
            }, cb, this),

            ibind(function(polyfillsData, next) {
                deps.push.apply(deps, polyfillsData.dependencies);

                sandbox.push(polyfillsData.body);

                this._loadURL(this.app.resourceBase, options, next);
            }, cb, this),

            ibind(function(appjsData, next) {
                deps.push.apply(deps, appjsData.dependencies);

                sandbox.push(appjsData.body);

                if (!options.featureMap) {
                    this._loadURL(this.app.hasPath, options, next);
                } else {
                    next(0, '');
                }
            }, cb, this),

            ibind(function(hasjsData, next) {
                if (hasjsData) {
                    deps.push.apply(deps, hasjsData.dependencies);
                    sandbox.push(hasjsData.body);
                }

                this._inlineScript(scriptPath, modulePath, deps, options, next);
            }, cb, this),

            ibind(function(result, next) {
                bodies.push(result.source);

                if (options.js == "standalone") {
                    this.renderStylesheet({css: "inline", images: options.images}, abind(function(err, result) {
                        sandbox.push(""
                            + "(function() {"
                            + "var ss = document.createElement('style');"
                            + "ss.innerHTML = " + JSON.stringify(result.source) + ";"
                            + "document.head.appendChild(ss);"
                            + "})();");
                        next(0);
                    }, cb, this));
                } else {
                    next(0);
                }
            }, cb, this),
        ],
        abind(function(err, result) {

            var source = this._concatScript(modulePath, sandbox, headers, bodies, options);
            cb(0, {path: 'all.js', source: source, dependencies: deps});
        }, cb, this));
    },