Mercurial > wikked
changeset 40:81333391792d
Moved client code from HTML template to `views.js`.
Better handle relative vs. absolute page URLs in wiki links.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Mon, 07 Jan 2013 15:31:17 -0800 |
parents | 7ec7cf21840a |
children | ef9cf617d76f |
files | wikked/static/js/wikked.js wikked/static/js/wikked/client.js wikked/static/js/wikked/views.js wikked/static/tpl/edit-page.html wikked/wiki.py |
diffstat | 5 files changed, 125 insertions(+), 63 deletions(-) [+] |
line wrap: on
line diff
--- a/wikked/static/js/wikked.js Sun Jan 06 23:17:16 2013 -0800 +++ b/wikked/static/js/wikked.js Mon Jan 07 15:31:17 2013 -0800 @@ -37,17 +37,16 @@ /** * Entry point: run Backbone! * - * We also import scripts like `handlebars` and `client` that - * are not used directly by anybody, but need to be evaluated. + * We also import scripts like `handlebars` that are not used directly + * by anybody, but need to be evaluated. */ require([ - 'wikked/app', - 'wikked/handlebars', - 'wikked/client', + 'wikked/app', + 'wikked/handlebars', 'backbone', 'bootstrap' ], - function(app, hb, client, Backbone) { + function(app, hb, Backbone) { var router = new app.Router(); Backbone.history.start();//{ pushState: true });
--- a/wikked/static/js/wikked/client.js Sun Jan 06 23:17:16 2013 -0800 +++ b/wikked/static/js/wikked/client.js Mon Jan 07 15:31:17 2013 -0800 @@ -1,8 +1,16 @@ /** * Client-side Wikked. */ -define(function() { +define([ + 'jquery', + 'underscore' + ], + function($, _) { + /** + * Lookup table and function to remove accentuated/alternate characters + * with their ASCII equivalent. + */ var defaultDiacriticsRemovalMap = [ {'base':'A', 'letters':/[\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F]/g}, {'base':'AA','letters':/[\uA732]/g}, @@ -99,9 +107,61 @@ return str; } - var PageFormatter = { + /** + * Function to normalize an array of path parts (remove/simplify `./` and + * `../` elements). + */ + function normalizeArray(parts, keepBlanks) { + var directories = [], prev; + for (var i = 0, l = parts.length - 1; i <= l; i++) { + var directory = parts[i]; + + // if it's blank, but it's not the first thing, and not the last thing, skip it. + if (directory === "" && i !== 0 && i !== l && !keepBlanks) + continue; + + // if it's a dot, and there was some previous dir already, then skip it. + if (directory === "." && prev !== undefined) + continue; + + // if it starts with "", and is a . or .., then skip it. + if (directories.length === 1 && directories[0] === "" && ( + directory === "." || directory === "..")) + continue; + + if ( + directory === ".." && directories.length && prev !== ".." && prev !== "." && prev !== undefined && (prev !== "" || keepBlanks)) { + directories.pop(); + prev = directories.slice(-1)[0] + } else { + if (prev === ".") directories.pop(); + directories.push(directory); + prev = directory; + } + } + return directories; + } + + /** + * Client-side page formatter, with support for previewing meta properties + * in the live preview window. + */ + var PageFormatter = function(baseUrl) { + this.baseUrl = baseUrl; + if (baseUrl === undefined) { + this.baseUrl = ''; + } + }; + _.extend(PageFormatter.prototype, { formatLink: function(link) { - ansi_link = removeDiacritics(link); + var abs_link = link; + if (link[0] == '/') { + abs_link = link.substring(1); + } else { + raw_abs_link = this.baseUrl + link + abs_link = normalizeArray(raw_abs_link.split('/')).join('/'); + } + ansi_link = removeDiacritics(abs_link); return ansi_link.toLowerCase().replace(/[^a-z0-9_\.\-\(\)\/]+/g, '-'); }, formatText: function(text) { @@ -126,11 +186,7 @@ }); return text; } - }; - //TODO: remove this and move the JS code from the template to the view. - if (!window.Wikked) - window.Wikked = {}; - window.Wikked.PageFormatter = PageFormatter; + }); return { PageFormatter: PageFormatter
--- a/wikked/static/js/wikked/views.js Sun Jan 06 23:17:16 2013 -0800 +++ b/wikked/static/js/wikked/views.js Mon Jan 07 15:31:17 2013 -0800 @@ -6,10 +6,11 @@ 'underscore', 'backbone', 'handlebars', + './client', './models', './util' ], - function($, _, Backbone, Handlebars, Models, Util) { + function($, _, Backbone, Handlebars, Client, Models, Util) { var exports = {}; @@ -229,6 +230,49 @@ }, renderCallback: function(view, model) { PageEditView.__super__.renderCallback.apply(this, arguments); + + // Create the Markdown editor. + var formatter = new Client.PageFormatter(); + formatter.baseUrl = this.model.get('path').match(/.*\//); + var converter = new Markdown.Converter(); + converter.hooks.chain("preConversion", function(text) { + return formatter.formatText(text); + }); + var editor = new Markdown.Editor(converter); //TODO: pass options + editor.run(); + var editor_control = this.$('textarea#wmd-input'); + editor_control.outerWidth(this.$('.wmd-input-wrapper').innerWidth()); + + // Input area resizing with the grip. + var last_pageY; + this.$(".wmd-input-grip") + .mousedown(function(e) { + last_pageY = e.pageY; + $('body') + .on('mousemove.wikked.editor_resize', function(e) { + editor_control.height(editor_control.height() + e.pageY - last_pageY); + last_pageY = e.pageY; + }) + .on('mouseup.wikked.editor_resize mouseleave.wikked.editor_resize', function(e) { + $('body').off('.wikked.editor_resize'); + }); + }); + + // Show/hide live preview. + this.$('.wmd-preview-wrapper>h3>a').on('click', function(e) { + $('#wmd-preview').fadeToggle(function() { + var icon = $('.wmd-preview-wrapper>h3>a i'); + if (icon.hasClass('icon-minus')) { + icon.removeClass('icon-minus'); + icon.addClass('icon-plus'); + } else { + icon.removeClass('icon-plus'); + icon.addClass('icon-minus'); + } + }); + }); + + // Make the model submit the form. this.$('#page-edit').submit(function(e) { e.preventDefault(); model.doEdit(this);
--- a/wikked/static/tpl/edit-page.html Sun Jan 06 23:17:16 2013 -0800 +++ b/wikked/static/tpl/edit-page.html Mon Jan 07 15:31:17 2013 -0800 @@ -39,49 +39,3 @@ <script type="text/javascript" src="/js/pagedown/Markdown.Converter.js"></script> <script type="text/javascript" src="/js/pagedown/Markdown.Sanitizer.js"></script> <script type="text/javascript" src="/js/pagedown/Markdown.Editor.js"></script> -<script type="text/javascript"> - (function() { - var formatter = _.extend(this.Wikked.PageFormatter, {}); - var converter = new Markdown.Converter(); - converter.hooks.chain("preConversion", function(text) { - return formatter.formatText(text); - }); - - //var help = function () { alert("Do you need help?"); } - //var options = { - // helpButton: { handler: help }, - // strings: { quoteexample: "whatever you're quoting, put it right here" } - //}; - var editor = new Markdown.Editor(converter); //TODO: pass options - editor.run(); - - var editor_control = $('textarea#wmd-input'); - editor_control.outerWidth($('.wmd-input-wrapper').innerWidth()); - - var last_pageY; - $(".wmd-input-grip") - .mousedown(function(e) { - last_pageY = e.pageY; - $('body') - .on('mousemove.wikked.editor_resize', function(e) { - editor_control.height(editor_control.height() + e.pageY - last_pageY); - last_pageY = e.pageY; - }) - .on('mouseup.wikked.editor_resize mouseleave.wikked.editor_resize', function(e) { - $('body').off('.wikked.editor_resize'); - }); - }); - $('.wmd-preview-wrapper>h3>a').on('click', function(e) { - $('#wmd-preview').fadeToggle(function() { - var icon = $('.wmd-preview-wrapper>h3>a i'); - if (icon.hasClass('icon-minus')) { - icon.removeClass('icon-minus'); - icon.addClass('icon-plus'); - } else { - icon.removeClass('icon-plus'); - icon.addClass('icon-minus'); - } - }); - }); - })(); -</script>
--- a/wikked/wiki.py Sun Jan 06 23:17:16 2013 -0800 +++ b/wikked/wiki.py Mon Jan 07 15:31:17 2013 -0800 @@ -95,7 +95,16 @@ return text def _formatWikiLink(self, ctx, display, url): - slug = Page.title_to_url(os.path.join(ctx.urldir, url)) + if url.startswith('/'): + # Absolute page URL. + abs_url = url[1:] + else: + # Relative page URL. Let's normalize all `..` in it, + # which could also replace forward slashes by backslashes + # on Windows, so we need to convert that back. + raw_abs_url = os.path.join(ctx.urldir, url) + abs_url = os.path.normpath(raw_abs_url).replace('\\', '/') + slug = Page.title_to_url(abs_url) ctx.out_links.append(slug) css_class = 'wiki-link' @@ -260,7 +269,7 @@ self.fs = FileSystem(root, slugify=Page.title_to_url) self.auth = UserManager(self.config, logger=self.logger) self.index = WhooshWikiIndex(os.path.join(root, '.index'), logger=self.logger) - + scm_type = 'hg' if self.config.has_option('wiki', 'scm'): scm_type = self.config.get('wiki', 'scm')