Instant Diffs/API
Tato stránka poskytuje dokumentaci pro vývojáře a pokročilé uživatele modulu Instant Diffs, který zlepšuje uživatelský zážitek při prohlížení rozdílů a revizí napříč projekty MediaWiki. Zde naleznete informace o API, vlastních akcích, konfiguraci odkazů a možnostech integrace.
Stav aplikace
Jednotka Instant Diffs, dostupná jako argument window.instantDiffs nebo id v háčku instantDiffs.ready, zpřístupňuje následující vlastnosti:
Úvodní příznaky
| Property | Type | Description |
|---|---|---|
isRunning
|
boolean
|
Set to true when the script starts initializing. Used to prevent multiple concurrent instances.
|
isFirstRun
|
boolean
|
Set to true during the initial content processing run, and reset to false on subsequent runs.
|
isRunCompleted
|
boolean
|
Set to true after the initial content processing run has finished.
|
isReady
|
boolean
|
Set to true after the script has fully initialized and is ready to process content.
|
isReplaced
|
boolean
|
Set to true if a standalone script instance was replaced by a newer non-standalone instance.
|
isUnloading
|
boolean
|
Set to true when the tab is being unloaded. Script activity is paused while this flag is set.
|
isPageAdjustmentsApplied
|
boolean
|
Set to true after page-specific adjustments have been applied for the current MediaWiki page type.
|
Modules and data
| Property | Type | Description |
|---|---|---|
config
|
Object
|
The active configuration object, containing selectors, labels, page lists, and other settings. |
local
|
Object
|
Local runtime variables, including assembled link selectors, special page aliases, server names, and observer instances. |
timers
|
Object
|
Script timer loggers used for performance tracking. |
i18n
|
Object
|
Localized strings map, keyed by language code. |
utils
|
Object
|
Utility functions used internally by Instant Diffs. |
view
|
Object
|
The active view instance managing the dialog window.
|
settings
|
Object
|
The active settings instance managing user preferences.
|
modules
|
Object
|
Exported classes and instances available for advanced integration. See Advanced integration. |
Hooks
Instant Diffs fires the following mw.hook events that scripts and gadgets can listen to. All hook names are prefixed with instantDiffs.
| Hook | Argument | Description |
|---|---|---|
instantDiffs.ready
|
id — the Instant Diffs singleton
|
Fires once after Instant Diffs has fully initialized. The safest entry point for accessing id.modules and registering integrations. Only fires if the gadget is enabled by the user.
|
instantDiffs.process
|
$context — a jQuery context
|
Fires to trigger link processing within a given container. Can be fired externally to process newly added content, or listened to for observing when processing is triggered. See Simple integration. |
instantDiffs.processed
|
links — an array of Link instances
|
Fires after each processing cycle completes, passing all successfully processed Link instances in the current batch.
|
instantDiffs.link.renderSuccess
|
link — a Link instance
|
Fires after a link is successfully rendered. Useful for post-processing individual links after they appear in the page. |
instantDiffs.link.renderError
|
link — a Link instance
|
Fires after a link fails to render due to an API error or invalid data. |
instantDiffs.navigation.complete
|
navigation — a Navigation instance
|
Fires each time the navigation bar is rendered in the dialog. The primary hook for registering custom actions. See Custom actions. |
instantDiffs.page.ready
|
page — a Page instance
|
Fires when the page content and navigation are rendered and hooks are about to fire. Fires before wikipage.content and wikipage.diff.
|
instantDiffs.page.complete
|
page — a Page instance
|
Fires after all page hooks have fired, including wikipage.content and wikipage.diff.
|
instantDiffs.page.renderSuccess
|
page — a Page instance
|
Fires after the page content is successfully rendered. |
instantDiffs.page.renderError
|
page — a Page instance
|
Fires after the page fails to render due to a request error. |
instantDiffs.page.renderComplete
|
page — a Page instance
|
Fires after rendering completes regardless of success or failure, after instantDiffs.page.renderSuccess or instantDiffs.page.renderError.
|
instantDiffs.page.beforeDetach
|
page — a Page instance
|
Fires before the page is detached from the DOM, for example when the dialog is closed or a new page is loaded in the same dialog. |
instantDiffs.page.detach
|
page — a Page instance
|
Fires after the page is detached from the DOM. |
Link integration
This section is intended for developers who want to integrate Instant Diffs link actions into their own scripts or gadgets. There are two levels of integration: simple integration using data attributes and mw.hook process hooks, and advanced integration by creating Link class instances directly. Both approaches support the same set of link options.
Simple integration
The simplest way to integrate Instant Diffs is by adding data attributes directly to your link elements. Instant Diffs will automatically detect and process them on the next wikipage.content or instantDiffs.process hook call.
Use data-instantdiffs-link to set the link behavior:
<a href="https://en.wikipedia.org/w/index.php?diff=1&oldid=2" data-instantdiffs-link="basic">diff</a>
Use data-instantdiffs-options to pass a JSON object with additional link options:
<a href="https://en.wikipedia.org/w/index.php?diff=42&oldid=37"
data-instantdiffs-link="basic"
data-instantdiffs-options='{"showLink": false}'>diff</a>
To trigger processing of links in a specific container, fire the instantDiffs.process hook with a jQuery context:
mw.hook( 'instantDiffs.process' ).fire( $( '.my-container' ) );
Mark container as line
You can mark any container element with the data-instantdiffs-line attribute to enable line highlighting when a link inside it is opened in the dialog. This is useful when rendering custom lists or tables that contain diff or revision links.
<ul>
<li data-instantdiffs-line>
<a href="https://en.wikipedia.org/w/index.php?diff=42&oldid=37" data-instantdiffs-link>diff</a>
</li>
</ul>
Marking a container as a line also changes the default link behavior to 'basic' for all links inside it.
<ul>
<li data-instantdiffs-line="all">
<a href="https://en.wikipedia.org/w/index.php?diff=42&oldid=37">diff</a>
</li>
</ul>
Setting data-instantdiffs-line to 'all' will automatically process all links inside the container, without requiring data-instantdiffs-link on each link.
Advanced integration
For more control, you can access the Link class directly via the instantDiffs.ready hook and create instances manually. This approach is safe to use in your own gadgets and scripts — the hook only fires if Instant Diffs is enabled by the user, so your code will not run for users who do not have the gadget enabled.
The Link class is available via the hook callback argument:
mw.hook( 'instantDiffs.ready' ).add( ( id ) => {
const { Link } = id.modules;
} );
Alternatively, it can be accessed via the global window.instantDiffs object if Instant Diffs is already initialized:
const { Link } = window.instantDiffs.modules;
To create a Link instance for a specific element:
mw.hook( 'instantDiffs.ready' ).add( ( id ) => {
const { Link } = id.modules;
const node = document.querySelector( 'a.my-diff-link' );
const link = new Link( node, {
behavior: 'basic',
showLink: false,
onLoad: ( link ) => {
console.log( 'Dialog loaded for:', link.getArticle().get( 'title' ) );
},
} );
} );
You can also use the static Link.findLinks method to process all diff and revision links within a given container, skipping any already processed by Instant Diffs. The method uses the same link selector ruleset that Instant Diffs uses internally to match supported diff and revision links across MediaWiki interface pages.
mw.hook( 'instantDiffs.ready' ).add( ( id ) => {
const { Link } = id.modules;
const $container = $( '.my-container' );
Link.findLinks( $container ).each( ( i, node ) => {
if ( Link.hasLink( node ) ) return;
new Link( node, { behavior: 'basic' } );
} );
} );
Open dialog programmatically
You can open the Instant Diffs dialog for any diff or revision without a link element, by creating a ViewButton instance directly and calling openDialog(), which returns a Promise that resolves when the dialog has opened. This is useful when you want to trigger the dialog from your own UI elements or scripts.
mw.hook( 'instantDiffs.ready' ).add( ( id ) => {
const { ViewButton } = id.modules;
const button = new ViewButton( {
article: {
oldid: 42,
diff: 'prev',
},
} );
button.openDialog();
} );
You can also open the dialog for an existing link element by creating a Link instance and calling openDialog() directly, which also returns a Promise that resolves when the dialog has opened:
mw.hook( 'instantDiffs.ready' ).add( ( id ) => {
const { Link } = id.modules;
const node = document.querySelector( 'a.my-diff-link' );
const link = Link.getLink( node ) || new Link( node );
link.openDialog();
} );
The article option of ViewButton accepts key-value pairs passed to the Article constructor. The following values are commonly used:
| Option | Type | Description |
|---|---|---|
diff
|
number|string
|
The revision ID of the newer revision in a diff. Accepts a numeric ID or a direction string: 'prev', 'next', or 'cur'.
|
oldid
|
number
|
The revision ID of the older revision in a diff, or the revision ID when viewing a single revision. |
direction
|
string
|
Fallback direction when oldid is empty. Accepted values: 'prev', 'next', 'cur'.
|
curid
|
number
|
The page ID, used to open the latest revision of a page. |
title
|
string
|
The page title, used together with diff or oldid to identify the page.
|
hostname
|
string
|
The hostname of a foreign wiki, used to open diffs from other Wikimedia projects. For example: 'en.wikipedia.org'.
|
page1
|
string
|
First page title for a Special:ComparePages diff. Requires title to be set to 'Special:ComparePages'.
|
page2
|
string
|
Second page title for a Special:ComparePages diff. Requires title to be set to 'Special:ComparePages'.
|
rev1
|
number
|
First revision ID for a Special:ComparePages diff. Requires title to be set to 'Special:ComparePages'.
|
rev2
|
number
|
Second revision ID for a Special:ComparePages diff. Requires title to be set to 'Special:ComparePages'.
|
hash
|
string
|
A URL fragment to scroll to after the dialog opens. |
section
|
string
|
A section name appended to the page title link. |
Link options
The following options can be passed to the Link constructor or via the data-instantdiffs-options attribute.
| Option | Type | Default | Description |
|---|---|---|---|
behavior
|
string
|
'basic'
|
Link behavior type. Accepted values:
|
insertMethod
|
string
|
'insertAfter'
|
Where to embed the actions panel relative to the link. Accepted values:
|
showLink
|
boolean
|
false[a]
|
Whether to render the main action button. When false, the click handler is attached directly to the existing link element instead.
|
showPageLink
|
boolean
|
true[a]
|
Whether to render the page navigation action button. Only applicable for 'request' behavior.
|
showAltTitle
|
boolean
|
false
|
Whether to display the original link title instead of the title generated by Instant Diffs. |
useAltKey
|
boolean
|
true
|
Whether Alt+Click opens the link normally in the current tab when the click handler is attached directly to the link. |
setClasses
|
boolean|string
|
true
|
Whether to add Instant Diffs CSS classes to the existing link element. Accepted values:
|
onRequest
|
Function
|
— | Callback fired before the dialog loads. Receives the Link instance as its argument.
|
onLoad
|
Function
|
— | Callback fired after the dialog content loads. Receives the Link instance as its argument.
|
onOpen
|
Function
|
— | Callback fired after the dialog opens. Receives the Link instance as its argument.
|
onClose
|
Function
|
— | Callback fired after the dialog closes. Receives the Link instance as its argument.
|
See also
Link.json GitHubViewButton.json GitHubArticle.json GitHub
Custom actions
This section describes how to add custom actions to the Instant Diffs Actions menu using the instantDiffs.navigation.complete hook. The hook fires each time the navigation bar is rendered, passing a Navigation instance as its argument. Custom actions are registered via navigation.addCustomAction() and appear in the Actions menu of the dialog.
Simple link
The simplest way to add a custom action is by registering a link with an href. No click handler is needed — Instant Diffs will render the action as a direct link in the Actions menu.
/**
* Add a custom "What links here" action to Instant Diffs navigation.
*/
mw.hook( 'instantDiffs.navigation.complete' ).add( ( navigation ) => {
if ( !navigation ) return;
const title = navigation.getArticle().get( 'title' );
if ( !title ) return;
navigation.addCustomAction( {
name: 'whatLinksHere',
label: 'What links here',
icon: 'linkExternal',
href: mw.util.getUrl( `Special:WhatLinksHere/${ title }` ),
} );
} );
Call simple handler
This example shows how to register an action with a synchronous click handler. The handler receives the action button instance as widget, performs an operation, and returns focus to the button when done.
/**
* Add a custom "Copy info link" action to Instant Diffs navigation.
* Copies a link to the page information to the clipboard.
*/
mw.hook( 'instantDiffs.navigation.complete' ).add( ( navigation ) => {
if ( !navigation ) return;
const { utils } = instantDiffs;
const { Article } = instantDiffs.modules;
/**
* Handle the "Copy info link" action click
*/
const handler = ( widget ) => {
// Get article data
const article = widget.getArticle();
const title = article.get( 'title' );
if ( !title ) return;
// Build absolute URL to page information
const url = mw.util.getUrl( title, { action: 'info' } );
const href = Article.utils.getHrefAbsolute( article, url );
// Copy link to clipboard
utils.clipboardWriteLink( href );
// Return focus to the action button
navigation.focusAction( widget );
};
// Register the custom action
navigation.addCustomAction( {
name: 'copyInfoLink',
label: 'Copy info link',
icon: 'copy',
handler: handler,
} );
} );
Call advanced handler
This example demonstrates a full asynchronous integration where the handler receives the action button instance as widget, shows a loading state, makes an API request, handles errors, and dynamically updates the button after a successful response.
/**
* Add a custom "Examine change" action to Instant Diffs navigation.
* Searches for abuse log entries near the current revision timestamp.
*/
mw.hook( 'instantDiffs.navigation.complete' ).add( ( navigation ) => {
if ( !navigation ) return;
const { Api, Article } = instantDiffs.modules;
/**
* Handle the "Examine change" action click
*/
const handler = ( widget ) => {
// Get article data
const article = widget.getArticle();
const title = article.get( 'title' );
const timestamp = article.get( 'timestamp' );
if ( !title || !timestamp ) {
onRequestError( widget, 'Missing title or timestamp.' );
return;
}
// Calculate timestamp range (±30 seconds from revision time)
const revisionDate = new Date( timestamp );
const startDate = new Date( revisionDate.getTime() - 30000 ); // 30 seconds before
const endDate = new Date( revisionDate.getTime() + 30000 ); // 30 seconds after
// Show loading state
navigation.pendingAction( widget, true );
// Query abuse log for entries near this revision
const params = {
action: 'query',
list: 'abuselog',
afldir: 'newer',
afltitle: title,
afluser: article.get( 'user' ),
aflstart: startDate.toISOString(),
aflend: endDate.toISOString(),
afllimit: 1,
aflprop: 'ids',
format: 'json',
formatversion: 2,
uselang: mw.config.get( 'wgUserLanguage' ),
errorformat: 'html',
};
// Article argument is specified to support foreign wikis as well
Api.get( params, article )
.then( ( data ) => onRequestDone( widget, data ) )
.fail( ( error, data ) => onRequestError( widget, Api.getApi.getErrorMessage( data ) ) );
};
/**
* Handle a successful API response
*/
const onRequestDone = ( widget, data ) => {
// Clear loading state
navigation.pendingAction( widget, false );
// Extract first abuse log entry
const entry = data && data.query && data.query.abuselog && data.query.abuselog[ 0 ];
if ( !entry ) {
onRequestError( widget, 'No abuse log entries found for this revision.' );
return;
}
// Build URL to abuse filter examination page
const article = widget.getArticle();
const url = mw.util.getUrl( `Special:AbuseFilter/examine/log/${ entry.id }` );
const href = Article.utils.getHrefAbsolute( article, url );
// Update all instances of this action with the found URL
navigation.eachCustomActionWidget( widget, ( actionWidget ) => {
actionWidget
.setHref( href )
.setHandler(); // Remove handler since we now have a direct link
} );
// Navigate to the examination page
navigation.execAction( widget );
};
/**
* Handle API error or no results
*/
const onRequestError = ( widget, message ) => {
// Clear loading state
navigation.pendingAction( widget, false );
// Show error notification
mw.notify( message, {
type: 'error',
tag: widget.getOption( 'name' ),
} );
// Return focus to the action button
navigation.focusAction( widget );
};
// Load icon styles
mw.loader.load( [ 'oojs-ui.styles.icons-editing-citation' ] );
// Register the custom action
navigation.addCustomAction( {
name: 'examineAbuseFilter',
label: 'Examine change',
icon: 'journal',
handler: handler,
} );
} );
Action widget
Each action's handler function receives a MenuButton instance as its first argument, referred to as widget in the examples above. MenuButton extends OO.ui.ButtonWidget, so all standard OOUI button options and methods are available, including setHref(), setDisabled(), setLabel(), focus(), and others. In addition, MenuButton provides the following methods:
| Method | Description |
|---|---|
getArticle()
|
Returns the Article instance associated with the button, providing access to diff and revision metadata.
|
getOption( name )
|
Returns a configuration option by name. |
getOptions()
|
Returns all configuration options. |
setHandler( handler, useAltKey )
|
Sets a click handler on the button. Pass no arguments to remove the current handler. |
execHandler()
|
Programmatically triggers the button's click handler. |
setLink( linkOptions )
|
Creates a Link instance around the button element. Accepts the same options as described in Link options.
|
setPending( value )
|
Toggles a pending state on the button. |
The following methods of the Navigation instance are available for use in custom action handlers. These methods accept the original unprefixed action name — the custom- prefix is handled internally:
| Method | Description |
|---|---|
addCustomAction( options )
|
Registers a custom action in the Actions menu. See available options below. |
getCustomAction( widgetOrName )
|
Returns all registered instances of the specified custom action. Accepts a MenuButton instance or an unprefixed action name string.
|
getCustomActionWidget( widgetOrName )
|
Returns all widget instances of the specified custom action. Accepts a MenuButton instance or an unprefixed action name string.
|
eachCustomAction( widgetOrName, handler )
|
Iterates over all registered instances of the specified custom action and calls handler with each entry. Accepts a MenuButton instance or an unprefixed action name string.
|
eachCustomActionWidget( widgetOrName, handler )
|
Iterates over all widget instances of the specified custom action and calls handler with each widget. Accepts a MenuButton instance or an unprefixed action name string. Useful for updating all placements of an action after an async operation.
|
The following general Navigation methods are useful for managing button state and focus within handlers. When referencing a custom action by name, the full prefixed name must be used, e.g. custom-whatLinksHere:
| Method | Description |
|---|---|
focusAction( widgetOrName )
|
Hides the Actions menu and sets focus on the specified button. Accepts a MenuButton instance or a full action name string.
|
pendingAction( widgetOrName, value )
|
Sets the loading state of the specified button. Pass true to show and false to hide. Accepts a MenuButton instance or a full action name string.
|
execAction( widgetOrName )
|
Programmatically triggers a click on the specified button if it is not disabled. Accepts a MenuButton instance or a full action name string.
|
toggleActions( value )
|
Toggles the visibility of the Actions menu. Pass true to show and false to hide.
|
getArticle()
|
Returns the Article instance associated with the current diff or revision.
|
The following options can be passed to navigation.addCustomAction():
| Option | Type | Description |
|---|---|---|
name
|
string
|
A unique action identifier. The prefix custom- is automatically prepended to the name internally, so getCustomAction() and related methods should always be called with the original unprefixed name.
|
label
|
string
|
The action label displayed in the Actions menu. |
icon
|
string
|
An OOUI icon name to display on the button. |
href
|
string
|
A URL to navigate to when the action is clicked. When provided without a handler, the action renders as a direct link.
|
pending
|
boolean
|
Whether to set a pending state. |
pin
|
boolean
|
Whether to pin the action button outside the Actions menu. Overrides the user's pin setting for this action. |
handler
|
Function
|
A click handler function. Receives the MenuButton instance as its first argument.
|
useAltKey
|
boolean
|
Whether Alt+Click bypasses the handler and follows the href directly.
|
setLink
|
boolean
|
Whether to create a Link instance around the button element, enabling Instant Diffs dialog behavior on the button's href.
|
linkOptions
|
Object
|
Configuration options for the Link instance created when setLink is true. Accepts the same options as described in Link options.
|
See also
Navigation.json GitHubMenuButton.json GitHub- Global Search — see how Wikimedia users integrate the Custom Actions API across projects.