diff --git a/realms/modules/wiki/models.py b/realms/modules/wiki/models.py index 703d240..3387da4 100644 --- a/realms/modules/wiki/models.py +++ b/realms/modules/wiki/models.py @@ -191,16 +191,10 @@ class WikiPage(HookMixin): return len(cached_revs), True @property - def partials(self): - data = self.data - if not data: - return {} - partials = {} - meta = self._get_meta(data) - if meta and 'import' in meta: - for partial_name in meta['import']: - partials[partial_name] = self.wiki.get_page(partial_name, sha=self.sha) - return partials + def imports(self): + """Names""" + meta = self._get_meta(self.data) or {} + return meta.get('import', []) @staticmethod def _get_meta(content): diff --git a/realms/modules/wiki/static/js/editor.js b/realms/modules/wiki/static/js/editor.js index 6340f58..fb17988 100644 --- a/realms/modules/wiki/static/js/editor.js +++ b/realms/modules/wiki/static/js/editor.js @@ -82,10 +82,26 @@ var deletePage = function() { bootbox.alert('Error deleting page!'); }); }; - +var last_imports = ''; +var partials = []; var aced = new Aced({ editor: $('#entry-markdown-content').find('.editor').attr('id'), - renderer: function(md) { return MDR.convert(md) }, + renderer: function(md) { + var doc = metaMarked(md); + if (doc.meta && 'import' in doc.meta) { + // If the imports have changed, refresh them from the server + if (doc.meta['import'].toString() != last_imports) { + last_imports = doc.meta['import'].toString(); + $.getJSON('/_partials', {'imports': doc.meta['import']}, function (response) { + partials = response['partials']; + // TODO: Better way to force update of the preview here than this fake signal? + aced.editor.session.doc._signal('change', + {'action': 'insert', 'lines': [], 'start': {'row': 0}, 'end': {'row': 0}}); + }); + } + } + return MDR.convert(md, partials) + }, info: Commit.info, submit: function(content) { var data = { diff --git a/realms/modules/wiki/templates/wiki/edit.html b/realms/modules/wiki/templates/wiki/edit.html index aef6a3b..3ee82c6 100644 --- a/realms/modules/wiki/templates/wiki/edit.html +++ b/realms/modules/wiki/templates/wiki/edit.html @@ -8,22 +8,6 @@ - {% if partials %} - - {% endif %} - {% if config.get('COLLABORATION') %} {% endif %} diff --git a/realms/modules/wiki/templates/wiki/page.html b/realms/modules/wiki/templates/wiki/page.html index bd40d7f..167f113 100644 --- a/realms/modules/wiki/templates/wiki/page.html +++ b/realms/modules/wiki/templates/wiki/page.html @@ -23,12 +23,7 @@ {% block js %} -{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/realms/modules/wiki/views.py b/realms/modules/wiki/views.py index 2db60ed..528e29a 100644 --- a/realms/modules/wiki/views.py +++ b/realms/modules/wiki/views.py @@ -1,5 +1,6 @@ from __future__ import absolute_import +import collections import itertools import sys from datetime import datetime @@ -27,7 +28,9 @@ def commit(name, sha): if not data: abort(404) - return render_template('wiki/page.html', name=name, page=data, commit=sha) + partials = _partials(data.imports, sha=sha) + + return render_template('wiki/page.html', name=name, page=data, commit=sha, partials=partials) @blueprint.route(r"/_compare//") @@ -103,7 +106,6 @@ def history_data(name): } - @blueprint.route("/_edit/") @login_required def edit(name): @@ -120,8 +122,32 @@ def edit(name): content=page.data, # TODO: Remove this? See #148 info=next(page.history), - sha=page.sha, - partials=page.partials) + sha=page.sha) + + +def _partials(imports, sha='HEAD'): + page_queue = collections.deque(imports) + partials = collections.OrderedDict() + while page_queue: + page_name = page_queue.popleft() + if page_name in partials: + continue + page = g.current_wiki.get_page(page_name, sha=sha) + try: + partials[page_name] = page.data + except KeyError: + partials[page_name] = "`Error importing wiki page '{0}'`".format(page_name) + continue + page_queue.extend(page.imports) + # We want to retain the order (and reverse it) so that combining metadata from the imports works + return list(reversed(partials.items())) + + +@blueprint.route("/_partials") +def partials(): + if current_app.config.get('PRIVATE_WIKI') and current_user.is_anonymous(): + return current_app.login_manager.unauthorized() + return {'partials': _partials(request.args.getlist('imports[]'))} @blueprint.route("/_create/", defaults={'name': None}) @@ -245,6 +271,6 @@ def page(name): data = g.current_wiki.get_page(cname) if data: - return render_template('wiki/page.html', name=cname, page=data, partials=data.partials) + return render_template('wiki/page.html', name=cname, page=data, partials=_partials(data.imports)) else: return redirect(url_for('wiki.create', name=cname)) diff --git a/realms/static/js/mdr.js b/realms/static/js/mdr.js index a776496..6522973 100644 --- a/realms/static/js/mdr.js +++ b/realms/static/js/mdr.js @@ -70,11 +70,12 @@ var MDR = { parse: function(md){ return markdownit.render(md); }, - convert: function(md, sanitize) { + convert: function(md, partials, sanitize) { if (this.sanitize !== null) { sanitize = this.sanitize; } this.md = md; + this.partials = partials; this.processMeta(); try { var html = this.parse(this.md); @@ -105,7 +106,15 @@ var MDR = { processMeta: function() { var doc = metaMarked(this.md); this.md = doc.md; - this.meta = doc.meta; + var meta = this.meta = {}; + if (this.partials) { + $.each(this.partials, function(index, item) { + var doc = metaMarked(item[1]); + Handlebars.registerPartial(item[0], doc.md); + $.extend(meta, doc.meta); + }) + } + $.extend(this.meta, doc.meta); if (this.meta) { try { var template = Handlebars.compile(this.md);