ep_comments_page 11.1.14 → 11.1.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -0
- package/commentManager.js +16 -7
- package/ep.json +1 -0
- package/exportHTML.js +36 -8
- package/index.js +152 -17
- package/locales/en.json +5 -0
- package/package.json +3 -4
- package/static/css/comment.css +188 -2
- package/static/js/commentBoxes.js +31 -10
- package/static/js/copyPasteEvents.js +12 -13
- package/static/js/index.js +415 -32
- package/static/js/timeslider.js +367 -0
- package/static/tests/backend/specs/editPermissions.js +118 -0
- package/static/tests/backend/specs/readOnlyPad.js +38 -2
- package/static/tests/frontend-new/helper/comments.ts +8 -1
- package/static/tests/frontend-new/specs/addCommentButtonState.spec.ts +74 -0
- package/static/tests/frontend-new/specs/authorColor.spec.ts +58 -0
- package/static/tests/frontend-new/specs/commentNavigation.spec.ts +136 -0
- package/static/tests/frontend-new/specs/commentSuggestion.spec.ts +156 -2
- package/static/tests/frontend-new/specs/commentsOverview.spec.ts +63 -0
- package/static/tests/frontend-new/specs/crossPadCommentCopy.spec.ts +62 -0
- package/static/tests/frontend-new/specs/exportComments.spec.ts +65 -0
- package/static/tests/frontend-new/specs/floatingCommentButton.spec.ts +39 -0
- package/static/tests/frontend-new/specs/highContrast.spec.ts +65 -0
- package/static/tests/frontend-new/specs/mobilePopup.spec.ts +64 -0
- package/static/tests/frontend-new/specs/multipleCommentsPerLine.spec.ts +62 -0
- package/static/tests/frontend-new/specs/readonlyButton.spec.ts +28 -0
- package/static/tests/frontend-new/specs/readonlyCommenting.spec.ts +40 -0
- package/static/tests/frontend-new/specs/readonlyHideActions.spec.ts +80 -0
- package/static/tests/frontend-new/specs/timeslider.spec.ts +225 -0
- package/templates/commentBarButtons.ejs +2 -2
- package/templates/comments.html +5 -0
- package/templates/commentsOverviewSetting.ejs +5 -0
package/static/css/comment.css
CHANGED
|
@@ -7,6 +7,27 @@
|
|
|
7
7
|
color: orange !important;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
/* High-contrast / forced-colors mode (e.g. Windows High Contrast Mode), #217.
|
|
11
|
+
In forced-colors mode the UA discards the fixed yellow/dark fill above, so
|
|
12
|
+
commented text becomes indistinguishable from the rest of the document, and
|
|
13
|
+
the orange open-state colour is unreadable against the highlight. Opt back
|
|
14
|
+
into author colours with the system "marked text" pair — the semantic
|
|
15
|
+
colours browsers reserve for highlighted text — so the highlight stays
|
|
16
|
+
visible and legible whatever the active high-contrast palette is, and mark
|
|
17
|
+
the open comment with an outline (which forced-colors honours) instead of a
|
|
18
|
+
colour that cannot guarantee contrast. */
|
|
19
|
+
@media (forced-colors: active) {
|
|
20
|
+
#innerdocbody .ace-line .comment {
|
|
21
|
+
background-color: Mark;
|
|
22
|
+
color: MarkText;
|
|
23
|
+
forced-color-adjust: none;
|
|
24
|
+
}
|
|
25
|
+
#innerdocbody .ace-line .comment[data-open="true"] {
|
|
26
|
+
color: MarkText !important;
|
|
27
|
+
outline: 2px solid CanvasText;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
10
31
|
|
|
11
32
|
/* Comment right side container */
|
|
12
33
|
#comments {
|
|
@@ -26,6 +47,10 @@
|
|
|
26
47
|
.sidebar-comment {
|
|
27
48
|
position: absolute;
|
|
28
49
|
width: 100%;
|
|
50
|
+
box-sizing: border-box;
|
|
51
|
+
/* Reserve room for the author-colour accent (#6) so commented boxes with and
|
|
52
|
+
without a known author colour stay aligned; the colour is set inline. */
|
|
53
|
+
border-left: 3px solid transparent;
|
|
29
54
|
}
|
|
30
55
|
|
|
31
56
|
/* WITH ICONS */
|
|
@@ -61,6 +86,50 @@ input.error, textarea.error {
|
|
|
61
86
|
display: inline;
|
|
62
87
|
}
|
|
63
88
|
|
|
89
|
+
/* #241: previous/next comment navigation arrows in the comment header. */
|
|
90
|
+
.comment-nav-wrapper {
|
|
91
|
+
float: right;
|
|
92
|
+
margin-left: 6px;
|
|
93
|
+
}
|
|
94
|
+
.comment-nav-prev,
|
|
95
|
+
.comment-nav-next {
|
|
96
|
+
/* A fixed, comfortably-clickable icon box. The localized label html10n writes
|
|
97
|
+
into the element is clipped/invisible (kept as the accessible name via
|
|
98
|
+
aria-label); the ‹ / › glyph is painted by ::before over the whole box. */
|
|
99
|
+
position: relative;
|
|
100
|
+
display: inline-block;
|
|
101
|
+
width: 1.5em;
|
|
102
|
+
height: 1.5em;
|
|
103
|
+
overflow: hidden;
|
|
104
|
+
white-space: nowrap;
|
|
105
|
+
color: transparent;
|
|
106
|
+
cursor: pointer;
|
|
107
|
+
vertical-align: middle;
|
|
108
|
+
}
|
|
109
|
+
.comment-nav-prev:before,
|
|
110
|
+
.comment-nav-next:before {
|
|
111
|
+
position: absolute;
|
|
112
|
+
top: 0;
|
|
113
|
+
left: 0;
|
|
114
|
+
width: 100%;
|
|
115
|
+
height: 100%;
|
|
116
|
+
line-height: 1.5em;
|
|
117
|
+
text-align: center;
|
|
118
|
+
color: #666;
|
|
119
|
+
font-size: 18px;
|
|
120
|
+
font-weight: bold;
|
|
121
|
+
}
|
|
122
|
+
.comment-nav-prev:hover:before,
|
|
123
|
+
.comment-nav-next:hover:before {
|
|
124
|
+
color: #000;
|
|
125
|
+
}
|
|
126
|
+
.comment-nav-prev:before {
|
|
127
|
+
content: "\2039"; /* ‹ */
|
|
128
|
+
}
|
|
129
|
+
.comment-nav-next:before {
|
|
130
|
+
content: "\203A"; /* › */
|
|
131
|
+
}
|
|
132
|
+
|
|
64
133
|
/* COMMENT COMPACTED (Visible on right side) */
|
|
65
134
|
.sidebar-comment:not(.full-display) .full-display-content {
|
|
66
135
|
display: none;
|
|
@@ -118,8 +187,13 @@ input.error, textarea.error {
|
|
|
118
187
|
}
|
|
119
188
|
.suggestion-display .from-value,
|
|
120
189
|
.suggestion-display .to-value {
|
|
121
|
-
opacity: .8;
|
|
122
190
|
font-style: italic;
|
|
191
|
+
/* #380: the colibris skin renders these values in its green --primary-color
|
|
192
|
+
(#64d29b), which is ~1.9:1 against the light comment background — well below
|
|
193
|
+
WCAG AA. Use the skin's regular text colour instead (readable everywhere,
|
|
194
|
+
still skin-overridable via the same token) with a dark fallback. !important
|
|
195
|
+
beats the core skin's non-important rule regardless of load order. */
|
|
196
|
+
color: var(--text-color, #2b2b2b) !important;
|
|
123
197
|
}
|
|
124
198
|
.suggestion-display .from-value:after, .suggestion-display .from-value:before,
|
|
125
199
|
.suggestion-display .to-value:after, .suggestion-display .to-value:before {
|
|
@@ -133,7 +207,6 @@ input.error, textarea.error {
|
|
|
133
207
|
}
|
|
134
208
|
.suggestion-create .from-value {
|
|
135
209
|
display: block;
|
|
136
|
-
opacity: .8;
|
|
137
210
|
font-style: italic;
|
|
138
211
|
margin: 5px 0;
|
|
139
212
|
}
|
|
@@ -199,6 +272,16 @@ input.error, textarea.error {
|
|
|
199
272
|
.comment-modal {
|
|
200
273
|
bottom: auto !important;
|
|
201
274
|
right: auto !important;
|
|
275
|
+
/* Single source of truth for the viewport safe-margin so the CSS width cap
|
|
276
|
+
and the JS left/top clamp can't drift apart (#192). commentBoxes.js reads
|
|
277
|
+
this custom property back via getComputedStyle. */
|
|
278
|
+
--comment-modal-margin: 10px;
|
|
279
|
+
/* Never let the popup grow wider than the viewport, otherwise it spills off
|
|
280
|
+
the right edge on narrow / mobile screens regardless of its left position
|
|
281
|
+
(#192). Pairs with the left/right clamp in commentBoxes.js. */
|
|
282
|
+
max-width: calc(100% - (2 * var(--comment-modal-margin)));
|
|
283
|
+
box-sizing: border-box;
|
|
284
|
+
overflow-wrap: break-word;
|
|
202
285
|
}
|
|
203
286
|
.comment-modal-comment {
|
|
204
287
|
padding: 0;
|
|
@@ -218,6 +301,109 @@ input.error, textarea.error {
|
|
|
218
301
|
margin-top: 0 !important;
|
|
219
302
|
}
|
|
220
303
|
|
|
304
|
+
/* READ-ONLY: hide write-only comment actions (edit / delete) on read-only
|
|
305
|
+
pads (#112). The comment sidebar and modal live in the ace_outer iframe,
|
|
306
|
+
which does not receive core's `readonly` body class, so the plugin tags the
|
|
307
|
+
outer body with `comments-readonly` itself (see static/js/index.js). The
|
|
308
|
+
server already rejects edits/deletes from read-only sessions; this removes
|
|
309
|
+
the now-dead controls from the UI. */
|
|
310
|
+
.comments-readonly .comment-actions-wrapper {
|
|
311
|
+
display: none !important;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/* #95: floating "add comment" button that follows the selection. Positioned
|
|
315
|
+
inline (in #editorcontainerbox space) by the plugin and clamped on-screen, so
|
|
316
|
+
it works the same on desktop and narrow/mobile viewports. It is shown
|
|
317
|
+
translucent so it doesn't obscure the selection, and becomes fully opaque on
|
|
318
|
+
hover/focus (#95). */
|
|
319
|
+
.floating-add-comment {
|
|
320
|
+
position: absolute;
|
|
321
|
+
display: none;
|
|
322
|
+
z-index: 100;
|
|
323
|
+
width: 26px;
|
|
324
|
+
height: 26px;
|
|
325
|
+
line-height: 26px;
|
|
326
|
+
text-align: center;
|
|
327
|
+
border-radius: 50%;
|
|
328
|
+
background: #fff;
|
|
329
|
+
box-shadow: 0 1px 4px rgba(0, 0, 0, .3);
|
|
330
|
+
cursor: pointer;
|
|
331
|
+
color: #444;
|
|
332
|
+
user-select: none;
|
|
333
|
+
opacity: .55;
|
|
334
|
+
transition: opacity .15s ease;
|
|
335
|
+
}
|
|
336
|
+
.floating-add-comment.visible {
|
|
337
|
+
display: block;
|
|
338
|
+
}
|
|
339
|
+
.floating-add-comment:hover,
|
|
340
|
+
.floating-add-comment:focus {
|
|
341
|
+
background: #f3f3f3;
|
|
342
|
+
opacity: 1;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/* #12/#5: all-comments overview panel (opened from the "Show all comments"
|
|
346
|
+
checkbox in the Settings pane). */
|
|
347
|
+
#comments-overview {
|
|
348
|
+
position: absolute;
|
|
349
|
+
top: 6px;
|
|
350
|
+
right: 6px;
|
|
351
|
+
width: 280px;
|
|
352
|
+
max-width: calc(100% - 12px);
|
|
353
|
+
max-height: 70%;
|
|
354
|
+
display: none;
|
|
355
|
+
flex-direction: column;
|
|
356
|
+
background: #fff;
|
|
357
|
+
border: 1px solid #ddd;
|
|
358
|
+
border-radius: 4px;
|
|
359
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, .25);
|
|
360
|
+
z-index: 101;
|
|
361
|
+
box-sizing: border-box;
|
|
362
|
+
overflow: hidden;
|
|
363
|
+
}
|
|
364
|
+
#comments-overview.visible {
|
|
365
|
+
display: flex;
|
|
366
|
+
}
|
|
367
|
+
.comments-overview-header {
|
|
368
|
+
font-weight: bold;
|
|
369
|
+
padding: 8px 10px;
|
|
370
|
+
border-bottom: 1px solid #eee;
|
|
371
|
+
flex: 0 0 auto;
|
|
372
|
+
}
|
|
373
|
+
.comments-overview-list {
|
|
374
|
+
overflow-y: auto;
|
|
375
|
+
flex: 1 1 auto;
|
|
376
|
+
}
|
|
377
|
+
.comments-overview-empty {
|
|
378
|
+
padding: 10px;
|
|
379
|
+
color: #888;
|
|
380
|
+
}
|
|
381
|
+
.comments-overview-row {
|
|
382
|
+
padding: 8px 10px;
|
|
383
|
+
border-bottom: 1px solid #f0f0f0;
|
|
384
|
+
cursor: pointer;
|
|
385
|
+
border-left: 3px solid transparent;
|
|
386
|
+
}
|
|
387
|
+
.comments-overview-row:hover {
|
|
388
|
+
background: #f5f5f5;
|
|
389
|
+
}
|
|
390
|
+
.comments-overview-row.resolved {
|
|
391
|
+
opacity: .6;
|
|
392
|
+
text-decoration: line-through;
|
|
393
|
+
}
|
|
394
|
+
.comments-overview-author {
|
|
395
|
+
font-weight: bold;
|
|
396
|
+
margin-right: 6px;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/* #96: visually mark the toolbar "Add comment" button as unavailable until
|
|
400
|
+
text is selected (commenting needs a selection). It is also not activatable
|
|
401
|
+
while disabled (see the click guard in static/js/index.js). */
|
|
402
|
+
.addComment.comment-btn-disabled {
|
|
403
|
+
opacity: .4;
|
|
404
|
+
cursor: not-allowed;
|
|
405
|
+
}
|
|
406
|
+
|
|
221
407
|
/* OTHER */
|
|
222
408
|
.hidden {
|
|
223
409
|
display: none;
|
|
@@ -52,8 +52,14 @@ const highlightComment = (commentId, e, editorComment) => {
|
|
|
52
52
|
// make a full copy of the html, including listeners
|
|
53
53
|
const commentElmCloned = commentElm.clone(true, true);
|
|
54
54
|
|
|
55
|
-
//
|
|
55
|
+
// Clear only the sidebar positioning so the clone sits correctly in the
|
|
56
|
+
// modal — but preserve the author-colour accent (#6), which insertComment()
|
|
57
|
+
// sets as an inline border-left and would otherwise be wiped by clearing
|
|
58
|
+
// the whole style attribute (#436). Read the inline value off the original
|
|
59
|
+
// element (the clone may be detached, so computed styles aren't available).
|
|
60
|
+
const authorBorder = commentElm[0] && commentElm[0].style.borderLeft;
|
|
56
61
|
commentElmCloned.attr('style', '');
|
|
62
|
+
if (authorBorder) commentElmCloned.css('border-left', authorBorder);
|
|
57
63
|
// fix checkbox, because as we are duplicating the sidebar-comment, we lose unique input names
|
|
58
64
|
commentElmCloned.find('.label-suggestion-checkbox').click(function () {
|
|
59
65
|
$(this).siblings('input[type="checkbox"]').click();
|
|
@@ -65,26 +71,41 @@ const highlightComment = (commentId, e, editorComment) => {
|
|
|
65
71
|
// get modal position
|
|
66
72
|
const containerWidth = getPadOuter().find('#outerdocbody').outerWidth(true);
|
|
67
73
|
const modalWitdh = getPadOuter().find('.comment-modal').outerWidth(true);
|
|
68
|
-
|
|
69
|
-
|
|
74
|
+
// Be tolerant of being called without a (complete) event — e.g. programmatic
|
|
75
|
+
// navigation (#241). Fall back to the anchor element's position so we never
|
|
76
|
+
// dereference a missing event (clientX/target).
|
|
77
|
+
const $anchor = (e && e.target) ? $(e.target) : (editorComment || commentElm);
|
|
78
|
+
const anchorOffset = $anchor.offset() || {left: 0, top: 0};
|
|
79
|
+
let targetLeft = (e && typeof e.clientX === 'number') ? e.clientX : anchorOffset.left;
|
|
80
|
+
let targetTop = anchorOffset.top;
|
|
70
81
|
if (editorComment) {
|
|
71
82
|
targetLeft += padInner.offset().left;
|
|
72
83
|
targetTop += parseInt(padInner.css('padding-top').split('px')[0]);
|
|
73
84
|
targetTop += parseInt(padOuter.find('#outerdocbody').css('padding-top').split('px')[0]);
|
|
74
85
|
} else {
|
|
75
86
|
// mean we are clicking from a comment Icon
|
|
76
|
-
targetLeft =
|
|
87
|
+
targetLeft = anchorOffset.left - 20;
|
|
77
88
|
}
|
|
78
89
|
|
|
79
|
-
//
|
|
80
|
-
//
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
90
|
+
// Clamp horizontally so the modal never spills off either edge. The old
|
|
91
|
+
// code only guarded the right edge, which left the popup half off-screen
|
|
92
|
+
// (or pushed it past the left edge from the icon's `offset - 20`) on
|
|
93
|
+
// narrow / mobile viewports (#192). max() keeps the left margin valid even
|
|
94
|
+
// when the modal is wider than the container.
|
|
95
|
+
// Read the safe-margin from the CSS custom property so JS and CSS stay in
|
|
96
|
+
// sync (single source of truth on .comment-modal); fall back to 10px.
|
|
97
|
+
const $modal = getPadOuter().find('.comment-modal');
|
|
98
|
+
const marginProp = $modal.length
|
|
99
|
+
? parseFloat(getComputedStyle($modal[0]).getPropertyValue('--comment-modal-margin'))
|
|
100
|
+
: NaN;
|
|
101
|
+
const margin = Number.isFinite(marginProp) ? marginProp : 10;
|
|
102
|
+
const maxLeft = Math.max(margin, containerWidth - modalWitdh - margin);
|
|
103
|
+
targetLeft = Math.min(Math.max(targetLeft, margin), maxLeft);
|
|
84
104
|
const editorCommentHeight = editorComment ? editorComment.outerHeight(true) : 30;
|
|
105
|
+
targetTop = Math.max(margin, targetTop + editorCommentHeight);
|
|
85
106
|
getPadOuter().find('.comment-modal').addClass('popup-show').css({
|
|
86
107
|
left: `${targetLeft}px`,
|
|
87
|
-
top: `${targetTop
|
|
108
|
+
top: `${targetTop}px`,
|
|
88
109
|
});
|
|
89
110
|
}
|
|
90
111
|
};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const _ = require('underscore');
|
|
4
3
|
const randomString = require('ep_etherpad-lite/static/js/pad_utils').randomString;
|
|
5
4
|
const shared = require('./shared');
|
|
6
5
|
|
|
@@ -49,15 +48,15 @@ exports.addTextOnClipboard = (e, ace, padInner, removeSelection, comments, repli
|
|
|
49
48
|
|
|
50
49
|
const getReplyData = (replies, commentIds) => {
|
|
51
50
|
let replyData = {};
|
|
52
|
-
|
|
53
|
-
replyData =
|
|
51
|
+
commentIds.forEach((commentId) => {
|
|
52
|
+
replyData = Object.assign(getRepliesFromCommentId(replies, commentId), replyData);
|
|
54
53
|
});
|
|
55
54
|
return replyData;
|
|
56
55
|
};
|
|
57
56
|
|
|
58
57
|
const getRepliesFromCommentId = (replies, commentId) => {
|
|
59
58
|
const repliesFromCommentID = {};
|
|
60
|
-
|
|
59
|
+
Object.entries(replies || {}).forEach(([replyId, reply]) => {
|
|
61
60
|
if (reply.commentId === commentId) {
|
|
62
61
|
repliesFromCommentID[replyId] = reply;
|
|
63
62
|
}
|
|
@@ -67,7 +66,7 @@ const getRepliesFromCommentId = (replies, commentId) => {
|
|
|
67
66
|
|
|
68
67
|
const buildCommentIdToFakeIdMap = (commentsData) => {
|
|
69
68
|
const commentIdToFakeId = {};
|
|
70
|
-
|
|
69
|
+
Object.entries(commentsData).forEach(([fakeCommentId, comment]) => {
|
|
71
70
|
const commentId = comment.data.originalCommentId;
|
|
72
71
|
commentIdToFakeId[commentId] = fakeCommentId;
|
|
73
72
|
});
|
|
@@ -76,7 +75,7 @@ const buildCommentIdToFakeIdMap = (commentsData) => {
|
|
|
76
75
|
|
|
77
76
|
const replaceCommentIdsWithFakeIds = (commentsData, html) => {
|
|
78
77
|
const commentIdToFakeId = buildCommentIdToFakeIdMap(commentsData);
|
|
79
|
-
|
|
78
|
+
Object.entries(commentIdToFakeId).forEach(([commentId, fakeCommentId]) => {
|
|
80
79
|
$(html).find(`.${commentId}`).removeClass(commentId).addClass(fakeCommentId);
|
|
81
80
|
});
|
|
82
81
|
const htmlWithFakeCommentIds = getHtml(html);
|
|
@@ -86,7 +85,7 @@ const replaceCommentIdsWithFakeIds = (commentsData, html) => {
|
|
|
86
85
|
const buildCommentsData = (html, comments) => {
|
|
87
86
|
const commentsData = {};
|
|
88
87
|
const originalCommentIds = getCommentIds(html);
|
|
89
|
-
|
|
88
|
+
originalCommentIds.forEach((originalCommentId) => {
|
|
90
89
|
const fakeCommentId = generateFakeCommentId();
|
|
91
90
|
const comment = comments[originalCommentId];
|
|
92
91
|
comment.data.originalCommentId = originalCommentId;
|
|
@@ -101,9 +100,9 @@ const generateFakeCommentId = () => {
|
|
|
101
100
|
};
|
|
102
101
|
|
|
103
102
|
const getCommentIds = (html) => {
|
|
104
|
-
const allSpans = $(html).find('span');
|
|
103
|
+
const allSpans = $(html).find('span').toArray();
|
|
105
104
|
const commentIds = [];
|
|
106
|
-
|
|
105
|
+
allSpans.forEach((span) => {
|
|
107
106
|
const cls = $(span).attr('class');
|
|
108
107
|
const classCommentId = /(?:^| )(c-[A-Za-z0-9]*)/.exec(cls);
|
|
109
108
|
const commentId = (classCommentId) ? classCommentId[1] : false;
|
|
@@ -217,7 +216,7 @@ const saveComments = (comments) => {
|
|
|
217
216
|
const mapOriginalCommentsId = pad.plugins.ep_comments_page.mapOriginalCommentsId;
|
|
218
217
|
const mapFakeComments = pad.plugins.ep_comments_page.mapFakeComments;
|
|
219
218
|
|
|
220
|
-
|
|
219
|
+
Object.entries(comments).forEach(([fakeCommentId, comment]) => {
|
|
221
220
|
const newCommentId = shared.generateCommentId();
|
|
222
221
|
mapFakeComments[fakeCommentId] = newCommentId;
|
|
223
222
|
const originalCommentId = comment.data.originalCommentId;
|
|
@@ -231,7 +230,7 @@ const saveReplies = (replies) => {
|
|
|
231
230
|
const repliesToSave = {};
|
|
232
231
|
const padId = clientVars.padId;
|
|
233
232
|
const mapOriginalCommentsId = pad.plugins.ep_comments_page.mapOriginalCommentsId;
|
|
234
|
-
|
|
233
|
+
Object.entries(replies).forEach(([replyId, reply]) => {
|
|
235
234
|
const originalCommentId = reply.commentId;
|
|
236
235
|
// as the comment copied has got a new commentId, we set this id in the reply as well
|
|
237
236
|
reply.commentId = mapOriginalCommentsId[originalCommentId];
|
|
@@ -258,7 +257,7 @@ const htmlDecode = (input) => {
|
|
|
258
257
|
exports.getCommentIdOnFirstPositionSelected = function () {
|
|
259
258
|
const attributeManager = this.documentAttributeManager;
|
|
260
259
|
const rep = this.rep;
|
|
261
|
-
const commentId =
|
|
260
|
+
const commentId = Object.fromEntries(
|
|
262
261
|
attributeManager.getAttributesOnPosition(rep.selStart[0], rep.selStart[1])).comment;
|
|
263
262
|
return commentId;
|
|
264
263
|
};
|
|
@@ -311,7 +310,7 @@ const hasCommentOnLine = (lineNumber, firstColumn, lastColumn, attributeManager)
|
|
|
311
310
|
let foundCommentOnLine = false;
|
|
312
311
|
for (let column = firstColumn; column <= lastColumn && !foundCommentOnLine; column++) {
|
|
313
312
|
const commentId =
|
|
314
|
-
|
|
313
|
+
Object.fromEntries(attributeManager.getAttributesOnPosition(lineNumber, column)).comment;
|
|
315
314
|
if (commentId !== undefined) {
|
|
316
315
|
foundCommentOnLine = true;
|
|
317
316
|
}
|