2024-05-24 12:31:30 +00:00
|
|
|
|
const controller = require( './controller.js' ),
|
2022-03-29 21:25:21 +00:00
|
|
|
|
url = new URL( location.href );
|
2019-12-10 21:46:22 +00:00
|
|
|
|
|
2019-10-10 20:17:24 +00:00
|
|
|
|
/**
|
2019-12-10 21:46:22 +00:00
|
|
|
|
* @class mw.dt
|
2019-10-10 20:17:24 +00:00
|
|
|
|
* @singleton
|
|
|
|
|
*/
|
2019-12-10 21:46:22 +00:00
|
|
|
|
mw.dt = {};
|
2019-10-10 20:17:24 +00:00
|
|
|
|
|
2022-02-22 23:10:43 +00:00
|
|
|
|
mw.dt.initState = {
|
|
|
|
|
firstLoad: true
|
|
|
|
|
};
|
2021-07-29 06:12:10 +00:00
|
|
|
|
|
2022-10-31 21:03:49 +00:00
|
|
|
|
// A/B test for logged out users:
|
|
|
|
|
if ( mw.user.isAnon() && mw.config.get( 'wgDiscussionToolsABTest' ) && mw.config.get( 'wgDiscussionToolsABTestBucket' ) ) {
|
2024-05-24 12:31:30 +00:00
|
|
|
|
const token = mw.cookie.get( 'DTABid', '', mw.user.generateRandomSessionId() );
|
2022-10-31 21:03:49 +00:00
|
|
|
|
mw.cookie.set( 'DTAB', mw.config.get( 'wgDiscussionToolsABTestBucket' ), { path: '/', expires: 90 * 86400, prefix: '' } );
|
|
|
|
|
mw.cookie.set( 'DTABid', token, { path: '/', expires: 90 * 86400, prefix: '' } );
|
|
|
|
|
}
|
2021-12-17 16:34:23 +00:00
|
|
|
|
|
2022-03-29 21:25:21 +00:00
|
|
|
|
if ( url.searchParams.get( 'dtrepliedto' ) ) {
|
2021-07-29 06:12:10 +00:00
|
|
|
|
// If we had to reload the page to highlight the new comment, extract that data from the URL and
|
|
|
|
|
// clean it up.
|
2022-03-29 21:25:21 +00:00
|
|
|
|
mw.dt.initState.repliedTo = url.searchParams.get( 'dtrepliedto' );
|
2023-08-24 15:36:44 +00:00
|
|
|
|
mw.dt.initState.tempUserCreated = url.searchParams.has( 'dttempusercreated' );
|
2023-10-30 08:43:46 +00:00
|
|
|
|
url.searchParams.delete( 'dtrepliedto' );
|
|
|
|
|
url.searchParams.delete( 'dttempusercreated' );
|
|
|
|
|
window.history.replaceState( {}, '', url );
|
2021-07-29 06:12:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-07-22 16:02:56 +00:00
|
|
|
|
/**
|
|
|
|
|
* Hook handler for `mw.hook( 'wikipage.content' )`.
|
|
|
|
|
*
|
|
|
|
|
* @param {jQuery} $container
|
|
|
|
|
*/
|
2020-06-24 20:27:53 +00:00
|
|
|
|
mw.dt.init = function ( $container ) {
|
2022-07-22 16:02:56 +00:00
|
|
|
|
function reallyInit( $node ) {
|
|
|
|
|
controller.init( $node, mw.dt.initState );
|
|
|
|
|
mw.dt.initState = {};
|
2022-12-08 16:15:02 +00:00
|
|
|
|
|
|
|
|
|
// TODO: This functionality could be provided by MediaWiki (T183720).
|
|
|
|
|
$( document.documentElement ).addClass( 'ext-discussiontools-init-ready' );
|
2022-07-22 16:02:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Only (re)initialize if the hook is being fired on the page content – not on e.g. a single image
|
|
|
|
|
// in a gallery slideshow, or a preview in our own reply tool
|
2020-06-24 20:27:53 +00:00
|
|
|
|
if ( $container.is( '#mw-content-text' ) || $container.find( '#mw-content-text' ).length ) {
|
|
|
|
|
// eslint-disable-next-line no-jquery/no-global-selector
|
2022-07-22 16:02:56 +00:00
|
|
|
|
reallyInit( $( '#mw-content-text' ) );
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Otherwise, if node is detached, wait to see what it actually is
|
|
|
|
|
if ( !$container.closest( 'html' ).length ) {
|
2024-04-18 18:37:58 +00:00
|
|
|
|
setTimeout( () => {
|
2022-07-22 16:02:56 +00:00
|
|
|
|
if ( $container.closest( 'html' ).length ) {
|
|
|
|
|
mw.dt.init( $container );
|
|
|
|
|
}
|
|
|
|
|
} );
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If it's a full page live preview, (re)initialize to support highlighting comments (T309423)
|
|
|
|
|
// FIXME This really should not depend on implementation details of 2 different live previews
|
|
|
|
|
// FIXME VisualEditor (2017WTE) preview can't be supported, because it messes with `id` attributes
|
2024-05-24 12:20:50 +00:00
|
|
|
|
const livePreviewSelectors = '#wikiPreview, .ext-WikiEditor-realtimepreview-preview';
|
2022-10-10 21:12:09 +00:00
|
|
|
|
if ( $container.parent().is( livePreviewSelectors ) ) {
|
2022-07-22 16:02:56 +00:00
|
|
|
|
reallyInit( $container );
|
|
|
|
|
return;
|
2020-06-24 20:27:53 +00:00
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2022-03-29 21:25:21 +00:00
|
|
|
|
if ( url.searchParams.get( 'dtdebug' ) ) {
|
2019-10-24 14:38:31 +00:00
|
|
|
|
mw.loader.load( 'ext.discussionTools.debug' );
|
2021-03-24 18:41:39 +00:00
|
|
|
|
} else {
|
2020-06-24 20:27:53 +00:00
|
|
|
|
// Don't use an anonymous function, because ReplyWidget needs to be able to remove this handler
|
|
|
|
|
mw.hook( 'wikipage.content' ).add( mw.dt.init );
|
2019-10-24 14:38:31 +00:00
|
|
|
|
}
|
2020-02-25 02:10:27 +00:00
|
|
|
|
|
2023-02-04 14:30:14 +00:00
|
|
|
|
if ( mw.config.get( 'wgCanonicalSpecialPageName' ) === 'TopicSubscriptions' ) {
|
2024-05-24 12:31:30 +00:00
|
|
|
|
const topicSubscriptions = require( './topicsubscriptions.js' );
|
2023-02-04 14:30:14 +00:00
|
|
|
|
topicSubscriptions.initSpecialTopicSubscriptions();
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-28 18:53:28 +00:00
|
|
|
|
if ( mw.config.get( 'wgAction' ) === 'history' ) {
|
2024-05-24 12:31:30 +00:00
|
|
|
|
const topicSubscriptions = require( './topicsubscriptions.js' );
|
2023-08-28 18:53:28 +00:00
|
|
|
|
topicSubscriptions.initNewTopicsSubscription();
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-13 23:25:56 +00:00
|
|
|
|
// Clean up old localStorage entries that were erroneously set with no expiration (T339042).
|
|
|
|
|
// We are no longer using these keys since T329299.
|
|
|
|
|
// TODO: Remove this code after a few weeks.
|
2024-04-18 18:37:58 +00:00
|
|
|
|
mw.requestIdleCallback( () => {
|
2023-06-13 23:25:56 +00:00
|
|
|
|
try {
|
2024-05-24 12:20:50 +00:00
|
|
|
|
for ( const key in localStorage ) {
|
2023-06-13 23:25:56 +00:00
|
|
|
|
if ( key.startsWith( 'reply/' ) ) {
|
|
|
|
|
localStorage.removeItem( key );
|
|
|
|
|
localStorage.removeItem( '_EXPIRY_' + key );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch ( err ) {}
|
|
|
|
|
} );
|
|
|
|
|
|
2020-02-25 02:10:27 +00:00
|
|
|
|
module.exports = {
|
2020-10-18 11:52:02 +00:00
|
|
|
|
controller: controller,
|
2020-07-20 21:15:03 +00:00
|
|
|
|
Parser: require( './Parser.js' ),
|
Change CommentParser into a service
Goal:
-----
To have a method like CommentParser::parse(), which just takes a node
to parse and a title and returns plain data, so that we don't need to
keep track of the config to construct a CommentParser object (the
required config like content language is provided by services) and
we don't need to keep that object around after parsing.
Changes:
--------
CommentParser.php:
* …is now a service. Constructor only takes services as arguments.
The node and title are passed to a new parse() method.
* parse() should return plain data, but I split this part to a separate
patch for ease of review: I49bfe019aa460651447fd383f73eafa9d7180a92.
* CommentParser still cheats and accesses global state in a few places,
e.g. calling Title::makeTitleSafe or CommentUtils::getTitleFromUrl,
so we can't turn its tests into true unit tests. This work is left
for future commits.
LanguageData.php:
* …is now a service, instead of a static class.
Parser.js:
* …is not a real service, but it's changed to behave in a similar way.
Constructor takes only the required config as argument,
and node and title are instead passed to a new parse() method.
CommentParserTest.php:
parser.test.js:
* Can be simplified, now that we don't need a useless node and title
to test internal methods that don't use them.
testUtils.js:
* Can be simplified, now that we don't need to override internal
ResourceLoader stuff just to change the parser config.
Change-Id: Iadb7757debe000025e52770ca51ebcf24ca8ee66
2022-02-19 02:43:21 +00:00
|
|
|
|
parserData: require( './parser/data.json' ),
|
2020-02-25 02:10:27 +00:00
|
|
|
|
modifier: require( './modifier.js' ),
|
2020-07-20 14:13:59 +00:00
|
|
|
|
ThreadItem: require( './ThreadItem.js' ),
|
|
|
|
|
HeadingItem: require( './HeadingItem.js' ),
|
|
|
|
|
CommentItem: require( './CommentItem.js' ),
|
2020-03-08 14:32:38 +00:00
|
|
|
|
utils: require( './utils.js' ),
|
2023-03-18 02:29:27 +00:00
|
|
|
|
config: require( './config.json' )
|
2020-02-25 02:10:27 +00:00
|
|
|
|
};
|