diff --git a/php.ini b/php.ini
index 1276578..1daa19c 100644
--- a/php.ini
+++ b/php.ini
@@ -1,7 +1,7 @@
; wikidiff2 extension settings
wikidiff2.change_threshold = 0.2
wikidiff2.moved_line_threshold = 0.4
-wikidiff2.moved_paragraph_detection_cutoff = 100
+wikidiff2.moved_paragraph_detection_cutoff = 5000000
wikidiff2.max_word_level_diff_complexity = 40000000
wikidiff2.max_split_size = 1
wikidiff2.initial_split_threshold = 0.1
diff --git a/test/test_diff_revisions/1295229484_parmove b/test/test_diff_revisions/1295229484_parmove
new file mode 100644
index 0000000..1252450
--- /dev/null
+++ b/test/test_diff_revisions/1295229484_parmove
@@ -0,0 +1,261 @@
+[[User_talk:Groceryheist/archive_1|Archive]]
+
+
__TOC__
+
+== Feedback request: Wikipedia policies and guidelines request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Talk:Tetris#rfc_46F74AF|'''Talk:Tetris''' on a "Society, sports, and culture" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 20:30, 15 April 2025 (UTC)
+
+== Feedback request: Society, sports, and culture request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Talk:Helms Amendment to the Foreign Assistance Act#rfc_AD213F1|'''Talk:Helms Amendment to the Foreign Assistance Act''' on a "Society, sports, and culture" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 20:30, 16 December 2023 (UTC)
+
+== Meetup in Seattle on 16 January 2024 ==
+
+{| style="border: 5px solid #ABCDEF ; background-color: #FFF; padding:10px 15px 0"
+
+|style="padding: 0; vertical-align: middle; height: 1.1em; font-size:130%" |'''[[Wikipedia:Meetup/Seattle|Seattle Wikimedia meetup]] |''' 16 January 2024
+
+|rowspan=3|[[File:Coffee cup in Hanoi, Vietnam.jpg|right|150px]]
+
+|-
+
+|
+
+* What: Meetup to chat about Wikipedia and schedule an edit-a-thon
+
+* When: Tuesday 16 January 2024, 5:45–7:45 pm
+
+*Where: Distant Worlds Coffeehouse at 6401 Roosevelt Way NE, Seattle
+
+* Please come! We'd love to see you.
+
+|-
+
+|colspan=2 style="font-size:85%; padding-top:15px;"|You're receiving this message because you are on [[Wikipedia:Meetup/Seattle/Invitees|our mailing list]]. To opt out of future mailings, please remove your name from the list.
+
+|}
+
+([[User talk:Buidhe|t]] · [[Special:Contributions/Buidhe|c]]) '''[[User:buidhe|buidhe]]''' 05:30, 27 December 2023 (UTC)
+
+
+
+== Notification: Feedback request service is down ==
+
+Hello, {{BASEPAGENAME}}
+
+You may have noticed that you have not received any messages from the [[Wikipedia:Feedback request service]] for over a month. {{noping|Yapperbot}} appears to have stopped delivering messages. Until that can be resolved, please [[Help:Watchlist|watch]] pages that interest you, such as [[Wikipedia:Requests for comment/Wikipedia policies and guidelines]].
+
+This notification has been sent to you as you are subscribed to the [[WP:FRS|Feedback Request Service]]. - [[User:MediaWiki message delivery|MediaWiki message delivery]] ([[User talk:MediaWiki message delivery|talk]]) 08:11, 28 January 2024 (UTC)
+
+
+
+
+
+== Feedback request: Society, sports, and culture request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Talk:2006#rfc_E808A5D|'''Talk:2006''' on a "Society, sports, and culture" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 07:31, 21 February 2024 (UTC)
+
+== Seattle March 2024 Events ==
+
+{|style="border-radius: 8px; padding:5px; width:90%; font-size:100%; border: 1px solid #20BF9F;" align="center"
+
+|-
+
+| rowspan=5 style="padding: 1em 1em;"|[[File:Seattle world fair stamp.jpg|150px|alt=Seattle world fair stamp]]
+
+|style="text-align: center;"|''There are a couple of events this month that we hope are of interest to you.''
+
+|-
+
+|style="text-align: center; font-size: 125%; border: 3px dashed #20BF9F;"|Tuesday, March 12 2024 3pm – 7pm (PDT), [[Wikipedia:Meetup/Seattle#Seattle articles edit-a-thon, Tuesday, March 12 2024 3pm – 7pm (PDT)|'''Seattle articles edit-a-thon''']], Seattle Public Library University Branch
+
+|-
+
+|This edit-a-thon is based on importance or popularity (as determined by pageviews, see [[Wikipedia:WikiProject Seattle/Popular pages]]; or main articles, such as those linked in [[Template:Seattle]]; also see [[Wikipedia:Version 1.0 Editorial Team/Seattle articles by quality statistics]]).
+
+|-
+
+|style="text-align: center; font-size: 125%; border: 3px dashed #20BF9F;"|Tuesday March 19 2024 6pm – 8pm (PDT), [[Wikipedia:Meetup/Seattle#Monthly meetup, Tuesday March 19 2024 6pm – 8pm (PDT)|'''March monthly meetup''']], Little Oddfellows Café—''new location!!!''
+
+|-
+
+|Since our previous meeting place, Distant Worlds Café, now closes at 6:30pm, we will meet this month at Little Oddfellows café inside of Elliott Bay Book Company in Capitol Hill.
+
+|}
+
+[[File:Cascadiawikimedians transparent Gill Sans 155px high.png|15px|link=:meta:Cascadia Wikimedians]] [[:meta:Cascadia Wikimedians|Cascadia Wikimedians]] placed this banner at 01:02, 9 March 2024 (UTC) by using the [[Wikipedia:Meetup/Portland/Participants]] list.
To subscribe to or unsubscribe from messages from [[Wikipedia:Meetup/Portland]], please add or remove your name [[Wikipedia:Meetup/Portland/Participants|here]].
+
+
+
+== Feedback request: Society, sports, and culture request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Talk:Whadjuk#rfc_BB5035A|'''Talk:Whadjuk''' on a "Society, sports, and culture" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 04:31, 17 March 2024 (UTC)
+
+== Feedback request: Society, sports, and culture request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Wikipedia:Reliable sources/Noticeboard#rfc_4B249A8|'''Wikipedia:Reliable sources/Noticeboard''' on a "Society, sports, and culture" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 01:30, 7 April 2024 (UTC)
+
+== Feedback request: Maths, science, and technology request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Wikipedia talk:WikiProject Weather/Tornadoes of XXXX criteria#rfc_467C7B2|'''Wikipedia talk:WikiProject Weather/Tornadoes of XXXX criteria''' on a "Maths, science, and technology" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 20:30, 23 April 2024 (UTC)
+
+== Feedback request: Maths, science, and technology request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Talk:Havana syndrome#rfc_9FB246D|'''Talk:Havana syndrome''' on a "Maths, science, and technology" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 03:31, 25 April 2024 (UTC)
+
+== Feedback request: Society, sports, and culture request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Talk:Aidi#rfc_9745B22|'''Talk:Aidi''' on a "Society, sports, and culture" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 07:30, 24 May 2024 (UTC)
+
+== Feedback request: Society, sports, and culture request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Wikipedia talk:WikiProject Baseball#rfc_10B411F|'''Wikipedia talk:WikiProject Baseball''' on a "Society, sports, and culture" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 17:31, 28 May 2024 (UTC)
+
+== Seattle Wiknic 11 August 2024 ==
+
+{| style="border: 5px solid #ABCDEF ; background-color: #FFF; padding:10px 15px 0"
+
+|style="padding: 0; vertical-align: middle; height: 1.1em; font-size:130%" |'''[[Wikipedia:Meetup/Seattle/Wiknic/2024|2024 Seattle Wiknic]] |''' 11 August 2024
+
+|rowspan=3|[[File:Seattle Wiknic 2019 at Washington Park Arboretum.jpg|right|150px]]
+
+|-
+
+|
+
+* What: Picnic to eat food and chat with other Wikimedians
+
+* When: Sunday 11 August 2024, noon–3 pm
+
+* Where: picnic tables in the meadow area at [[Washington Park Arboretum]]
+
+* Please come and bring food! We'd love to see you.
+
+|-
+
+|colspan=2 style="font-size:85%; padding-top:15px;"|You're receiving this message because you are on [[Wikipedia:Meetup/Seattle/Invitees|our mailing list]]. To opt out of future mailings, please remove your name from the list.
+
+|}
+
+([[User talk:Buidhe|t]] · [[Special:Contributions/Buidhe|c]]) '''[[User:buidhe|buidhe]]''' 04:37, 1 August 2024 (UTC)
+
+
+
+== Feedback requests from the Feedback Request Service ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Wikipedia talk:WikiProject Sports#rfc_2E0CECA|'''Wikipedia talk:WikiProject Sports''']] and [[Talk:Morocco#rfc_B5C588A|'''Talk:Morocco''']] on "Society, sports, and culture" request for comments, and at [[Talk:Toxicology#rfc_646EFFA|'''Talk:Toxicology''' on a "Maths, science, and technology" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 12:33, 29 August 2024 (UTC)
+
+== Feedback request: Society, sports, and culture request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Talk:2023 Nashville school shooting#rfc_DCA51ED|'''Talk:2023 Nashville school shooting''' on a "Society, sports, and culture" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 02:32, 4 September 2024 (UTC)
+
+== Saying Hi ==
+
+Hi Groceryheist! Am I doing this whole talk page thing right? Let me know! By the way, I'm enjoying class so far.
+
+[[User:KoiTheFish|KoiTheFish]] ([[User talk:KoiTheFish|talk]]) 23:08, 6 September 2024 (UTC)
+
+:You got it! Thank you! [[User:Groceryheist|Groceryheist]] ([[User talk:Groceryheist#top|talk]]) 01:59, 7 September 2024 (UTC)
+
+== Hello ==
+
+Hi! Just wanted to say hello! Great class so far!
+
+--[[User:Pinkdolphinbird|Pinkdolphinbird]] ([[User talk:Pinkdolphinbird|talk]]) 03:18, 7 September 2024 (UTC)
+
+:Hi {{u|Pinkdolphinbird}}. Thanks for saying Hello! I'm glad you're enjoying the class. [[User:Groceryheist|Groceryheist]] ([[User talk:Groceryheist#top|talk]]) 03:28, 8 September 2024 (UTC)
+
+== Feedback request: Society, sports, and culture request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Talk:2024 Kolkata rape and murder incident#rfc_7F245C4|'''Talk:2024 Kolkata rape and murder incident''' on a "Society, sports, and culture" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 17:30, 9 September 2024 (UTC)
+
+== Feedback request: Wikipedia policies and guidelines request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Wikipedia talk:Notability#rfc_6E14382|'''Wikipedia talk:Notability''' on a "Wikipedia policies and guidelines" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 17:30, 10 September 2024 (UTC)
+
+== Hello! ==
+
+Hi groceryheist! Just wanted to say hi 👋 [[User:Fluffycatlover|Fluffycatlover]] ([[User talk:Fluffycatlover|talk]]) 20:41, 10 September 2024 (UTC)
+
+== Feedback request: Wikipedia policies and guidelines request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Wikipedia:Village pump (policy)#rfc_E1CEF9F|'''Wikipedia:Village pump (policy)''' on a "Wikipedia policies and guidelines" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 01:30, 18 October 2024 (UTC)
+
+== Feedback request: Wikipedia policies and guidelines request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Wikipedia:Requests for comment/Grey Literature#rfc_402ED76|'''Wikipedia:Requests for comment/Grey Literature''' on a "Wikipedia policies and guidelines" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 17:31, 10 November 2024 (UTC)
+
+== ArbCom 2024 Elections voter message ==
+
+
+
+
[[File:Scale of justice 2.svg|40px]]
+
+
+
+Hello! Voting in the '''[[WP:ACE2024|2024 Arbitration Committee elections]]''' is now open until 23:59 (UTC) on {{#time:l, j F Y|{{Arbitration Committee candidate/data|2024|end}}-1 day}}. All '''[[Wikipedia:Arbitration Committee Elections December 2024#Election timeline|eligible users]]''' are allowed to vote. Users with alternate accounts may only vote once.
+
+The [[WP:ARBCOM|Arbitration Committee]] is the panel of editors responsible for conducting the [[Wikipedia:Arbitration|Wikipedia arbitration process]]. It has the authority to impose binding solutions to disputes between editors, primarily for serious conduct disputes the community has been unable to resolve. This includes the authority to impose [[WP:BAN|site bans]], [[WP:TBAN|topic bans]], editing restrictions, and other measures needed to maintain our editing environment. The [[Wikipedia:Arbitration/Policy|arbitration policy]] describes the Committee's roles and responsibilities in greater detail.
+
+If you wish to participate in the 2024 election, please review [[Wikipedia:Arbitration Committee Elections December 2024/Candidates|the candidates]] and submit your choices on the '''[[Special:SecurePoll/vote/{{Arbitration Committee candidate/data|2024|poll}}|voting page]]'''. If you no longer wish to receive these messages, you may add {{tlx|NoACEMM}} to your user talk page. [[User:MediaWiki message delivery|MediaWiki message delivery]] ([[User talk:MediaWiki message delivery|talk]]) 00:13, 19 November 2024 (UTC)
+
+
+
+
+
+
+
+== Seattle Wikipedia Day, January 11, 2025 ==
+
+{|style="border-radius: 8px; padding:5px; width:90%; font-size:100%; border: 1px solid #20BF9F;" align="center"
+
+|-
+
+|rowspan=4|[[File:Wikipedia 20 birthday cake.jpg |left |290px |link=Wikipedia:Wikipedia Day]]
+
+|style="text-align: center;" |{{large|''Seattle Wikipedia Day''}}
+
+''Saturday afternoon, January 11, from 1:00–4:30pm PT at the Capitol Hill Meeting Room at [[Capitol Hill Branch Library]] (425 Harvard Ave. E., Seattle, WA 98102)''
+
+[[Wikipedia:Wikipedia Day|Wikipedia Day]] celebrates the anniversary of the founding of Wikipedia. This year we will observe Wikipedia Day with an [[edit-a-thon]] to improve the [[Seattle]] and other articles important to [[WP:WikiProject Seattle|WikiProject Seattle]], such as [[History of Seattle]], [[Puget Sound]], [[Lake Union]], [[Lake Washington]], [[Pioneer Square, Seattle|Pioneer Square]], [[Seattle Center]], [[Tacoma, Washington|Tacoma]], and [[University of Washington]].
+
+'''→''Sign up at [[Wikipedia:Meetup/Seattle/Wikipedia Day 2025]]!''←'''
+
+You can also read and add to the [[Wikipedia talk:Meetup/Seattle/Wikipedia Day 2025|task list]].
+
+Please remember to check our [[Wikipedia:Meetup/Seattle#Scheduled meetups in Seattle|Seattle meetup schedule]] each month for upcoming events.
+
+|rowspan=4|[[File:Space Needle 1 2016-08-15.jpg |left |200px |link=Wikipedia:WikiProject Seattle]]
+
+|}
+
+06:12, 1 January 2025 (UTC) To unsubscribe from future messages from [[Wikipedia:Meetup/Seattle]], please remove your name from [[Wikipedia:Meetup/Seattle/Invitees|this list]].
+
+
+
+== Feedback request: Wikipedia policies and guidelines request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Wikipedia:Reliable sources/Noticeboard#rfc_8CACBB0|'''Wikipedia:Reliable sources/Noticeboard''' on a "Wikipedia policies and guidelines" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 09:30, 18 February 2025 (UTC)
+
+== Feedback request: Society, sports, and culture request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Talk:Aristides de Sousa Mendes#rfc_283E464|'''Talk:Aristides de Sousa Mendes''' on a "Society, sports, and culture" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 23:30, 10 March 2025 (UTC)
+
+== Feedback request: Society, sports, and culture request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Wikipedia:Reliable sources/Noticeboard#rfc_3F06890|'''Wikipedia:Reliable sources/Noticeboard''' on a "Society, sports, and culture" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 01:32, 12 March 2025 (UTC)
+
+== Feedback request: Maths, science, and technology request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Talk:Nonmetal#rfc_38273CE|'''Talk:Nonmetal''' on a "Maths, science, and technology" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 10:30, 6 April 2025 (UTC)
+
+== Feedback request: Society, sports, and culture request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Wikipedia:Requests for coment/Names of deceased trans people#rfc_2DE3507|'''Wikipedia:Requests for coment/Names of deceased trans people''' on a "Wikipedia policies and guidelines" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 07:30, 14 December 2023 (UTC)
+
+
+== Feedback request: Society, sports, and culture request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Talk:Muffin#rfc_A0750CE|'''Talk:Muffin''' on a "Society, sports, and culture" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 13:46, 12 June 2025 (UTC)
+
diff --git a/test/test_diff_revisions/1295229484_parmove_and_change b/test/test_diff_revisions/1295229484_parmove_and_change
new file mode 100644
index 0000000..a22534f
--- /dev/null
+++ b/test/test_diff_revisions/1295229484_parmove_and_change
@@ -0,0 +1,260 @@
+[[User_talk:Groceryheist/archive_1|Archive]]
+
+__TOC__
+
+== Feedback request: Wikipedia policies and guidelines request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Wikipedia:Requests for coment/Names of deceased trans people#rfc_2DE3507|'''Wikipedia:Requests for coment/Names of deceased trans people''' on a "Wikipedia policies and guidelines" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 07:30, 14 December 2023 (UTC)
+
+== Feedback request: Society, sports, and culture request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Talk:Helms Amendment to the Foreign Assistance Act#rfc_AD213F1|'''Talk:Helms Amendment to the Foreign Assistance Act''' on a "Society, sports, and culture" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 20:30, 16 December 2023 (UTC)
+
+== Meetup in Seattle on 16 January 2024 ==
+
+{| style="border: 5px solid #ABCDEF ; background-color: #FFF; padding:10px 15px 0"
+
+|style="padding: 0; vertical-align: middle; height: 1.1em; font-size:130%" |'''[[Wikipedia:Meetup/Seattle|Seattle Wikimedia meetup]] |''' 16 January 2024
+
+|rowspan=3|[[File:Coffee cup in Hanoi, Vietnam.jpg|right|150px]]
+
+|-
+
+|
+
+* What: Meetup to chat about Wikipedia and schedule an edit-a-thon
+
+* When: Tuesday 16 January 2024, 5:45–7:45 pm
+
+*Where: Distant Worlds Coffeehouse at 6401 Roosevelt Way NE, Seattle
+
+* Please come! We'd love to see you.
+
+|-
+
+|colspan=2 style="font-size:85%; padding-top:15px;"|You're receiving this message because you are on [[Wikipedia:Meetup/Seattle/Invitees|our mailing list]]. To opt out of future mailings, please remove your name from the list.
+
+|}
+
+([[User talk:Buidhe|t]] · [[Special:Contributions/Buidhe|c]]) '''[[User:buidhe|buidhe]]''' 05:30, 27 December 2023 (UTC)
+
+
+
+== Notification: Feedback request service is down ==
+
+Hello, {{BASEPAGENAME}}
+
+This notification has been sent to you as you are subscribed to the [[WP:FRS|Feedback Request Service]]. - [[User:MediaWiki message delivery|MediaWiki message delivery]] ([[User talk:MediaWiki message delivery|talk]]) 08:11, 28 January 2024 (UTC)
+
+You have probably not noticed that you have not received any messages from the [[Wikipedia:Feedback request service]] for over a month. {{noping|Yapperbot}} appears to have stopped delivering messages,whoops. Please just [[Help:Watchlist|watch]] pages that interest you, such as [[Wikipedia:Requests for comment/Wikipedia policies and guidelines]].
+
+
+
+
+
+== Feedback request: Society, sports, and culture request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Talk:2006#rfc_E808A5D|'''Talk:2006''' on a "Society, sports, and culture" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 07:31, 21 February 2024 (UTC)
+
+== Seattle March 2024 Events ==
+
+{|style="border-radius: 8px; padding:5px; width:90%; font-size:100%; border: 1px solid #20BF9F;" align="center"
+
+|-
+
+| rowspan=5 style="padding: 1em 1em;"|[[File:Seattle world fair stamp.jpg|150px|alt=Seattle world fair stamp]]
+
+|style="text-align: center;"|''There are a couple of events this month that we hope are of interest to you.''
+
+|-
+
+|style="text-align: center; font-size: 125%; border: 3px dashed #20BF9F;"|Tuesday, March 12 2024 3pm – 7pm (PDT), [[Wikipedia:Meetup/Seattle#Seattle articles edit-a-thon, Tuesday, March 12 2024 3pm – 7pm (PDT)|'''Seattle articles edit-a-thon''']], Seattle Public Library University Branch
+
+|-
+
+|This edit-a-thon is based on importance or popularity (as determined by pageviews, see [[Wikipedia:WikiProject Seattle/Popular pages]]; or main articles, such as those linked in [[Template:Seattle]]; also see [[Wikipedia:Version 1.0 Editorial Team/Seattle articles by quality statistics]]).
+
+|-
+
+|style="text-align: center; font-size: 125%; border: 3px dashed #20BF9F;"|Tuesday March 19 2024 6pm – 8pm (PDT), [[Wikipedia:Meetup/Seattle#Monthly meetup, Tuesday March 19 2024 6pm – 8pm (PDT)|'''March monthly meetup''']], Little Oddfellows Café—''new location!!!''
+
+|-
+
+|Since our previous meeting place, Distant Worlds Café, now closes at 6:30pm, we will meet this month at Little Oddfellows café inside of Elliott Bay Book Company in Capitol Hill.
+
+|}
+
+[[File:Cascadiawikimedians transparent Gill Sans 155px high.png|15px|link=:meta:Cascadia Wikimedians]] [[:meta:Cascadia Wikimedians|Cascadia Wikimedians]] placed this banner at 01:02, 9 March 2024 (UTC) by using the [[Wikipedia:Meetup/Portland/Participants]] list.
To subscribe to or unsubscribe from messages from [[Wikipedia:Meetup/Portland]], please add or remove your name [[Wikipedia:Meetup/Portland/Participants|here]].
+
+
+
+== Feedback request: Society, sports, and culture request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Talk:Whadjuk#rfc_BB5035A|'''Talk:Whadjuk''' on a "Society, sports, and culture" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 04:31, 17 March 2024 (UTC)
+
+== Feedback request: Society, sports, and culture request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Wikipedia:Reliable sources/Noticeboard#rfc_4B249A8|'''Wikipedia:Reliable sources/Noticeboard''' on a "Society, sports, and culture" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 01:30, 7 April 2024 (UTC)
+
+== Feedback request: Maths, science, and technology request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Wikipedia talk:WikiProject Weather/Tornadoes of XXXX criteria#rfc_467C7B2|'''Wikipedia talk:WikiProject Weather/Tornadoes of XXXX criteria''' on a "Maths, science, and technology" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 20:30, 23 April 2024 (UTC)
+
+== Feedback request: Maths, science, and technology request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Talk:Havana syndrome#rfc_9FB246D|'''Talk:Havana syndrome''' on a "Maths, science, and technology" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 03:31, 25 April 2024 (UTC)
+
+== Feedback request: Society, sports, and culture request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Talk:Aidi#rfc_9745B22|'''Talk:Aidi''' on a "Society, sports, and culture" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 07:30, 24 May 2024 (UTC)
+
+== Feedback request: Society, sports, and culture request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Wikipedia talk:WikiProject Baseball#rfc_10B411F|'''Wikipedia talk:WikiProject Baseball''' on a "Society, sports, and culture" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 17:31, 28 May 2024 (UTC)
+
+== Seattle Wiknic 11 August 2024 ==
+
+{| style="border: 5px solid #ABCDEF ; background-color: #FFF; padding:10px 15px 0"
+
+|style="padding: 0; vertical-align: middle; height: 1.1em; font-size:130%" |'''[[Wikipedia:Meetup/Seattle/Wiknic/2024|2024 Seattle Wiknic]] |''' 11 August 2024
+
+|rowspan=3|[[File:Seattle Wiknic 2019 at Washington Park Arboretum.jpg|right|150px]]
+
+|-
+
+|
+
+* What: Picnic to eat food and chat with other Wikimedians
+
+* When: Sunday 11 August 2024, noon–3 pm
+
+* Where: picnic tables in the meadow area at [[Washington Park Arboretum]]
+
+* Please come and bring food! We'd love to see you.
+
+|-
+
+|colspan=2 style="font-size:85%; padding-top:15px;"|You're receiving this message because you are on [[Wikipedia:Meetup/Seattle/Invitees|our mailing list]]. To opt out of future mailings, please remove your name from the list.
+
+|}
+
+([[User talk:Buidhe|t]] · [[Special:Contributions/Buidhe|c]]) '''[[User:buidhe|buidhe]]''' 04:37, 1 August 2024 (UTC)
+
+
+
+== Feedback requests from the Feedback Request Service ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Wikipedia talk:WikiProject Sports#rfc_2E0CECA|'''Wikipedia talk:WikiProject Sports''']] and [[Talk:Morocco#rfc_B5C588A|'''Talk:Morocco''']] on "Society, sports, and culture" request for comments, and at [[Talk:Toxicology#rfc_646EFFA|'''Talk:Toxicology''' on a "Maths, science, and technology" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 12:33, 29 August 2024 (UTC)
+
+== Feedback request: Society, sports, and culture request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Talk:2023 Nashville school shooting#rfc_DCA51ED|'''Talk:2023 Nashville school shooting''' on a "Society, sports, and culture" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 02:32, 4 September 2024 (UTC)
+
+== Saying Hi ==
+
+Hi Groceryheist! Am I doing this whole talk page thing right? Let me know! By the way, I'm enjoying class so far.
+
+[[User:KoiTheFish|KoiTheFish]] ([[User talk:KoiTheFish|talk]]) 23:08, 6 September 2024 (UTC)
+
+:You got it! Thank you! [[User:Groceryheist|Groceryheist]] ([[User talk:Groceryheist#top|talk]]) 01:59, 7 September 2024 (UTC)
+
+== Hello ==
+
+Hi! Just wanted to say hello! Great class so far!
+
+--[[User:Pinkdolphinbird|Pinkdolphinbird]] ([[User talk:Pinkdolphinbird|talk]]) 03:18, 7 September 2024 (UTC)
+
+:Hi {{u|Pinkdolphinbird}}. Thanks for saying Hello! I'm glad you're enjoying the class. [[User:Groceryheist|Groceryheist]] ([[User talk:Groceryheist#top|talk]]) 03:28, 8 September 2024 (UTC)
+
+== Feedback request: Society, sports, and culture request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Talk:2024 Kolkata rape and murder incident#rfc_7F245C4|'''Talk:2024 Kolkata rape and murder incident''' on a "Society, sports, and culture" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 17:30, 9 September 2024 (UTC)
+
+== Feedback request: Wikipedia policies and guidelines request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Wikipedia talk:Notability#rfc_6E14382|'''Wikipedia talk:Notability''' on a "Wikipedia policies and guidelines" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 17:30, 10 September 2024 (UTC)
+
+== Hello! ==
+
+Hi groceryheist! Just wanted to say hi 👋 [[User:Fluffycatlover|Fluffycatlover]] ([[User talk:Fluffycatlover|talk]]) 20:41, 10 September 2024 (UTC)
+
+== Feedback request: Wikipedia policies and guidelines request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Wikipedia:Village pump (policy)#rfc_E1CEF9F|'''Wikipedia:Village pump (policy)''' on a "Wikipedia policies and guidelines" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 01:30, 18 October 2024 (UTC)
+
+== Feedback request: Wikipedia policies and guidelines request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Wikipedia:Requests for comment/Grey Literature#rfc_402ED76|'''Wikipedia:Requests for comment/Grey Literature''' on a "Wikipedia policies and guidelines" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 17:31, 10 November 2024 (UTC)
+
+== ArbCom 2024 Elections voter message ==
+
+
+
+
[[File:Scale of justice 2.svg|40px]]
+
+
+
+Hello! Voting in the '''[[WP:ACE2024|2024 Arbitration Committee elections]]''' is now open until 23:59 (UTC) on {{#time:l, j F Y|{{Arbitration Committee candidate/data|2024|end}}-1 day}}. All '''[[Wikipedia:Arbitration Committee Elections December 2024#Election timeline|eligible users]]''' are allowed to vote. Users with alternate accounts may only vote once.
+
+The [[WP:ARBCOM|Arbitration Committee]] is the panel of editors responsible for conducting the [[Wikipedia:Arbitration|Wikipedia arbitration process]]. It has the authority to impose binding solutions to disputes between editors, primarily for serious conduct disputes the community has been unable to resolve. This includes the authority to impose [[WP:BAN|site bans]], [[WP:TBAN|topic bans]], editing restrictions, and other measures needed to maintain our editing environment. The [[Wikipedia:Arbitration/Policy|arbitration policy]] describes the Committee's roles and responsibilities in greater detail.
+
+If you wish to participate in the 2024 election, please review [[Wikipedia:Arbitration Committee Elections December 2024/Candidates|the candidates]] and submit your choices on the '''[[Special:SecurePoll/vote/{{Arbitration Committee candidate/data|2024|poll}}|voting page]]'''. If you no longer wish to receive these messages, you may add {{tlx|NoACEMM}} to your user talk page. [[User:MediaWiki message delivery|MediaWiki message delivery]] ([[User talk:MediaWiki message delivery|talk]]) 00:13, 19 November 2024 (UTC)
+
+
+
+
+
+
+
+== Seattle Wikipedia Day, January 11, 2025 ==
+
+{|style="border-radius: 8px; padding:5px; width:90%; font-size:100%; border: 1px solid #20BF9F;" align="center"
+
+|-
+
+|rowspan=4|[[File:Wikipedia 20 birthday cake.jpg |left |290px |link=Wikipedia:Wikipedia Day]]
+
+|style="text-align: center;" |{{large|''Seattle Wikipedia Day''}}
+
+''Saturday afternoon, January 11, from 1:00–4:30pm PT at the Capitol Hill Meeting Room at [[Capitol Hill Branch Library]] (425 Harvard Ave. E., Seattle, WA 98102)''
+
+[[Wikipedia:Wikipedia Day|Wikipedia Day]] celebrates the anniversary of the founding of Wikipedia. This year we will observe Wikipedia Day with an [[edit-a-thon]] to improve the [[Seattle]] and other articles important to [[WP:WikiProject Seattle|WikiProject Seattle]], such as [[History of Seattle]], [[Puget Sound]], [[Lake Union]], [[Lake Washington]], [[Pioneer Square, Seattle|Pioneer Square]], [[Seattle Center]], [[Tacoma, Washington|Tacoma]], and [[University of Washington]].
+
+'''→''Sign up at [[Wikipedia:Meetup/Seattle/Wikipedia Day 2025]]!''←'''
+
+You can also read and add to the [[Wikipedia talk:Meetup/Seattle/Wikipedia Day 2025|task list]].
+
+Please remember to check our [[Wikipedia:Meetup/Seattle#Scheduled meetups in Seattle|Seattle meetup schedule]] each month for upcoming events.
+
+|rowspan=4|[[File:Space Needle 1 2016-08-15.jpg |left |200px |link=Wikipedia:WikiProject Seattle]]
+
+|}
+
+06:12, 1 January 2025 (UTC) To unsubscribe from future messages from [[Wikipedia:Meetup/Seattle]], please remove your name from [[Wikipedia:Meetup/Seattle/Invitees|this list]].
+
+
+
+== Feedback request: Wikipedia policies and guidelines request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Wikipedia:Reliable sources/Noticeboard#rfc_8CACBB0|'''Wikipedia:Reliable sources/Noticeboard''' on a "Wikipedia policies and guidelines" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 09:30, 18 February 2025 (UTC)
+
+== Feedback request: Society, sports, and culture request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Talk:Aristides de Sousa Mendes#rfc_283E464|'''Talk:Aristides de Sousa Mendes''' on a "Society, sports, and culture" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 23:30, 10 March 2025 (UTC)
+
+== Feedback request: Society, sports, and culture request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Wikipedia:Reliable sources/Noticeboard#rfc_3F06890|'''Wikipedia:Reliable sources/Noticeboard''' on a "Society, sports, and culture" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 01:32, 12 March 2025 (UTC)
+
+== Feedback request: Maths, science, and technology request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Talk:Nonmetal#rfc_38273CE|'''Talk:Nonmetal''' on a "Maths, science, and technology" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 10:30, 6 April 2025 (UTC)
+
+== Feedback request: Society, sports, and culture request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Talk:Tetris#rfc_46F74AF|'''Talk:Tetris''' on a "Society, sports, and culture" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 20:30, 15 April 2025 (UTC)
+
+== Feedback request: Society, sports, and culture request for comment ==
+
+[[File:Internet-group-chat.svg|48px|left|alt=|link=]]Your feedback is requested at [[Talk:Muffin#rfc_A0750CE|'''Talk:Muffin''' on a "Society, sports, and culture" request for comment]]. Thank you for helping out!
You were randomly selected to receive this invitation from the list of [[WP:FRS|Feedback Request Service]] subscribers. If you'd like not to receive these messages any more, you can opt out at any time by [[WP:FRS|removing your name]]. Message delivered to you with love by [[User:Yapperbot|Yapperbot]] :) | Is this wrong? Contact [[User talk:Naypta|my bot operator]]. | Sent at 13:46, 12 June 2025 (UTC)
+
diff --git a/test/test_wiki_diff_matcher.py b/test/test_wiki_diff_matcher.py
index 33b0047..ea98184 100644
--- a/test/test_wiki_diff_matcher.py
+++ b/test/test_wiki_diff_matcher.py
@@ -27,7 +27,11 @@ async def start_stop_server():
def assert_equal_enough(tokens:List[Token], rev):
# the tokens exclude newlines
# we allow extra whitespace at the beginning or end
- assert ''.join([str(t) for t in tokens]).strip() == rev.replace('\n','').strip()
+ token_doc = ''.join(str(t) for t in tokens).strip()
+ rev_doc = rev.replace('\n','').strip()
+ print(token_doc, file = open('token','w'))
+ print(rev_doc, file = open('rev','w'))
+ assert token_doc == rev_doc
def assert_correct_equal_section(ops, expected_equal_lines, expected_equal_tokens):
@@ -128,8 +132,6 @@ def test_delete():
expected_equal_tokens=9323)
-
-
# first lets test that we properly build the operations.
# then we can test if the state seems to work as intended.
def test_addition():
@@ -170,3 +172,29 @@ def test_addition():
assert n_inserted_tokens == last_b2 - initial_equal_tokens == 292
assert n_inserts == 2
+def test_paragraph_move():
+ rev1 = open("test/test_diff_revisions/1295229484").read()
+ rev2 = open("test/test_diff_revisions/1295229484_parmove").read()
+ matcher = WikiDiffMatcher([rev1,rev2])
+ diff_processor = matcher.processor()
+
+ # note that a and b are constructed from the diffs.
+ # so they reflect the state of the text according to the diff processor
+ ops, a, b = diff_processor.process(rev1)
+ ops, a, b = diff_processor.process(rev2)
+ assert_equal_enough(b, rev2)
+ assert_equal_enough(a, rev1)
+
+def test_paragraph_move_and_change():
+ rev1 = open("test/test_diff_revisions/1295229484").read()
+ rev2 = open("test/test_diff_revisions/1295229484_parmove_and_change").read()
+ matcher = WikiDiffMatcher([rev1,rev2])
+ diff_processor = matcher.processor()
+
+ # note that a and b are constructed from the diffs.
+ # so they reflect the state of the text according to the diff processor
+ ops, a, b = diff_processor.process(rev1)
+ ops, a, b = diff_processor.process(rev2)
+ assert_equal_enough(b, rev2)
+ assert_equal_enough(a, rev1)
+
diff --git a/wiki_diff_matcher.py b/wiki_diff_matcher.py
index b807c75..1399ffb 100644
--- a/wiki_diff_matcher.py
+++ b/wiki_diff_matcher.py
@@ -1,14 +1,26 @@
import json
import sys
+from collections import namedtuple
from itertools import chain
-from typing import Generator, List, Optional, Tuple
+from typing import Dict, Generator, List, Optional, Tuple
+
import requests
-from deltas import (Delete, DiffEngine, Equal, Insert, Operation,
- RegexTokenizer, Token, tokenizers)
+from deltas import Equal, Insert, Delete, DiffEngine, Operation, RegexTokenizer, tokenizers
TOKENIZER = tokenizers.wikitext_split
+def find_greatest_le_key(target_key, data_dict):
+ for key in data_dict: # Iterates over keys in insertion order (which is sorted)
+ if key <= target_key:
+ found_key = (
+ key # This is the largest key found so far that satisfies the condition
+ )
+ else:
+ # Since the dictionary is sorted, if key > target_key,
+ # all subsequent keys will also be > target_key.
+ return found_key or key
+
def compute_diffs(url: str, texts: list[str]) -> list:
response = None
@@ -38,26 +50,15 @@ def compute_diffs(url: str, texts: list[str]) -> list:
print(f"An unexpected error occurred: {e}")
raise e
- # for diff in incremental_diffs:
- # for wikidiffop in json.loads(diff)["diff"][0:5]:
- # print(wikidiffop)
-
return incremental_diffs
class DiffToOperationMap:
-
- def __init__(self, from_text, to_text, diff, tokenizer):
-
- self.diff = diff
+ def __init__(self, diff, tokenizer):
self.tokenizer = tokenizer
self.diff = json.loads(diff)
# the code below is designed to work in bytes because that's how wikidiff2 indexes
- self.from_bytes = from_text.encode("utf-8")
- self.to_bytes = to_text.encode("utf-8")
-
-
self.from_last_end_bytes = 0
self.from_last_to_bytes = 0
self.n_from_start_tokens = 0
@@ -66,19 +67,22 @@ class DiffToOperationMap:
self.last_from_start_line = 0
self.from_last_end_bytes = 0
self.to_last_end_bytes = 0
-
+ # keeps track of the number of tokens seen so far
+ # to avoid repeated tokenization
+ self.from_byte_token_index_map: Dict[int, int] = {}
+ self.to_byte_token_index_map: Dict[int, int] = {}
+ self.par_move_dict = {}
+
def tokenize(self, bytes):
return self.tokenizer.tokenize(bytes.decode("utf-8"))
def to_operations(self):
- parmove_from_dict = {} # lookup move diffs based on moveinfo id.
- parmove_to_dict = {}
+ parmoves = []
for entry in self.diff["diff"]:
- offset = entry['offset']
- linebytes = entry["text"].encode("utf-8")
-
+ offset = entry["offset"]
+ text = entry["text"]
# ignore empty diffs. They don't have any tokens
- if len(linebytes) == 0:
+ if len(text) == 0:
continue
# this is the first byte of the line in the 'from' revision.
from_start_line = entry["offset"]["from"]
@@ -86,32 +90,35 @@ class DiffToOperationMap:
to_start_line = entry["offset"]["to"]
if entry["type"] == 0:
- yield from self.doEqual(linebytes, offset)
-
+ yield from self.doEqual(text, offset)
+
# a line included in the 'to' revision, but not in the 'from' revision
elif entry["type"] == 1:
- yield from self.doInsert(linebytes, offset)
+ yield from self.doInsert(text, offset)
# a line included in the 'from' revision, but not in the 'to' revision
elif entry["type"] == 2:
- yield from self.doDelete(linebytes, offset)
-
+ yield from self.doDelete(text, offset)
+
elif entry["type"] == 3:
- yield from self.doHighlightRange(linebytes, entry['highlightRanges'], offset)
-
+ yield from self.doHighlightRange(
+ text, entry["highlightRanges"], offset
+ )
+
elif entry["type"] == 4:
- parmove_from_dict["moveInfo"]["id"] = diff
+ self.par_move_dict[entry["moveInfo"]["id"]] = entry
+
+ # we need to count the tokens in the from revision so token index is correct
+ self.n_from_end_tokens += len(self.tokenize(entry['text'].encode()))
+ self.n_from_start_tokens += len(self.tokenize(entry['text'].encode()))
elif entry["type"] == 5:
- # for type 4 diffs (paragraph moved in the from revision) we need to find a matching type 5 diff.
- parmove_to_dict["moveInfo"]["id"] = diff
- # for deletions and equality report the token indexes from the 'from' revision.
+ yield from self.doParMove(entry)
else:
# The 'type' isn't one of the known
raise ValueError(d)
-
# mwpersistence expects differences to be represented in order from the
# result's perspective ("to"), not the previous text. Thus, if a line
# is moved earlier then its insertion should appear before its deletion.
@@ -119,16 +126,16 @@ class DiffToOperationMap:
# strictly increasing, while the "from" segments should merely be
# non-overlapping.
- # now we go through the parmoves
- for id, from_diff in parmove_from_dict.items():
- to_diff = parmove_from_dict[from_diff["moveInfo"]["linkId"]]
-
- def doEqual(self, equal_bytes, offset):
+ def doEqual(self, equal_text, offset):
+ equal_bytes = equal_text.encode()
tokens = self.tokenize(equal_bytes)
n_tokens = len(tokens)
self.n_from_end_tokens = self.n_from_start_tokens + n_tokens
self.n_to_end_tokens = self.n_to_start_tokens + n_tokens
+ # we need to keep track of the to and from last end bytes
+ self.from_last_end_bytes = offset["from"] + len(equal_bytes)
+ self.to_last_end_bytes = offset["to"] + len(equal_bytes)
yield (
Equal(
self.n_from_start_tokens,
@@ -139,17 +146,20 @@ class DiffToOperationMap:
tokens,
tokens,
)
- # we need to keep track of the to and from last end bytes
- self.from_last_end_bytes = offset["from"] + len(equal_bytes)
- self.to_last_end_bytes = offset["to"] + len(equal_bytes)
+
self.n_from_start_tokens += n_tokens
self.n_to_start_tokens += n_tokens
+ self.from_byte_token_index_map[
+ offset['from']
+ ] = self.n_from_end_tokens
+ self.to_byte_token_index_map[offset['to']] = self.n_to_end_tokens
-
- def doInsert(self, insert_bytes, offset):
+ def doInsert(self, insert_text, offset):
+ insert_bytes = insert_text.encode()
tokens = self.tokenize(insert_bytes)
n_tokens = len(tokens)
self.n_to_end_tokens = self.n_to_start_tokens + n_tokens
+ self.to_last_end_bytes = offset["to"] + len(insert_bytes)
yield (
Insert(
self.n_from_start_tokens,
@@ -162,12 +172,15 @@ class DiffToOperationMap:
)
# We have now used more of the "to" tokens.
self.n_to_start_tokens += n_tokens
- self.to_last_end_bytes = offset["to"] + len(insert_bytes)
- def doDelete(self, delete_bytes, offset):
+ self.to_byte_token_index_map[offset['to']] = self.n_to_end_tokens
+
+ def doDelete(self, delete_text, offset):
+ delete_bytes = delete_text.encode()
tokens = self.tokenize(delete_bytes)
n_tokens = len(tokens)
self.n_from_end_tokens = self.n_from_start_tokens + n_tokens
+ self.from_last_end_bytes = offset["from"] + len(delete_bytes)
yield (
Delete(
self.n_from_start_tokens,
@@ -180,7 +193,10 @@ class DiffToOperationMap:
)
# We have now used more of the "from" tokens.
self.n_from_start_tokens += n_tokens
- self.from_last_end_bytes = offset["from"] + len(delete_bytes)
+
+ self.from_byte_token_index_map[
+ offset['from']
+ ] = self.n_from_end_tokens
def doHighlightRange(self, highlight_bytes, highlightRanges, offset):
# The text field is an overlapping mix of both the from and to,
@@ -196,14 +212,11 @@ class DiffToOperationMap:
highlight_start = highlightRange["start"]
# equal bytes in between highlights
if highlight_start > highlight_end:
-
- equal_bytes = highlight_bytes[
- highlight_end : highlight_start
- ]
+ equal_bytes = highlight_bytes[highlight_end:highlight_start]
n_equal_bytes = len(equal_bytes)
yield from self.doEqual(equal_bytes, highlight_offset)
- highlight_offset['from'] += n_equal_bytes
- highlight_offset['to'] += n_equal_bytes
+ highlight_offset["from"] += n_equal_bytes
+ highlight_offset["to"] += n_equal_bytes
# handle highlighted insert / delete
highlight_end = highlight_start + highlightRange["length"]
@@ -211,10 +224,10 @@ class DiffToOperationMap:
n_range_bytes = len(range_bytes)
if highlightRange["type"] == 0:
yield from self.doInsert(range_bytes, highlight_offset)
- highlight_offset['to'] += n_range_bytes
+ highlight_offset["to"] += n_range_bytes
elif highlightRange["type"] == 1:
yield from self.doDelete(range_bytes, highlight_offset)
- highlight_offset['from'] += n_range_bytes
+ highlight_offset["from"] += n_range_bytes
else:
raise Exception(entry)
@@ -223,6 +236,39 @@ class DiffToOperationMap:
range_bytes = highlight_bytes[highlight_end:]
yield from self.doEqual(range_bytes, highlight_offset)
+ def doParMove(self, to_diff):
+
+ # the tricky part here is to put the tokens in the right spots.
+ from_diff = self.par_move_dict[to_diff["moveInfo"]["linkId"]]
+
+ from_byte_start = from_diff["offset"]["from"]
+ # as of python 3.7 dictionaries are in insertion order. So
+ # we can just find the first key that's greater
+
+ # since the paragraph is removed in the "from" version, the index it is removed from
+ # will be *after* the
+ if from_byte_start >= self.from_last_end_bytes: # if the from paragraph is at the end
+ from_token_start = next(reversed(self.from_byte_token_index_map.values()))
+ else:
+ key = find_greatest_le_key(from_byte_start, self.from_byte_token_index_map)
+ from_token_start = self.from_byte_token_index_map[key]
+
+ # get the to token index
+ to_byte_start = to_diff["offset"]["to"]
+ if to_byte_start >= self.to_last_end_bytes:
+ to_token_start = next(reversed(self.to_byte_token_index_map.values()))
+ else:
+ key = find_greatest_le_key(to_byte_start, self.to_byte_token_index_map)
+ to_token_start = self.to_byte_token_index_map[key]
+
+ # now we set the state and apply the highlights
+ self.n_from_start_tokens = self.n_from_end_tokens = from_token_start
+ self.n_to_start_tokens = self.n_to_end_tokens = to_token_start
+ offset = {"from": from_byte_start, "to": to_byte_start}
+ yield from self.doHighlightRange(
+ to_diff["text"], to_diff["highlightRanges"], offset
+ )
+
class WikiDiffMatcher:
def __init__(
@@ -249,15 +295,23 @@ class WikiDiffMatcher:
# The diff has already been computed, but we need to incrementally
# retrieve it to recreate the behavior DiffState expects.
diff = next(self.diffs)
- diffToOperationsMapper = DiffToOperationMap(self.previous_text, text, diff, self.tokenizer)
+ diffToOperationsMapper = DiffToOperationMap(
+ diff, self.tokenizer
+ )
(
operations,
aseq,
bseq,
- ) = list(
- zip(*diffToOperationsMapper.to_operations())
- )
+ ) = list(zip(*diffToOperationsMapper.to_operations()))
+ aseq = list(aseq)
+
+ # aseq can be out of order, we need to sort it by a1 index.
+ indices = list(range(len(aseq)))
+ indices.sort(key = lambda i: operations[i].a1)
+ aseq = [aseq[i] for i in indices]
+
+ # bseq cannot be out of order since diffs are resolved in the order of aseq.
self.last_tokens = list(chain.from_iterable(aseq))
tokens = list(chain.from_iterable(bseq))
self.previous_text = text