def publish_listener(sender, *args, **kwargs):
- sender.book.touch()
- for c in sender.book:
+ sender.touch()
+ for c in sender:
c.touch()
-post_publish.connect(publish_listener)
+post_publish.connect(publish_listener, sender=Book)
+def publish_listener(sender, *args, **kwargs):
+ sender.touch()
+post_publish.connect(publish_listener, sender=Image)
+
+
+def chunk_publishable_listener(sender, *args, **kwargs):
+ sender.tree.touch()
+ if isinstance(sender.tree, Chunk):
+ sender.tree.book.touch()
+post_publishable.connect(chunk_publishable_listener)
def publishable_listener(sender, *args, **kwargs):
sender.tree.touch()
- sender.tree.book.touch()
-post_publishable.connect(publishable_listener)
+post_publishable.connect(publishable_listener, sender=Image)
def listener_create(sender, instance, created, **kwargs):
{% endblock %}
{% block dialogs %}
- {% include "wiki_img/save_dialog.html" %}
+ {% include "wiki/save_dialog.html" %}
+ {% include "wiki/revert_dialog.html" %}
+ {% if can_pubmark %}
+ {% include "wiki/pubmark_dialog.html" %}
+ {% endif %}
{% endblock %}
{% block editor-class %}
+++ /dev/null
-{% load i18n %}
-<div id="save_dialog" class="dialog" data-ui-jsclass="SaveDialog">
- <form method="POST" action="">
- {% csrf_token %}
- <p>{{ forms.text_save.comment.label }}</p>
- <p class="help_text">
- {{ forms.text_save.comment.help_text}}
- <span data-ui-error-for="{{ forms.text_save.comment.name }}"> </span>
- </p>
- {{forms.text_save.comment }}
-
-
-
- {% for f in forms.text_save.hidden_fields %}
- {{ f }}
- {% endfor %}
-
- <p data-ui-error-for="__all__"> </p>
-
- <p class="action_area">
- <button type="submit" class"ok" data-ui-action="save">Zapisz</button>
- <button type="button" class="cancel" data-ui-action="cancel">Anuluj</button>
- </p>
- </form>
-</div>
+++ /dev/null
-{% load i18n %}
-<div id="add_tag_dialog" class="dialog" data-ui-jsclass="AddTagDialog">
- <form method="POST" action="#">
- {% for field in forms.add_tag.visible_fields %}
- <p>{{ field.label_tag }} {{ field }} <span data-ui-error-for="{{ field.name }}"> </span></p>
- <p>{{ field.help_text }}</p>
- {% endfor %}
-
- {% for f in forms.add_tag.hidden_fields %}
- {{ f }}
- {% endfor %}
- <p data-ui-error-for="__all__"> </p>
-
- <p class="action_area">
- <button type="submit" class"ok" data-ui-action="save">{% trans "Save" %}</button>
- <button type="button" class="cancel" data-ui-action="cancel">{% trans "Cancel" %}</button>
- </p>
- </form>
-</div>
url(r'^text/(?P<image_id>\d+)/$',
'text', name="wiki_img_text"),
- url(r'^history/(?P<chunk_id>\d+)/$',
- 'history', name="wiki_history"),
+ url(r'^history/(?P<object_id>\d+)/$',
+ 'history', name="wiki_img_history"),
+
+ url(r'^revert/(?P<object_id>\d+)/$',
+ 'revert', name='wiki_img_revert'),
+
+ url(r'^diff/(?P<object_id>\d+)/$', 'diff', name="wiki_img_diff"),
+ url(r'^pubmark/(?P<object_id>\d+)/$', 'pubmark', name="wiki_img_pubmark"),
)
from django.views.generic.simple import direct_to_template
from django.core.urlresolvers import reverse
-from wiki.helpers import JSONResponse
+from wiki.helpers import (JSONResponse, JSONFormInvalid, JSONServerError,
+ ajax_require_permission)
+
from django import http
from django.shortcuts import get_object_or_404
-from django.views.decorators.http import require_GET
+from django.views.decorators.http import require_GET, require_POST
from django.conf import settings
from django.utils.formats import localize
+from django.utils.translation import ugettext as _
from catalogue.models import Image
-from wiki_img.forms import DocumentTextSaveForm
+from wiki import forms
+from wiki import nice_diff
+from wiki_img.forms import ImageSaveForm
#
# Quick hack around caching problems, TODO: use ETags
return direct_to_template(request, template_name, extra_context={
'document': doc,
'forms': {
- "text_save": DocumentTextSaveForm(user=request.user, prefix="textsave"),
+ "text_save": ImageSaveForm(user=request.user, prefix="textsave"),
+ "text_revert": forms.DocumentTextRevertForm(prefix="textrevert"),
+ "pubmark": forms.DocumentPubmarkForm(prefix="pubmark"),
},
+ 'can_pubmark': request.user.has_perm('catalogue.can_pubmark_image'),
'REDMINE_URL': settings.REDMINE_URL,
})
except (KeyError):
raise Http404
-
-
return direct_to_template(request, template_name, extra_context={
'document': doc,
'revision': revision,
def text(request, image_id):
doc = get_object_or_404(Image, pk=image_id)
if request.method == 'POST':
- form = DocumentTextSaveForm(request.POST, user=request.user, prefix="textsave")
+ form = ImageSaveForm(request.POST, user=request.user, prefix="textsave")
if form.is_valid():
if request.user.is_authenticated():
author = request.user
stage = form.cleaned_data['stage_completed']
tags = [stage] if stage else []
publishable = (form.cleaned_data['publishable'] and
- request.user.has_perm('catalogue.can_pubmark'))
+ request.user.has_perm('catalogue.can_pubmark_image'))
doc.commit(author=author,
- text=text,
- parent=parent,
- description=form.cleaned_data['comment'],
- tags=tags,
- author_name=form.cleaned_data['author_name'],
- author_email=form.cleaned_data['author_email'],
- publishable=publishable,
- )
+ text=text,
+ parent=parent,
+ description=form.cleaned_data['comment'],
+ tags=tags,
+ author_name=form.cleaned_data['author_name'],
+ author_email=form.cleaned_data['author_email'],
+ publishable=publishable,
+ )
revision = doc.revision()
return JSONResponse({
'text': doc.materialize() if parent_revision != revision else None,
@never_cache
-def history(request, chunk_id):
+def history(request, object_id):
# TODO: pagination
- doc = get_object_or_404(Image, pk=chunk_id)
+ doc = get_object_or_404(Image, pk=object_id)
if not doc.accessible(request):
return HttpResponseForbidden("Not authorized.")
"tag": ',\n'.join(unicode(tag) for tag in change.tags.all()),
})
return JSONResponse(changes)
+
+
+@never_cache
+@require_POST
+def revert(request, object_id):
+ form = forms.DocumentTextRevertForm(request.POST, prefix="textrevert")
+ if form.is_valid():
+ doc = get_object_or_404(Image, pk=object_id)
+ if not doc.accessible(request):
+ return HttpResponseForbidden("Not authorized.")
+
+ revision = form.cleaned_data['revision']
+
+ comment = form.cleaned_data['comment']
+ comment += "\n#revert to %s" % revision
+
+ if request.user.is_authenticated():
+ author = request.user
+ else:
+ author = None
+
+ before = doc.revision()
+ logger.info("Reverting %s to %s", object_id, revision)
+ doc.at_revision(revision).revert(author=author, description=comment)
+
+ return JSONResponse({
+ 'text': doc.materialize() if before != doc.revision() else None,
+ 'meta': {},
+ 'revision': doc.revision(),
+ })
+ else:
+ return JSONFormInvalid(form)
+
+
+@never_cache
+def diff(request, object_id):
+ revA = int(request.GET.get('from', 0))
+ revB = int(request.GET.get('to', 0))
+
+ if revA > revB:
+ revA, revB = revB, revA
+
+ if revB == 0:
+ revB = None
+
+ doc = get_object_or_404(Image, pk=object_id)
+ if not doc.accessible(request):
+ return HttpResponseForbidden("Not authorized.")
+
+ # allow diff from the beginning
+ if revA:
+ docA = doc.at_revision(revA).materialize()
+ else:
+ docA = ""
+ docB = doc.at_revision(revB).materialize()
+
+ return http.HttpResponse(nice_diff.html_diff_table(docA.splitlines(),
+ docB.splitlines(), context=3))
+
+
+@require_POST
+@ajax_require_permission('catalogue.can_pubmark_image')
+def pubmark(request, object_id):
+ form = forms.DocumentPubmarkForm(request.POST, prefix="pubmark")
+ if form.is_valid():
+ doc = get_object_or_404(Image, pk=object_id)
+ if not doc.accessible(request):
+ return HttpResponseForbidden("Not authorized.")
+
+ revision = form.cleaned_data['revision']
+ publishable = form.cleaned_data['publishable']
+ change = doc.at_revision(revision)
+ if publishable != change.publishable:
+ change.set_publishable(publishable)
+ return JSONResponse({"message": _("Revision marked")})
+ else:
+ return JSONResponse({"message": _("Nothing changed")})
+ else:
+ return JSONFormInvalid(form)
# base UI
'js/wiki_img/base.js',
- 'js/wiki_img/toolbar.js',
+ 'js/wiki/toolbar.js',
# dialogs
- 'js/wiki_img/dialog_save.js',
- 'js/wiki_img/dialog_addtag.js',
+ 'js/wiki/dialog_save.js',
+ 'js/wiki/dialog_revert.js',
+ 'js/wiki/dialog_pubmark.js',
# views
- 'js/wiki_img/view_summary.js',
'js/wiki_img/view_editor_objects.js',
'js/wiki_img/view_editor_motifs.js',
'js/wiki/view_editor_source.js',
'js/wiki/view_history.js',
+ 'js/wiki/view_column_diff.js',
),
'output_filename': 'compressed/detail_img_scripts_?.js',
},
+++ /dev/null
-/*
- * Dialog for saving document to the server
- *
- */
-(function($){
-
- function AddTagDialog(element, options){
- if (!options.revision && options.revision != 0)
- throw "AddTagDialog needs a revision number.";
-
- this.ctx = $.wiki.exitContext();
- this.clearForm();
-
- /* fill out hidden fields */
- this.$form = $('form', element);
-
- $("input[name='addtag-id']", this.$form).val(CurrentDocument.id);
- $("input[name='addtag-revision']", this.$form).val(options.revision);
-
- $.wiki.cls.GenericDialog.call(this, element);
- };
-
- AddTagDialog.prototype = $.extend(new $.wiki.cls.GenericDialog(), {
- cancelAction: function(){
- $.wiki.enterContext(this.ctx);
- this.hide();
- },
-
- saveAction: function(){
- var self = this;
-
- self.$elem.block({
- message: "Dodawanie tagu",
- fadeIn: 0,
- });
-
- CurrentDocument.setTag({
- form: self.$form,
- success: function(doc, changed, info){
- self.$elem.block({
- message: info,
- timeout: 2000,
- fadeOut: 0,
- onUnblock: function(){
- self.hide();
- $.wiki.enterContext(self.ctx);
- }
- });
- },
- failure: function(doc, info){
- console.log("Failure", info);
- self.reportErrors(info);
- self.$elem.unblock();
- }
- });
- }
- });
-
- /* make it global */
- $.wiki.cls.AddTagDialog = AddTagDialog;
-})(jQuery);
+++ /dev/null
-/*
- * Dialog for saving document to the server
- *
- */
-(function($) {
-
- function SaveDialog(element) {
- this.ctx = $.wiki.exitContext();
- this.clearForm();
-
- /* fill out hidden fields */
- this.$form = $('form', element);
-
- $("input[name='textsave-id']", this.$form).val(CurrentDocument.id);
- $("input[name='textsave-parent_commit']", this.$form).val(CurrentDocument.commit);
-
- $.wiki.cls.GenericDialog.call(this, element);
- };
-
- SaveDialog.prototype = new $.wiki.cls.GenericDialog();
-
- SaveDialog.prototype.cancelAction = function() {
- $.wiki.enterContext(this.ctx);
- this.hide();
- };
-
- SaveDialog.prototype.saveAction = function() {
- var self = this;
-
- self.$elem.block({
- message: "Zapisywanie... <br/><button id='save-hide'>ukryj</button>",
- fadeIn: 0,
- });
- $.wiki.blocking = self.$elem;
-
- try {
-
- CurrentDocument.save({
- form: self.$form,
- success: function(doc, changed, info){
- self.$elem.block({
- message: info,
- timeout: 2000,
- fadeOut: 0,
- onUnblock: function() {
- self.hide();
- $.wiki.enterContext(self.ctx);
- }
- });
- },
- failure: function(doc, info) {
- console.log("Failure", info);
- self.reportErrors(info);
- self.$elem.unblock();
- }
- });
- } catch(e) {
- console.log('Exception:', e)
- self.$elem.unblock();
- }
- }; /* end of save dialog */
-
- /* make it global */
- $.wiki.cls.SaveDialog = SaveDialog;
-})(jQuery);
DEFAULT_PERSPECTIVE = "#MotifsPerspective";
+
$(function()
{
var tabs = $('ol#tabs li');
p.destroy();
return false;
});
-
+/*
$(window).resize(function(){
$('iframe').height($(window).height() - $('#tabs').outerHeight() - $('#source-editor .toolbar').outerHeight());
});
+ */
$(document).bind('wlapi_document_changed', function(event, doc) {
try {
$('#loading-overlay').fadeOut();
var active_tab = document.location.hash || DEFAULT_PERSPECTIVE;
- $(window).resize();
-
console.log("Initial tab is:", active_tab)
$.wiki.switchToTab(active_tab);
},
+++ /dev/null
-/*
- * Toolbar plugin.
- */
-(function($) {
-
- $.fn.toolbarize = function(options) {
- var $toolbar = $(this);
- var $container = $('.button_group_container', $toolbar);
-
- $('.button_group button', $toolbar).click(function(event){
- event.preventDefault();
-
- var params = eval("(" + $(this).attr('data-ui-action-params') + ")");
-
- scriptletCenter.callInteractive({
- action: $(this).attr('data-ui-action'),
- context: options.actionContext,
- extra: params
- });
- });
-
- $toolbar.children().filter('select').change(function(event){
- var slug = $(this).val();
- $container.scrollLeft(0);
- $('*[data-group]').hide().filter('[data-group=' + slug + ']').show();
- }).change();
-
- $('button.next', $toolbar).click(function() {
- var $current_group = $('.button_group:visible', $toolbar);
- var scroll = $container.scrollLeft();
-
- var $hidden = $("li", $current_group).filter(function() {
- return ($(this).position().left + $(this).outerWidth()) > $container.width();
- }).first();
-
- if($hidden.length > 0) {
- scroll = $hidden.position().left + scroll + $hidden.outerWidth() - $container.width() + 1;
- $container.scrollLeft(scroll);
- };
- });
-
- $('button.prev', $toolbar).click(function() {
- var $current_group = $('.button_group:visible', $toolbar);
- var scroll = $container.scrollLeft();
-
- /* first not visible element is: */
- var $hidden = $("li", $current_group).filter(function() {
- return $(this).position().left < 0;
- }).last();
-
- if( $hidden.length > 0)
- {
- scroll = scroll + $hidden.position().left;
- $container.scrollLeft(scroll);
- };
- });
-
- };
-
-})(jQuery);
\ No newline at end of file
+++ /dev/null
-/* COMMENT */
-(function($) {
-
- function CodeMirrorPerspective(options)
- {
- var old_callback = options.callback;
- options.callback = function(){
- var self = this;
-
- this.codemirror = CodeMirror.fromTextArea('codemirror_placeholder', {
- parserfile: 'parsexml.js',
- path: STATIC_URL + "js/lib/codemirror-0.8/",
- stylesheet: STATIC_URL + "css/xmlcolors_20100906.css",
- parserConfig: {
- useHTMLKludges: false
- },
- iframeClass: 'xml-iframe',
- textWrapping: true,
- lineNumbers: true,
- width: "100%",
- height: "100%",
- tabMode: 'spaces',
- indentUnit: 0,
- readOnly: CurrentDocument.readonly || false,
- initCallback: function(){
-
- self.codemirror.grabKeys(function(event) {
- if (event.button) {
- $(event.button).trigger('click');
- event.button = null;
- }
- }, function(keycode, event) {
- if(!event.altKey)
- return false;
-
- var c = String.fromCharCode(keycode).toLowerCase();
- var button = $("#source-editor button[data-ui-accesskey='"+c+"']");
- if(button.length == 0)
- return false;
-
- /* it doesn't matter which button we pick - all do the same */
- event.button = button[0];
- return true;
- });
-
- $('#source-editor .toolbar').toolbarize({
- actionContext: self.codemirror
- });
-
- console.log("Initialized CodeMirror");
-
- // textarea is no longer needed
- $('codemirror_placeholder').remove();
-
- old_callback.call(self);
- }
- });
- };
-
- $.wiki.Perspective.call(this, options);
- };
-
-
- CodeMirrorPerspective.prototype = new $.wiki.Perspective();
-
- CodeMirrorPerspective.prototype.freezeState = function() {
- this.config().position = this.codemirror.win.scrollY || 0;
- };
-
- CodeMirrorPerspective.prototype.unfreezeState = function () {
- this.codemirror.win.scroll(0, this.config().position || 0);
- };
-
- CodeMirrorPerspective.prototype.onEnter = function(success, failure) {
- $.wiki.Perspective.prototype.onEnter.call(this);
-
- console.log('Entering', this.doc);
- this.codemirror.setCode(this.doc.text);
-
- /* fix line numbers bar */
- var $nums = $('.CodeMirror-line-numbers');
- var barWidth = $nums.width();
-
- $(this.codemirror.frame.contentDocument.body).css('padding-left', barWidth);
- // $nums.css('left', -barWidth);
-
- $(window).resize();
- this.unfreezeState(this._uistate);
-
- if(success) success();
- }
-
- CodeMirrorPerspective.prototype.onExit = function(success, failure) {
- this.freezeState();
-
- $.wiki.Perspective.prototype.onExit.call(this);
- console.log('Exiting', this.doc);
- this.doc.setText(this.codemirror.getCode());
-
- if ($('.vsplitbar').hasClass('active') && $('#SearchPerspective').hasClass('active')) {
- $.wiki.switchToTab('#ScanGalleryPerspective');
- }
-
- if(success) success();
- }
-
- $.wiki.CodeMirrorPerspective = CodeMirrorPerspective;
-
-})(jQuery);
+++ /dev/null
-(function($){
-
- function SummaryPerspective(options) {
- var old_callback = options.callback;
- var self = this;
-
- $.wiki.Perspective.call(this, options);
- };
-
- SummaryPerspective.prototype = new $.wiki.Perspective();
-
- SummaryPerspective.prototype.freezeState = function(){
- // must
- };
-
- SummaryPerspective.prototype.onEnter = function(success, failure){
- $.wiki.Perspective.prototype.onEnter.call(this);
-
- console.log("Entered summery view");
- };
-
- $.wiki.SummaryPerspective = SummaryPerspective;
-
-})(jQuery);
-
return base_path + "/text/" + arguments[1] + "/";
}
- if (vname == "ajax_document_history") {
+ if (vname == "ajax_document_revert") {
+ return base_path + "/revert/" + arguments[1] + '/';
+ }
- return base_path + "/history/" + arguments[1] + "/";
+ if (vname == "ajax_document_history") {
+ return base_path + "/history/" + arguments[1] + '/';
}
-*/
-/*
- if (vname == "ajax_document_diff")
- return base_path + "/" + arguments[1] + "/diff";
- if (vname == "ajax_document_rev")
- return base_path + "/" + arguments[1] + "/rev";
-
- if (vname == "ajax_document_addtag")
- return base_path + "/" + arguments[1] + "/tags";
+ if (vname == "ajax_document_diff")
+ return base_path + "/diff/" + arguments[1] + '/';
- if (vname == "ajax_publish")
- return base_path + "/" + arguments[1] + "/publish";*/
+ if (vname == "ajax_document_pubmark")
+ return base_path + "/pubmark/" + arguments[1] + '/';
console.log("Couldn't reverse match:", vname);
return "/404.html";
}
});
};
+ WikiDocument.prototype.fetchDiff = function(params) {
+ /* this doesn't modify anything, so no locks */
+ var self = this;
+ params = $.extend({
+ 'from': self.revision,
+ 'to': self.revision
+ }, noops, params);
+ $.ajax({
+ method: "GET",
+ url: reverse("ajax_document_diff", self.id),
+ dataType: 'html',
+ data: {
+ "from": params['from'],
+ "to": params['to']
+ },
+ success: function(data) {
+ params['success'](self, data);
+ },
+ error: function() {
+ params['failure'](self, "Nie udało się wczytać porównania wersji.");
+ }
+ });
+ };
/*
* Set document's text
});
}; /* end of save() */
- WikiDocument.prototype.publish = function(params) {
- params = $.extend({}, noops, params);
- var self = this;
- $.ajax({
- url: reverse("ajax_publish", self.id),
- type: "POST",
- dataType: "json",
- success: function(data) {
- params.success(self, data);
- },
- error: function(xhr) {
- if (xhr.status == 403 || xhr.status == 401) {
- params.failure(self, "Nie masz uprawnień lub nie jesteś zalogowany.");
- }
- else {
- try {
- params.failure(self, xhr.responseText);
- }
- catch (e) {
- params.failure(self, "Nie udało się - błąd serwera.");
- };
- };
+ WikiDocument.prototype.revertToVersion = function(params) {
+ var self = this;
+ params = $.extend({}, noops, params);
- }
- });
- };
- WikiDocument.prototype.setTag = function(params) {
+ if (params.revision >= this.revision) {
+ params.failure(self, 'Proszę wybrać rewizję starszą niż aktualna.');
+ return;
+ }
+
+ // Serialize form to dictionary
+ var data = {};
+ $.each(params['form'].serializeArray(), function() {
+ data[this.name] = this.value;
+ });
+
+ $.ajax({
+ url: reverse("ajax_document_revert", self.id),
+ type: "POST",
+ dataType: "json",
+ data: data,
+ success: function(data) {
+ if (data.text) {
+ self.text = data.text;
+ self.revision = data.revision;
+ self.gallery = data.gallery;
+ self.triggerDocumentChanged();
+
+ params.success(self, "Udało się przywrócić wersję :)");
+ }
+ else {
+ params.failure(self, "Przywracana wersja identyczna z aktualną. Anulowano przywracanie.");
+ }
+ },
+ error: function(xhr) {
+ params.failure(self, "Nie udało się przywrócić wersji - błąd serwera.");
+ }
+ });
+ };
+
+ WikiDocument.prototype.pubmark = function(params) {
params = $.extend({}, noops, params);
var self = this;
var data = {
- "addtag-id": self.id,
+ "pubmark-id": self.id,
};
/* unpack form */
});
$.ajax({
- url: reverse("ajax_document_addtag", self.id),
+ url: reverse("ajax_document_pubmark", self.id),
type: "POST",
dataType: "json",
data: data,
});
};
+
+
WikiDocument.prototype.getImageItems = function(tag) {
var self = this;
}
var a = [];
- $(tag, doc).each(function(i, e) {
+ $('sem[type="'+tag+'"]', doc).each(function(i, e) {
var $e = $(e);
- a.push([
- $e.text(),
- $e.attr('x1'),
- $e.attr('y1'),
- $e.attr('x2'),
- $e.attr('y2')
- ]);
+ var $div = $e.children().first()
+ var value = $e.attr(tag);
+ $e.find('div').each(function(i, div) {
+ var $div = $(div);
+ switch ($div.attr('type')) {
+ case 'area':
+ a.push([
+ value,
+ $div.attr('x1'),
+ $div.attr('y1'),
+ $div.attr('x2'),
+ $div.attr('y2')
+ ]);
+ break;
+ case 'whole':
+ a.push([
+ value,
+ null, null, null, null
+ ]);
+ break
+ }
+ });
});
return a;
return null;
}
- $(tag, doc).remove();
+ $('sem[type="'+tag+'"]', doc).remove();
$root = $(doc.firstChild);
$.each(items, function(i, e) {
- var el = $(doc.createElement(tag));
- el.text(e[0]);
- if (e[1] !== null) {
- el.attr('x1', e[1]);
- el.attr('y1', e[2]);
- el.attr('x2', e[3]);
- el.attr('y2', e[4]);
+ var $sem = $(doc.createElement("sem"));
+ $sem.attr('type', tag);
+ $sem.attr(tag, e[0]);
+ $div = $(doc.createElement("div"));
+ if (e[1]) {
+ $div.attr('type', 'area');
+ $div.attr('x1', e[1]);
+ $div.attr('y1', e[2]);
+ $div.attr('x2', e[3]);
+ $div.attr('y2', e[4]);
+ }
+ else {
+ $div.attr('type', 'whole');
}
- $root.append(el);
+ $sem.append($div);
+ $root.append($sem);
});
- self.setText(serializer.serializeToString(doc));
+ self.setText(XML(serializer.serializeToString(doc)).toXMLString());
}