Extra lines currently render empty list items which are invisible.
Remove these as the user probably didn't intend from them to appear
in the wikiext.
Bug: T249867
Change-Id: I75c1192a94b918783d362d38cd91a508bb169d56
3 or 5 tilde signatures will be assumed to be erroneous and fixed
to 4 tilde signatures. This will be visible in the preview so shouldn't
come as a suprise to users.
Bug: T245628
Change-Id: I741f0761a6fb10c99cf3239ac5c6c7e1a2b872c7
The section wrappers can be marked as template-affected when the
previous or next section is transcluded, causing comments to be
unnecessarily uneditable. The new test case demonstrates this.
Depends-On: I03bc455d5484a6c51f3fa2397c64936b829fe7e3
Change-Id: I895a04990d79a3475d778b4fef054ea0bb076f0b
* When we discover the comment comes from a transcluded page, follow
the transclusion to find the source page. We follow transclusions
recursively, up to an arbitrary limit of 10.
* In the reply widget, display the title of the page where we will
save the reply, to avoid users confused why their edit won't show up
in the history. In the wikitext workflow this is done by redirecting
the user to the edited page at the end, but it seems less surprising
to stay on the current page.
* After saving the reply, we must purge the current page, otherwise
the new content will not be immediately visible on it.
Bug: T247535
Change-Id: I1c6631aa65a2fce6c1c2f0dd4a8c7aa6389caf94
The rejection handling callback was accidentally resolving the
promise, which resulted in an error like 'TypeError: Cannot read
property '$element' of undefined' when the resolution value was
used.
Fixing this reveals that we weren't removing the placeholder list
element correctly. This wasn't immediately visible because of the
.empty() call in the next resolution callback, but it would have
caused something similar to T245574.
Follow-up to 6964f0c965.
Change-Id: I3aeb9a86046c4ccaa6c39301edc7285d02b0320c
Previously you'd only learn about the issue when saving failed.
Now a modal alert dialog with the error message appears.
This means that we have to wait for the loading to finish before we
can display the ReplyWidget now... this should not be noticeable,
since we preload in #init.
Bug: T247533
Change-Id: I5468e67c449d530a0d15f69bff954d37a5b6a14c
This has two benefits:
* Allows detecting a conflict if two edits are saved in the same second
* Doesn't ignore conflicts with yourself (T246726)
Depends-On: Id7565018f66860b5c2ba688777508db1b88700ae
Bug: T246726
Change-Id: I22eaa1af5692854870d31e08b171a070a2fda0de
This is a problem we can detect at the loading stage, rather than at
the saving stage, so move it from #postReply to #getParsoidCommentData.
Follow-up to e3e4ef9de4.
Change-Id: I19362399f9ff2fdc487ea4900654bc61d990575f
When trying to reply to a comment that is inside a transclusion,
detect if it's transcluded from a subpage or simply wrapped in a
template, and show appropriate error messages.
References:
* VisualEditor ve.dm.Converter#getAboutGroup()
* VisualEditor ve.dm.ModelRegistry#matchElement()
* Parsoid Linter#findEnclosingTemplateName()
Bug: T245694
Change-Id: If3dd1ebbf1d02ee4379c200019bfc3a8ec02325b
We disable the other reply links using 'pointer-events: none' in CSS,
but IE 11 doesn't support that.
I tried hiding them instead and using @supports rules in CSS to apply
'pointer-events: none', but the result was worse than this.
Change-Id: Iab2bfe9c623f3d32cce9776277f33483155a0c42
We always pass the same arguments to the controller method and
two of those are global config values, so just pass the comment ID
each time it is used instead.
Change-Id: Ic68c70bdadb29310e930dd10fd6c6137d01ad22f
Previously they were added at the end of the text node containing the
timestamp, which was usually the end of the line, but not always.
And also fix the same problem for inserting the actual replies (or
reply widgets). This replaces an undocumented hack that prevented our
own reply links from triggering this bug (without it, the reply widget
would be inserted before the reply link rather than after).
While we're here, remove unintentional spacing that appeared before
some reply links, caused by trailing whitespace in text nodes.
Add tests for all of the above.
Bug: T245695
Change-Id: I354b63e2446bb996176a2e3d76abf944127f307e
This is the same as in VisualEditor. ve.parseXhtml has workarounds for
IE 11 bugs that would cause dirty diffs when saving.
Note that we must use ve.serializeXhtml to convert the document back
to a HTML string, but this is already the case (the conversion happens
in mw.libs.ve.targetSaver.saveDoc).
Change-Id: Ib6dec0002eaf33fc0d4a45331a6d38e5c5d7ab8c
The "Reply" buttons were active when viewing an old revision of the
page (&oldid=1234). This was probably unintentional, and it would undo
all more recent comments if you saved yours.
However, I think it would be a useful feature. You often end up
viewing old revisions when reviewing changes to pages from your
watchlist or email notifications.
Now, when the reply widget is launched from an old revision, it will
try to find the relevant parent comment in the latest revision of the
page, and edit that revision when inserting the reply. If the parent
comment is gone, it shows a useful error message.
Bug: T235761
Change-Id: I8c5b631d3bfb62196fd219cbcd7d497408d187a7
The most common case of edit conflicts on talk pages is several people
responding to the same comment at the same time.[citation needed]
We can easily resolve this case by fetching the latest revision of the
page and re-running our code to insert a reply on it.
When we can't insert a reply, that probably means the parent comment
was deleted or moved, so display an error message indicating that
instead of the generic one.
Bug: T240643
Change-Id: Ic686acc747580d46779960211a02e9830a6ae86f
Previously, we only built the Parsoid document once (on page load) and
kept it around forever. Every time we tried to post a reply, it was
added to this document, even if it wasn't saved due to some error.
This resulted in duplicate replies when the user managed to actually
save.
Now we only keep around the HTML string and some metadata fetched from
the API, and rebuild the actual document every time before adding a
reply.
Bug: T245333
Change-Id: Ib1c344a7d613cdf67644aa243147c5e699c2c1e7
This ensures that expired tokens are refreshed and retried, while
invalid tokens caused by the user logging in/out cause an error. We
should think about displaying a better interface for the latter case.
Bug: T245327
Depends-On: I485f99e1f5f493262b0c9af22370da01adf1e09c
Change-Id: Ibc097ed68e3ae72223b0680ee8895f7884399958
Native Range objects are automatically updated when the DOM elements
they refer to are affected (e.g. detached from the DOM, or their offset
changes because of siblings being added/removed).
This seemed harmless or maybe even slightly useful, but it turns out
it conflicts with VisualEditor, which has to wrap the entire page in a
new DOM node when it opens (and unwrap it when it closes), effectively
temporarily detaching it from the DOM, which destroys all our ranges.
Just use a plain object that stores the same data as a Range. And when
we need to use Range's API, we can simply construct a temporary one.
Bug: T241861
Change-Id: Iee64aa3d667877265ef8a59293c202e6478d7fb6
This sets up the tags:
* discussiontools
* discussiontools-reply
* discussiontools-edit (not yet implemented)
* discussiontools-newsection (not yet implemented)
The tags are flagged as user-addable, because otherwise they can't be
passed through to the VE API (at least, not without editing it so that
it explicitly knows about them, which seems like a strange
interdependency). It's assumed that letting users who know about the
tags add them to random changes via action=editchangetags would be
(a) the pettiest and most inconsequential vandalism possible, and
(b) unlikely to happen.
This relies upon I2c1d0f8d69bc03e5c1877c790247e165f160e966 in
VisualEditor to not also tag the edits with `visualeditor`.
Bug: T242184
Change-Id: I4e5e26afdd52279df242e1912f073b415b812c3b
I don't like that I had to special-case `<p>` tags (top-level
comments) in this code. I feel like it should be possible to handle
top-level comments and replies in a generic way, but I couldn't find
a way to do it that actually worked.
Notes about changes to the behavior, based on the test cases:
* Given a top-level comment A, if there was a "list gap" in the
replies to it: previously new replies would be incorrectly added at
the location of the gap; now they are added after the last reply.
(T242822)
Example: "pl", comment at "08:23, 29 wrz 2018 (CEST)"
* Given a top-level comment A and a reply to it B that skips an
indentation level: previously new replies to A would be added with
the same indentation level as B; now they are added with the
indentation level of A plus one. (The old behavior wasn't a bug, and
this is an accidental effect of other changes, but it seems okay.)
Example: "pl", comment at "03:22, 30 wrz 2018 (CEST)"
and reply at "09:43, 30 wrz 2018 (CEST)"
* Given a top-level comment A, a reply to it B, and a following
top-level comment C that starts at the same indentation level as B:
previously new replies to A would be incorrectly added in the middle
of the comment C, due to the DOM list structure; now they are added
before C. (T241391)
(It seems that comment C was supposed to be a multi-line reply that
was wrongly indented. Unfortunately we have no way to distinguish
this case from a top-level multi-line comment that just happens to
start with a bullet list.)
Example: "pl", comments at "03:36, 24 paź 2018 (CEST)",
"08:35, 24 paź 2018 (CEST)", "17:14, 24 paź 2018 (CEST)"
* In the "en" example, there are some other changes where funnily
nested tags result in slightly different results with the new code.
They don't look important.
* In rare cases, we must split an existing list to add a reply in the
right place. (Basically add `</ul>` before the reply and `<ul>`
after, but it's a bit awkward in DOM terms.)
Example: split-list.html, comment "aaa"; also split-list2.html
(which is the result of saving the previous reply), comment "aaa"
* The modifier can no longer generate DOM that is invalid HTML, fixing
a FIXME in modifier.test.js (or at least, it doesn't happen in these
test cases any more).
Bug: T241391
Bug: T242822
Change-Id: I2a70db01e9a8916c5636bc59ea8490166966d5ec
* Add config option $wgDiscussionToolsUseVisualEditor (default false).
* Add new modules ext.discussionTools.ReplyWidgetPlain and ...ReplyWidgetVisual,
replacing ...ReplyWidget. Load only one of them depending on the config.
TODO:
* Also add the visual mode of VisualEditor, this only uses NWE now.
There is already code to support saving from it, but no mode
switcher tool
Co-Authored-By: Ed Sanders <esanders@wikimedia.org>
Co-Authored-By: Bartosz Dziewoński <matma.rex@gmail.com>
Change-Id: I9b6db865d51baf400fb715dc7aa68ccd8cdd4905
* Query parameters for the API must be in lowercase.
* Also, 'starttimestamp' was misspelled.
Bug: T240643
Change-Id: I6497770dfc3a9512af063b846c3f73aa5603b637
Method can be used by preview logic later. Whitespace trimming
avoids sig ending up on newline in a <pre>.
Change-Id: If6f06f17395af0c6645082c1b9493be87422c059
The packageFiles system makes it easier to export site config data
from PHP to JS, which we need a lot of, but it's awkward when mixing
it with defining and accessing classes via a namespace like mw.dt.
The only thing remaining in mw.dt is mw.dt.pageThreads, which is
described to be "for debugging", so we should keep it easy to type.
Also we still use the namespace for documenting classes.
Everything else can be reached by require()'ing a ResourceLoader
module, for example instead of `mw.dt.ui.ReplyWidget`
you'd do `require( 'ext.discussionTools.ReplyWidget' )`.
(When debugging from browser console, use `mw.loader.require` instead.)
Change-Id: I6496abcf58c21658d6fd0f3fc1db1f7380a89df7
Possible use cases:
* Matching comments between PHP and Parsoid HTML [implemented here]
* Finding the same comment in a different revision of a page
(e.g. while resolving an edit conflict, or to allow resuming
composition of autosaved comments) [implemented for highlighting
user's own posted comment only]
* Permanent links to comments [future]
The reasoning for this form of ID is:
* _Timestamp_ by itself is a nearly unique identifier, so it's a good
thing to start with
* Users may post multiple comments in one edit (or in many edits in
one minute), so we need the _sequential number_ to distinguish them
* _Username_ is probably not required, but it may reduce the need
for sequential numbers, and will help with human-readability if we
add permanent links
The ID remains stable when a new comment is added anywhere by anyone
(excepts comments within the same minute by the same user), or when a
section is renamed.
It's not always stable when a comment is moved or when an entire
section is moved or deleted (archived), but you can't have everything.
Change-Id: Idaae6427d659d12b82e37f1791bd03833632c7c0
Otherwise the rest of the page may shift if hiding the link changes
line-wrapping. It felt super confusing when it happened to me while
I was testing an unrelated thing.
https://phabricator.wikimedia.org/F31254175
Change-Id: I53aecdbf3bfba579b48875532d251de0f1c81d6c