| author | Simon Descarpentries <sid@sopinspace.com> |
| Tue, 06 May 2014 13:52:01 +0200 | |
| changeset 651 | 9bbc657f6837 |
| parent 533 | c7aed0340a00 |
| permissions | -rw-r--r-- |
| 0 | 1 |
# -*- coding: utf-8 -*- |
2 |
from difflib import SequenceMatcher |
|
3 |
#from cm.utils.spannifier import Spannifier |
|
4 |
import sys, operator |
|
5 |
from cm.utils.spannifier import spannify |
|
6 |
from cm.converters.pandoc_converters import pandoc_convert |
|
7 |
import logging |
|
8 |
from cm.utils.spannifier import get_the_soup |
|
|
533
c7aed0340a00
For some reason, when exporting commented text with background colors, angle brackets for html spans are sometimes returned as entities by soup.
gibus
parents:
519
diff
changeset
|
9 |
import re |
| 0 | 10 |
|
11 |
import html5lib |
|
12 |
from html5lib import treebuilders |
|
13 |
||
14 |
def compute_new_comment_positions(old_content, old_format, new_content, new_format, commentList): |
|
15 |
||
| 175 | 16 |
# cf. TextVersion.get_content |
17 |
previousVersionContent = pandoc_convert(old_content, old_format, 'html') |
|
18 |
newVersionContent = pandoc_convert(new_content, new_format, 'html') |
|
19 |
||
|
502
8ec189cc214d
do not skip span for newline textnodes otherwise compute_new_comment_positions() will return bad results for pandoc texts.
gibus
parents:
498
diff
changeset
|
20 |
_, previous_char_list, span_starts_previous = spannify(previousVersionContent, False) |
|
8ec189cc214d
do not skip span for newline textnodes otherwise compute_new_comment_positions() will return bad results for pandoc texts.
gibus
parents:
498
diff
changeset
|
21 |
_, new_char_list, span_starts_new = spannify(newVersionContent, False) |
| 0 | 22 |
|
23 |
sm = SequenceMatcher(None, previous_char_list, new_char_list) |
|
24 |
||
25 |
opcodes = sm.get_opcodes() |
|
26 |
to_remove_comments_ids = set() |
|
27 |
||
| 103 | 28 |
# limit to real comments (not replies) and those that have scope |
29 |
commentList = [c for c in commentList if not c.is_reply() and not c.is_scope_removed()] |
|
| 0 | 30 |
|
31 |
for comment in commentList: |
|
32 |
try: |
|
33 |
comment.initial_start_offset = span_starts_previous[comment.start_wrapper] + comment.start_offset |
|
34 |
comment.initial_end_offset = span_starts_previous[comment.end_wrapper] + comment.end_offset |
|
35 |
except KeyError: |
|
36 |
logging.error('Key error (wrapper out of bounds of span_starts_previous)') |
|
37 |
continue |
|
38 |
||
39 |
comment.computed_start_offset = comment.initial_start_offset |
|
40 |
comment.computed_end_offset = comment.initial_end_offset |
|
41 |
||
42 |
# comment.computed_start_wrapper = None |
|
43 |
# comment.computed_end_wrapper = None |
|
44 |
||
45 |
comment.valid = True |
|
46 |
for tag, i1, i2, j1, j2 in opcodes: |
|
47 |
#print tag, i1, i2, j1, j2 |
|
48 |
||
49 |
for i in xrange(len(commentList)) : |
|
50 |
if tag != 'equal' : |
|
51 |
comment = commentList[i] |
|
52 |
if not comment.valid: |
|
53 |
continue |
|
54 |
||
55 |
if comment.initial_start_offset >= i2 : |
|
56 |
# if offset |
|
57 |
delta = ((j2 - j1) - (i2 - i1)) |
|
58 |
comment.computed_start_offset += delta |
|
59 |
comment.computed_end_offset += delta |
|
60 |
||
61 |
elif comment.initial_end_offset > i1: |
|
62 |
comment.valid = False |
|
63 |
||
64 |
# id, initial_start, initial_end, computed_start, computed_end, valid = self.computationResults[i] |
|
65 |
||
| 172 | 66 |
for cc in commentList: |
67 |
if cc.valid: |
|
| 0 | 68 |
for id in xrange(len(span_starts_new.keys())): |
|
496
c3df46754007
Fixes crash when editing, apparently when comment spans on multiple text nodes.
gibus
parents:
454
diff
changeset
|
69 |
start = span_starts_new.get(id, 0) |
| 0 | 70 |
end = span_starts_new.get(id+1, sys.maxint) |
71 |
||
72 |
# adjust start |
|
| 172 | 73 |
if cc.computed_start_offset >= start and cc.computed_start_offset < end: |
74 |
cc.start_wrapper = id |
|
75 |
cc.start_offset = cc.computed_start_offset - start |
|
| 0 | 76 |
|
77 |
# adjust end |
|
| 172 | 78 |
if cc.computed_end_offset >= start and cc.computed_end_offset < end: |
79 |
cc.end_wrapper = id |
|
80 |
cc.end_offset = cc.computed_end_offset - start |
|
| 0 | 81 |
|
82 |
# returns to_modify, to_remove |
|
83 |
return [c for c in commentList if c.valid], \ |
|
84 |
[c for c in commentList if not c.valid] |
|
85 |
||
86 |
def add_marker(text, color, start_ids, end_ids, with_markers, with_colors): |
|
87 |
# TODO |
|
88 |
# THESE 3 LINES ARE REALLY JUST FOR TESTING THIS IS COPIED FROM C-TEXT.CSS AND SHOULD BE DONE DIFFERENTLY |
|
|
519
e89c25780e6e
Gradient of colors for commented text depends on number of comments including replies, instead of depending only on number of threads.
gibus
parents:
502
diff
changeset
|
89 |
BCKCOLORS = ['#ffffff', '#ffffa8', '#fff6a1', '#ffeb99', '#ffde91', '#ffd08a', '#ffc182', '#ffaf7a', '#ff9d73', '#ff896b', '#ff7363', '#ff5c5c'] |
|
e89c25780e6e
Gradient of colors for commented text depends on number of comments including replies, instead of depending only on number of threads.
gibus
parents:
502
diff
changeset
|
90 |
for i in range(14) : |
|
e89c25780e6e
Gradient of colors for commented text depends on number of comments including replies, instead of depending only on number of threads.
gibus
parents:
502
diff
changeset
|
91 |
BCKCOLORS.append('#ff5c5c') |
| 0 | 92 |
|
93 |
ret = text |
|
94 |
||
95 |
if with_markers: |
|
96 |
end_ids.reverse() |
|
|
360
bfaab8740995
Add abiword as an alternative to open office for conversions
gibus
parents:
308
diff
changeset
|
97 |
ret = "%s%s%s"%(''.join(["[%s>"%start_id for start_id in start_ids]), ret, ''.join(["<%s]"%end_id for end_id in end_ids])) |
| 0 | 98 |
|
99 |
if with_colors and color != 0 : |
|
|
365
a478cb9786fd
For some reasons, abiwords can read background style attribute but not background-color
gibus
parents:
360
diff
changeset
|
100 |
# For some reasons, abiwords can read background style attribute but not background-color |
|
a478cb9786fd
For some reasons, abiwords can read background style attribute but not background-color
gibus
parents:
360
diff
changeset
|
101 |
from cm.cm_settings import USE_ABI |
|
a478cb9786fd
For some reasons, abiwords can read background style attribute but not background-color
gibus
parents:
360
diff
changeset
|
102 |
if USE_ABI: |
|
a478cb9786fd
For some reasons, abiwords can read background style attribute but not background-color
gibus
parents:
360
diff
changeset
|
103 |
ret = "<span style='background:%s;'>%s</span>"%(BCKCOLORS[color], ret) |
|
a478cb9786fd
For some reasons, abiwords can read background style attribute but not background-color
gibus
parents:
360
diff
changeset
|
104 |
else: |
| 0 | 105 |
ret = "<span style='background-color:%s;'>%s</span>"%(BCKCOLORS[color], ret) |
106 |
||
107 |
return ret |
|
108 |
||
| 103 | 109 |
# comments are comments and replies : |
| 0 | 110 |
def insert_comment_markers(htmlcontent, comments, with_markers, with_colors) : |
111 |
||
112 |
html = get_the_soup(htmlcontent) ; |
|
113 |
||
|
58
a480a91d63ca
BUG FIX : pdf export PhA tests, TODO fix special html caracters in comments
reno
parents:
0
diff
changeset
|
114 |
if comments : |
|
a480a91d63ca
BUG FIX : pdf export PhA tests, TODO fix special html caracters in comments
reno
parents:
0
diff
changeset
|
115 |
max_wrapper = max([comment.end_wrapper for comment in comments]) |
|
a480a91d63ca
BUG FIX : pdf export PhA tests, TODO fix special html caracters in comments
reno
parents:
0
diff
changeset
|
116 |
min_wrapper = min([comment.start_wrapper for comment in comments]) |
|
a480a91d63ca
BUG FIX : pdf export PhA tests, TODO fix special html caracters in comments
reno
parents:
0
diff
changeset
|
117 |
|
| 0 | 118 |
datas = {} # { wrapper_id : {'start_color':nb_of_comments_unterminated_at_wrapper_start, 'offsets':{offset: [[ids of wrappers starting at offset], [ids of wrappers ending at offset]]}} |
119 |
# datas['offsets'][someoffset][0] and idem[1] will be ordered the way comments are (should be ('start_wrapper', 'start_offset', 'end_wrapper', 'end_offset') important) |
|
120 |
cpt = 1 # starting numbered comment |
|
121 |
for comment in comments : |
|
122 |
if comment.is_reply() : |
|
123 |
continue ; |
|
124 |
||
125 |
# start |
|
126 |
wrapper_data = datas.get(comment.start_wrapper, {'start_color':0, 'offsets':{}}) |
|
127 |
offset = wrapper_data.get('offsets').get(comment.start_offset, [[],[]]) |
|
128 |
offset[0].append(cpt) |
|
129 |
wrapper_data['offsets'][comment.start_offset] = offset |
|
130 |
datas[comment.start_wrapper] = wrapper_data |
|
131 |
||
132 |
# end |
|
133 |
wrapper_data = datas.get(comment.end_wrapper, {'start_color':0, 'offsets':{}}) |
|
134 |
offset = wrapper_data.get('offsets').get(comment.end_offset, [[],[]]) |
|
135 |
offset[1].append(cpt) |
|
136 |
wrapper_data['offsets'][comment.end_offset] = offset |
|
137 |
datas[comment.end_wrapper] = wrapper_data |
|
138 |
||
139 |
for cc in range(comment.start_wrapper + 1, comment.end_wrapper + 1) : |
|
140 |
wrapper_data = datas.get(cc, {'start_color':0, 'offsets':{}}) |
|
141 |
wrapper_data['start_color'] += 1 |
|
142 |
datas[cc] = wrapper_data |
|
143 |
||
144 |
cpt = cpt + 1 |
|
145 |
||
146 |
# order ee values |
|
147 |
for (wrapper_id, wrapper_data) in datas.items() : |
|
148 |
start_color = wrapper_data['start_color'] |
|
149 |
offsets = sorted(wrapper_data['offsets'].items(), key=operator.itemgetter(0)) |
|
| 290 | 150 |
|
| 308 | 151 |
d = html.find(id = "sv-%d"%wrapper_id) |
152 |
if not d: # comment detached |
|
153 |
continue |
|
154 |
content = d.contents[0] |
|
| 0 | 155 |
|
156 |
spans = "" |
|
157 |
||
158 |
if offsets : |
|
159 |
color = start_color |
|
160 |
||
161 |
start = 0 |
|
162 |
start_ids = [] |
|
163 |
end_ids = [] |
|
164 |
||
165 |
for offset, ids in offsets : |
|
166 |
||
167 |
end_ids = ids[1] |
|
168 |
end = offset |
|
169 |
||
170 |
spans += add_marker(content[start:end], color, start_ids, end_ids, with_markers, with_colors) |
|
171 |
||
172 |
start_ids = ids[0] |
|
173 |
start = end |
|
174 |
||
175 |
color += (len(ids[0]) - len(ids[1])) |
|
176 |
||
177 |
end_ids = [] |
|
178 |
spans += add_marker(content[end:], color,start_ids, end_ids, with_markers, with_colors) |
|
179 |
else : # the whole content is to be colored with start_color |
|
180 |
spans += add_marker(content, start_color, [], [], with_markers, with_colors) |
|
181 |
||
182 |
content.replaceWith(spans) |
|
183 |
||
|
533
c7aed0340a00
For some reason, when exporting commented text with background colors, angle brackets for html spans are sometimes returned as entities by soup.
gibus
parents:
519
diff
changeset
|
184 |
output = unicode(html) |
|
c7aed0340a00
For some reason, when exporting commented text with background colors, angle brackets for html spans are sometimes returned as entities by soup.
gibus
parents:
519
diff
changeset
|
185 |
# Soup has introduced HTML entities, which should be expanded |
|
c7aed0340a00
For some reason, when exporting commented text with background colors, angle brackets for html spans are sometimes returned as entities by soup.
gibus
parents:
519
diff
changeset
|
186 |
output =re.sub(r""", '"', output) |
|
c7aed0340a00
For some reason, when exporting commented text with background colors, angle brackets for html spans are sometimes returned as entities by soup.
gibus
parents:
519
diff
changeset
|
187 |
output =re.sub(r"&", '&', output) |
|
c7aed0340a00
For some reason, when exporting commented text with background colors, angle brackets for html spans are sometimes returned as entities by soup.
gibus
parents:
519
diff
changeset
|
188 |
output =re.sub(r">", '>', output) |
|
c7aed0340a00
For some reason, when exporting commented text with background colors, angle brackets for html spans are sometimes returned as entities by soup.
gibus
parents:
519
diff
changeset
|
189 |
output =re.sub(r"<", '<', output) |
|
c7aed0340a00
For some reason, when exporting commented text with background colors, angle brackets for html spans are sometimes returned as entities by soup.
gibus
parents:
519
diff
changeset
|
190 |
return unicode(output) |