// The Antville Project // http://code.google.com/p/antville // // Copyright 2001–2014 by the Workers of Antville. // // Licensed under the Apache License, Version 2.0 (the ``License''); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. relocateProperty(Story, "createtime", "created"); relocateProperty(Story, "modifytime", "modified"); Story.ALLOWED_MACROS = Story.ALLOWED_MACROS.concat([ "fakemail", "imageoftheday", "logo", "spacer", "storylist", "thumbnail", "site.image", "site.link", "site.thumbnail", "story.image", "story.thumbnail", "story.topic", "this.image", "this.link", "this.thumbnail", "this.topic" ]); Story.prototype.rotate_action = function() { if (this.status === Story.CLOSED) { this.status = this.cache.status || Story.PUBLIC; } else if (this.mode === Story.FEATURED) { this.mode = Story.HIDDEN; } else { this.cache.status = this.status; this.mode = Story.FEATURED; this.status = Story.CLOSED; } return res.redirect(req.data.http_referer || this._parent.href()); } /** * * @param {Object} param * @param {String} action * @param {String} text */ Story.prototype.link_macro = function(param, action, text) { switch (action) { case 'rotate': if (this.status === Story.CLOSED) { text = param.publish || gettext('Publish'); } else if (this.mode === Story.FEATURED) { text = param.hide || gettext('Hide'); } else { text = param.close || gettext('Close'); } delete param.publish; delete param.hide; delete param.close; } return HopObject.prototype.link_macro.call(this, param, action, text); } Story.prototype.backlinks_macro = Story.prototype.referrers_macro; Story.prototype.allowTextMacros = function(skin) { return Story.prototype.macro_filter(skin); } Story.prototype.commentform_macro = function(param) { if (this.site.commentMode === Site.DISABLED || this.commentMode === Story.CLOSED) { return; } if (session.user) { res.data.action = this.href("comment"); res.handlers.parent = this; HopObject.confirmConstructor(Comment); var comment = new Comment; comment.story = this; comment.renderSkin("Comment#edit"); } else { html.link({href: this.site.members.href("login")}, param.text || "Please login to add a comment"); } return; } Story.prototype.content_macro = function(param) { // Clone param and remove non-HTML attributes from param: var options = Object.clone.call(param, {}); var noAttr = 'as clipping delimiter fallback limit part'; for (let key of noAttr.split(String.SPACE)) { delete param[key]; } switch (options.as) { case "editor": if (param.cols || param.rows) { this.textarea_macro(param, options.part); } else { this.input_macro(param, options.part); } break; case "image": var part = this.getMetadata(options.part); part && res.write(this.format_filter(part, param, "image")); break; default: var part = this.getRenderedContentPart(options.part, options.as); if (!part && options.fallback) { part = this.getRenderedContentPart(options.fallback, options.as); } if (options.limit) { part = part.stripTags().head(options.limit, options.clipping, options.delimiter || String.SPACE); } if (options.as === "link") { res.write(this.link_filter(part || "...", param)); } else { res.write(part); } } return; } Story.prototype.getRenderedContentPart = function(name, mode) { var part = this.getMetadata(name); if (!part) { return ""; } var key = mode ? (name + ":" + mode) : name; var lastRendered = this.cache["lastRendered_" + key]; if (!lastRendered) { // FIXME: || lastRendered.getTime() < this.metadata.getLastModified().getTime()) switch (mode) { case "plaintext": part = this.format_filter(part, {}, "plain"); break; case "alttext": part = this.format_filter(part, {}, "quotes"); break; default: // Enable caching; some macros (eg. poll, storylist) will set this // to false to prevent caching of a contentpart containing them. res.meta.cachePart = true; part = this.format_filter(part, {}, "markdown"); } this.cache[key] = part; if (res.meta.cachePart) { this.cache["lastRendered_" + key] = new Date(); } } return this.cache[key]; } Story.prototype.location_macro = function(param) { switch (this.mode) { case Story.FEATURED: res.write("site"); break; default: if (this.tags.size() > 0) { html.link({href: this.tags.get(0).tag.href()}, "topic"); } } return; } Story.prototype.topic_macro = function(param) { // This method is applied to images as well, thus we check what we got first: if (this.constructor !== Image && this.status !== Story.PUBLIC) { return; } if (this.tags.size() < 1) { return; } var tag = this.tags.get(0).tag; if (!tag) { return; } if (!param.as || param.as === "text") { res.write(tag.name); } else if (param.as === "link") { html.link({href: tag.href()}, param.text || tag.name); } else if (param.as === "image") { param.imgprefix || (param.imgprefix = "topic_"); var img = HopObject.getFromPath(param.imgprefix + tag.name, "images"); delete param.imgprefix; delete param.as; if (img) { res.push(); img.render_macro(param); delete param.height; delete param.width; delete param.border; delete param.src; delete param.alt; link_filter(res.pop(), param, tag.href()); } } return; } Story.prototype.topicchooser_macro = function(param) { var site = this.site || res.handlers.site; var currentTopic = this.tags.size() > 0 ? this.tags.get(0).tag : null; var topics = (this.constructor === Story ? site.stories.tags : site.images.galleries); var options = [], topic; for (var i=0; i 0); if (linkflag) { html.openTag("a", {href: this.href() + "#comments"}); } if (commentCnt < 1) { res.write(param.no || "no comments"); } else if (commentCnt < 2) { res.write(param.one || "one comment"); } else { res.write(commentCnt + (param.more || " " + "comments")); } if (linkflag) { html.closeTag("a"); } return; } Story.prototype.reads_macro = function(param) { res.write(this.requests); return; } Story.prototype.summary_macro = function(param) { param.limit || (param.limit = 15); var keys, summary; if (arguments.length > 1) { res.push(); var content; for (var i=1; i'); res.write(tail); return; }