This page describes some implementation and design choices for annotations as well as proposed initial MVP candidates, building on the description of a general annotation service.
The core annotation implementation consists of the following two deliverables:
The data structure contains extension points to support alternative anchor mechanisms and alternative migration mechanisms, and of course the actual content associated with the annotation is generic as well, but these aren't included in the initial core implementation.
We will assume that the migration API is accessible both within mediawiki-core as a direct PHP function call as well as via a network API like the action API.
Certain use cases for annotations require some additional features not included in the core features set.
The core feature set does not include any user interface support for creating, viewing, or editing annotations. This UX can be pre-existing, new, or generic.
For pre-existing UX, we are retrofitting the annotation service into an existing feature, and so are expecting to re-use the pre-existing create/edit/view mechanisms. For other use cases, we expect to have support from a feature team who will build new UX. Finally, there may be use for a generic view/edit UX for annotations built into VE which could be used/reused by a number of simple annotation types.
The core feature set does not include storage of annotations, although it does define a JSON serialization format. The first distinction to be made is whether annotations are considered per-user or shared.
Some applications propose to store annotations external to core. For example, per-user annotations can be stored in browser local storage and the network API used to explicitly migrate when needed. If shared annotations are needed, then they can be stored in a database managed by a mediawiki extension. In both cases, local caching or update can be used to avoid repeated migrations.
An alternative is to provide storage of shared annotations in mediawiki-core as a generic service; this is generally not appropriate for per-user annotations. For example, annotations can be a first class content type in the Multi-Content Revisions (MCR) system and stored alongside revision data for an article. A generic API to retrieve "all current annotations for a Title" or "all current annotations for a Title, migrated to the current revision" can be provided, and/or a cached storage mechanism to reduce migration costs.[1]
Some use cases may wish to work with annotations on unsaved content, for example in-progress edits. We can extend the core API to allow anchoring annotations to a stashed revision. As long as the wikitext corresponding to a particular stashed revision can be provided, this presents no particular issue to the migration mechanism. We might also want to support the Draft namespace or userspace as alternative anchors. These generally would extend the revision history with one additional "draft" revision on top, and allow migrating annotations to that draft revision.[2]
Client-side features most naturally work with an HTML DOM representation of the page, and so some use cases may wish to use DOM-anchored annotations.
One way to provide this feature is by providing a DOM-to-wikitext mapping service. In this implementation, annotations are still natively anchored in wikitext, but we provide a way to easily obtain appropriate wikitext indices for a given DOM range. There two variants of this. For read view HTML, you may want to provide a client-side JavaScript API that when given a DOM node in window.document will return appropriate wikitext indices, for example by providing an network API endpoint to provide a map from DOM node id attributes to wikitext indices. For Visual Editor, you can annotate Visual Editor's internal data model with wikitext indices at load time.
One potential complication is that some visible content may not have an obvious mapping to wikitext, for example it may be generated by a template or Scribunto module. The DOM-to-wikitext mapping service would presumably make these nodes un-selectable or expand the annotation range as needed to contain the content.
An alternative implementation is to provide a native DOM anchor type for annotations. For HTML contents that are deterministic and reproducible, XPath or ID-based selectors can be used. The main issue is that MediaWiki article HTML is not presently deterministic nor reproducible so this would require persistent storage of rendered articles or an infrastructural investment in deterministic parsing. This would be a major feature dependency.
A final alternative is to provide plaintext anchors for annotations. This is part of the W3C annotation standard and can be extended in an obvious way to allow fuzzy text matches as well. By providing anchor text, the annotation can potentially be resolved either against the wikitext, read view HTML, or Visual Editor's data model. The primary drawback is that the anchor is unreliable, but this may still be a reasonable option for non-critical annotations like user highlights. In addition to the "heavyweight" text diff migration in the core annotation functionality, often you can attempt to directly match the plaintext anchor against the latest revision for a lower cost migration.
Not included in the core functionality is any API for querying annotations on a given title. There is a W3C spec for annotation publication and discoverability which could be implemented for standards-compliance and interoperability.[3] This would be most natural to implement as a generic service alongside storage of shared annotations in mediawiki-core, but could be implemented even for externally stored annotations.
Extensible UX for annotations in Visual Editor would allow easier development of future annotation types, but is not strictly necessary for any initial use cases.
There have been a number of use cases proposed as the initial MVP for the annotation feature. In this section, I will discuss which of the additional features described above are required for each potential use case; this determines the cost of the initial MVP implementation.
The translate extension uses pre-existing UX for shared annotations. An MVP could store the translations externally (in a database managed by the Translate extension) but would benefit from storage of shared annotations in core if that were available. It does not require any alternative anchoring mechanisms.
Some generic UX would probably be needed to edit translation regions.
There are two related use cases from the editing team.
The first is to record which edit suggestions were made for a specific user, and to suppress those that had already been dismissed by that user. This is pre-existing UX from the editing team, using external storage of per-user annotations in browser local storage. They would like to anchor to a stashed revision corresponding to the edit-in-progress, but can probably accommodate anchoring the annotation only once the edit has been saved. The would need a DOM-to-wikitext mapping service for Visual Editor.
A related feature is to record edit suggestions as part of the history of the page/recent changes, so that other editors can potentially follow up on suggestions that were made but not acted upon during this edit session, or so that we can suppress showing a suggestion that has been dismissed multiple times by other editors. This is pre-existing or new UX built by the editing team, using external storage of shared annotations; since these suggestions are considered fairly ephemeral they wouldn't be appropriate for core storage in MCR. The saved annotation can anchor to a saved revision, but they would probably require the DOM-to-wikitext mapping service for Visual Editor and potentially the ability to anchor to a stashed revision during the initial creation of the suggestion.
The editing team is likely to build a version of this feature ahead of the annotation work; the value add from the annotation services is a shared data model and the migration capability; currently they plan to wipe all suggestions when a new revision is saved.
This feature would support persistent reader highlights. For the purpose of this discussion we'll assume they are per-user and stored in browser local storage. This is new UX from the feature team, and would be stored externally (not appropriate for core MCR storage). They would likely be per-user, but one could imagine a shared variant for "most frequently highlighted region" or something similar. The require the DOM-to-wikitext mapping service for Read View HTML, although they could potentially use plain text anchors.
The value add from the annotation service is primarily the migration capability.
The least expensive MVP would probably be support for reader highlights using external storage (the responsibility of the feature team) and a simple plain text anchor system. This would let us build out the data model and migration UX while deferring some of the more difficult interfaces. Assuming that feature was successful, a next step could switch to wikitext anchoring using the DOM-to-wikitext mapping for Read View HTML, which would improve the reliability of anchoring and migration.
Using the Translate extension as an MVP would solve a long-standing pain point for multilingual content. Translation regions are already represented as wikitext regions, so this would also allow us to initially defer DOM-to-wikitext mapping. We could implement a compatibility mode mapping annotations back to explicit <translate> markers in the wikitext to allow editing the annotation regions without requiring new Visual Editor integration. The follow up after the MVP would likely be a more-integrated annotation region editor, which would likely involve building some version of DOM-to-wikitext mapping, although it may be possible to build the region editor on top of the "source editing" mode of Visual Editor to further defer building that mapping service.
The edit suggestions use cases are potentially the most complex MVP, as they involve anchoring annotations to a DOM which is being actively edited. We may be able to use a plain text anchor in the initial MVP to defer the anchoring issue,[4] and then extend this with a DOM-to-wikitext mapping service supporting stashed content in a follow-up.
My initial recommendation is to pursue the reader highlight MVP while aligning data models with the edit suggestions features so that they are able to adopt the annotation system once an appropriate DOM-to-wikitext mapping service is implemented in phase 2. If we are unable to partner with another team for UX and other support, the Translate extension is an alternative use case which the Content Transform Team could potentially implement in a silo on a longer time frame, since it is a back-end retrofit for existing UX and can initially reuse existing Visual Editor support for the <translate> tag.
<link rel="http://www.w3.org/ns/oa#annotationService" href="..."> in the document <head> which point to a server URL which can be used to list all annotations of the given page. More details in the W3C spec.