Ejemplo n.º 1
0
    def diff(self, request, *args, **kwargs):
        # this can be cached because the underlying data won't change (although
        # the formatting might)
        version = self.get_object()

        # most recent version just before this one
        old_version = self.get_queryset().filter(id__lt=version.id).first()

        differ = AttributeDiffer()

        if old_version:
            old_document = old_version._object_version.object
            old_document.document_xml = differ.preprocess_document_diff(
                old_document.document_xml)
            old_html = old_document.to_html()
        else:
            old_html = ""

        new_document = version._object_version.object
        new_document.document_xml = differ.preprocess_document_diff(
            new_document.document_xml)
        new_html = new_document.to_html()

        old_tree = lxml.html.fromstring(old_html) if old_html else None
        new_tree = lxml.html.fromstring(new_html)
        n_changes = differ.diff_document_html(old_tree, new_tree)

        diff = lxml.html.tostring(new_tree, encoding='unicode')

        # TODO: include other diff'd attributes

        return Response({
            'content': diff,
            'n_changes': n_changes,
        })
Ejemplo n.º 2
0
    def post(self, request):
        serializer = DocumentAPISerializer(data=self.request.data)
        serializer.fields['document'].fields['content'].required = True
        serializer.is_valid(raise_exception=True)

        differ = AttributeDiffer()

        current_document = serializer.fields['document'].update_document(
            Document(), serializer.validated_data['document'])
        current_document.document_xml = differ.preprocess_document_diff(
            current_document.document_xml)
        current_html = current_document.to_html()

        comparison_doc_id = request.data['comparison_doc_id']
        try:
            comparison_document = Document.objects.get(id=comparison_doc_id)
        except Document.DoesNotExist:
            raise Http404()
        comparison_document.document_xml = differ.preprocess_document_diff(
            comparison_document.document_xml)
        comparison_document_html = comparison_document.to_html()

        current_tree = lxml.html.fromstring(current_html)
        comparison_tree = lxml.html.fromstring(comparison_document_html)
        n_changes = differ.diff_document_html(comparison_tree, current_tree)

        diff = lxml.html.tostring(current_tree, encoding='utf-8')

        # TODO: include other diff'd attributes

        return Response({
            'content': diff,
            'n_changes': n_changes,
        })
Ejemplo n.º 3
0
    def post(self, request, document_id):
        serializer = DocumentDiffSerializer(instance=self.document,
                                            data=self.request.data)
        serializer.is_valid(raise_exception=True)

        differ = AttributeDiffer()

        local_doc = self.document

        # set this up to be the modified document
        remote_doc = Document.objects.get(pk=local_doc.pk)
        serializer.fields['document'].update_document(
            local_doc, serializer.validated_data['document'])

        local_doc.content = differ.preprocess_document_diff(
            local_doc.document_xml).decode('utf-8')
        remote_doc.content = differ.preprocess_document_diff(
            remote_doc.document_xml).decode('utf-8')

        element_id = serializer.validated_data.get('element_id')
        if element_id:
            # handle certain elements that don't have ids
            if element_id in ['preface', 'preamble', 'components']:
                xpath = f'//a:{element_id}'
            else:
                xpath = f'//a:*[@eId="{element_id}"]'

            # diff just this element
            local_element = local_doc.doc.root.xpath(
                xpath, namespaces={'a': local_doc.doc.namespace})
            remote_element = remote_doc.doc.root.xpath(
                xpath, namespaces={'a': local_doc.doc.namespace})

            local_html = local_doc.to_html(
                element=local_element[0]) if len(local_element) else None
            remote_html = remote_doc.to_html(
                element=remote_element[0]) if len(remote_element) else None
        else:
            # diff the whole document
            local_html = local_doc.to_html()
            remote_html = remote_doc.to_html()

        local_tree = lxml.html.fromstring(local_html or "<div></div>")
        remote_tree = lxml.html.fromstring(
            remote_html) if remote_html else None
        n_changes, diff = differ.diff_document_html(remote_tree, local_tree)

        if not isinstance(diff, str):
            diff = lxml.html.tostring(diff, encoding='utf-8')

        # TODO: include other diff'd attributes

        return Response({
            'html_diff': diff,
            'n_changes': n_changes,
        })