Jump to content

Specs/HTML/2.4.0

From mediawiki.org

This page defines a MediaWiki-specific DOM based on HTML5 and RDFa. The semantics of MediaWiki-specific functionality are encoded using RDFa.

Changes since Specs/HTML/2.3.0

[edit]
  • T261181: Add DOM-range annotation support.
  • T292657: mw-file-description added to media links to the file description page, which is the default
  • T108380: Set title for tooltips on media if caption isn't visible

Preliminaries

[edit]

RDFa structures

[edit]

Global prefix mappings:

  • prefix="mw: http://mediawiki.org/rdf/ dc: http://purl.org/dc/terms/"
  • Convention: Capital for types, lowercase for attributes.
  • Generally use the prefix instead of vocab definitions to avoid clashes (and allow mixing) with user-supplied RDFa. User-supplied RDFa with the mw prefix is moved to a non-clashing prefix in Parsoid.

Versioning

[edit]

An integer version number is set in the head section of the returned HTML document. This version is incremented whenever this DOM spec or any other important aspect of the Parsoid HTML output changes. See task T54937 for details.

<meta property="mw:htmlVersion" content="2.4.0">

For backward-compatibility reasons, this information is also available in a meta tag with the mw:html:version property, but this will eventually be deprecated.

ID attributes on all elements

[edit]

In pagebundles, we assign ID attributes to all elements, and use this to associate external metadata with those elements: Element_IDs. So far, we've moved data-parsoid (private, so should not matter to users) and will likely also move data-mw (public) from the DOM into JSON objects keyed on the ID.

Expectations of editing clients

[edit]

This section only applies to clients that edit HTML and expect to convert that HTML to wikitext without introducing unrelated diffs in that wikitext.

FIXME: This section probably needs some updates: (1) Subbu would like to rename mw:Placeholder to mw:Uneditable. (2) Probably need to refine the "DOM subtrees marked up with...they don't understand" section to include (or explicitly exclude) unknown annotations.

A typeof="mw:Placeholder" protects DOM structures from any editing. Clients are expected to preserve / protect subtrees marked as such. Clients are also expected to preserve any DOM subtrees marked up with typeof, rel, property in the http://mediawiki.org/rdf/ namespace they don't understand. This decouples clients from Parsoid development, and lets them concentrate on editing constructs whose special semantics they understand without having to implement all possible content elements.

FIXME; see https://phabricator.wikimedia.org/T303298#7761772

Exceptions

[edit]

Captions contained within media can be modified, for example a figcaption within a figure[typeof="mw:Image/Thumb"]. An exception to this exception would be when the media is itself generated by a transclusion, so a figure which also has typeof="mw:Transclusions" or an about attribute. See template markup.

Modules tags available in ‎<head>

[edit]

Three meta tags are inserted, when required, to the ‎<head> of the page, to communicate the list of style modules, general modules, and Javascipt configuration variables used on the page. These are, respectively, the properties mw:styleModules , mw:generalModules and mw:jsConfigVars . Clients can use information from these meta tags to construct appropriate ResourceLoader URLs to fetch the modules.

Example:

<meta property="mw:generalModules" content="ext.graph.vega2|site"/>
<meta property="mw:styleModules" content="ext.graph.styles|ext.cite.styles"/>
<meta property="mw:jsConfigVars" content='{"wgGraphSpecs":{"61938741d3ae7fae72d62af573684bda5ccbeefc":{"legends":[],"scales":[{"type":"ordinal","name":"x","zero":false,"domain":{"data":"chart","field":"x"},"padding":0.2,"range":"width","nice":true},{"type":"linear","name":"y","domain":{"data":"chart","field":"y"},"zero":true,"range":"height","nice":true},{"domain":{"data":"chart","field":"series"},"type":"ordinal","name":"color","range":"category10"}],"version":2,"marks":[{"type":"rect","properties":{"hover":{"fill":{"value":"red"}},"update":{"fill":{"scale":"color","field":"series"}},"enter":{"y":{"scale":"y","field":"y"},"x":{"scale":"x","field":"x"},"y2":{"scale":"y","value":0},"width":{"scale":"x","offset":-1,"band":true},"fill":{"scale":"color","field":"series"}}},"from":{"data":"chart"}}],"height":100,"axes":[{"type":"x","title":"X","scale":"x","format":"d","properties":{"axis":{"strokeWidth":{"value":2},"stroke":{"value":"#54595d"}},"ticks":{"stroke":{"value":"#54595d"}},"title":{"fill":{"value":"#54595d"}},"labels":{"fill":{"value":"#54595d"}}},"grid":false},{"type":"y","title":"Y","scale":"y","format":"d","properties":{"title":{"fill":{"value":"#54595d"}},"grid":{"stroke":{"value":"#54595d"}},"ticks":{"stroke":{"value":"#54595d"}},"axis":{"strokeWidth":{"value":2},"stroke":{"value":"#54595d"}},"labels":{"fill":{"value":"#54595d"}}},"grid":false}],"data":[{"format":{"parse":{"y":"integer","x":"integer"},"type":"json"},"name":"chart","values":[{"y":10,"series":"y","x":1},{"y":12,"series":"y","x":2},{"y":6,"series":"y","x":3},{"y":14,"series":"y","x":4},{"y":2,"series":"y","x":5},{"y":10,"series":"y","x":6},{"y":7,"series":"y","x":7},{"y":9,"series":"y","x":8}]}],"width":600}}}'/>

Headings and Sections

[edit]

Status: Implemented. Tracking bug for sections; tracking bug for HTML5 IDs.

Given the illustrative wikitext:

...lead section contents...
== foo=bar ==
...section contents...
=== nested ===
...section contents...

The corresponding HTML DOM would be:

<section data-mw-section-id="0">
    ...lead section contents...
</section>
<section data-mw-section-id="1">
    <h2 id="foo=bar"><span id="foo.3Dbar" typeof="mw:FallbackId"></span>foo=bar</h2>
    ...section contents...
    <section data-mw-section-id="2">
        <h3 id="nested">nested</h3>
        ...section contents...
    </section>
</section>

Note the following properties:

  • There is always a <section> tag for the lead section, even if it is empty. It will be the first <section> tag in the document, and will have data-mw-section-id="0" unless it is uneditable.
  • The data-mw-section-id attribute will either be "0" or greater and correspond exactly to a PHP section ID (as used for action=edit for example), or will be "-1" (indicating an uneditable non-pseudo section) or "-2" (indicating a pseudo-section, which is also uneditable). Further discussion at Parsing/Notes/Section Wrapping.
  • There will be a ‎<h_> element as the first child of ‎<section> if it is not a pseudo-section.
  • The id attribute on the ‎<h_> element matches the 'html5' $wgFragmentMode. If needed, an empty ‎<span> with typeof="mw:FallbackId" will be added to hold an id attribute matching the 'legacy' $wgFragmentMode. The id attributes and the empty spans are ignored during serialization back to wikitext; only the contents of the heading element are significant.
  • The ‎<section> tags are properly nested.

Media

[edit]

Images

[edit]

Status: Implemented. Tracking bug.

In the examples below, the original size of the example image is 1941 × 220 pixels (these are the dimensions of the Foobar.jpg used in parserTests). The width and height in the DOM represent the actual scaled image height (not the bounding box dimensions specified in the wikitext). When image dimensions are modified or images with a non-default size are created, we will serialize to a square bounding box around the given width and/or height attributes. In the future: When using a (possibly scaled) version of the default thumbnail size, we will serialize using the scale or square option to enforce a square thumbnail bounding box (see task T64671).

The basic tree structure of all images, regardless of formatting options, alignment, or thumbnails, is:

<(figure|span) typeof="mw:Image"> <!-- or mw:Image/Thumb, mw:Image/Frame etc -->
 <a or span><img resource="..." src="..."></a or span>
 <figcaption (absent when inline)>...</figcaption>
</(figure|span)>

The outer <figure> element needs to become a <span> element when the figure is rendered inline, since otherwise the HTML5 parser will interrupt a surrounding block context. The inner <figcaption> element is rendered as a data-mw attribute in this case (since block content in an invisible caption would otherwise break parsing). The inner <a> element needs to become a span if there is no link; see task T46627. An "alt" attribute on the <img> is present if (and only if) the "alt=" options are present in the wikitext markup. If the "lang=" option is present, the <img> tag will have a "lang" attribute. The "resource" attribute on the <img> tag specifies the wiki title and namespace for the image (so it doesn't have to be reverse-engineered from the "src" attribute); it should point to a relative URL based on the image title. The "link=" option will be present in generated wikitext if and only if the "resource" attribute of <img> differs from the "href" attribute of the <a> tag.

The <img> tag will have data-file-width, data-file-height, and data-file-type attributes indicating the original (unscaled) size and type of the image. See task T64881.

Summary of semantic info for images
[edit]

Summary of semantic info that is present in the HTML generated for images:

wrapper node
‎<figure> for block images and ‎<span> for inline images
typeof attribute on the wrapper
mw:Image, mw:Image/Thumb, mw:Image/Frame, mw:Image/Frameless for different image uses
figure classes
mw-valign-{baseline,middle,sub,super,text-top,text-bottom,top,bottom} are only applied to inline media (rendered as ‎<span>): mw-halign-{left,right,center,none} and optionally mw-image-border and mw-default-size for full-size images and thumbs scaled to the wiki's and user's default thumb size
figcaption sub-element
The caption
resource attribute on image
link to image resource page. TODO: what to use for images from commons?
width and / or height on image
scaled image size. Only one of width or height is fine for easier client-side scaling without aspect ratio issues.
alt attribute on image
alt property
src attribute on image
thumb governed by explicit thumb option or implicit from image
href attribute on a around image
link target, normally just the image page- BUT a element can be absent if link is explicitly empty.
Specific image examples
[edit]

[[Image:Foobar.jpg]] (Note 1)

<span typeof="mw:Image" class="mw-default-size">
 <a href="./File:Foobar.jpg" class="mw-file-description">
  <img resource="./File:Foobar.jpg" src="http://upload.wikimedia.org/wikipedia/commons/3/3a/Foobar.jpg"
       width="1941" height="220">
 </a>
</span>

Without a link, we use the same basic DOM structure, but use a span instead of an a wrapper (task T46627):

[[Image:Foo.jpg|link=]] (Note 1)

<span typeof="mw:Image" class="mw-default-size">
 <span>
  <img resource="./File:Foobar.jpg" src="http://upload.wikimedia.org/wikipedia/commons/3/3a/Foobar.jpg"
       width="1941" height="220">
 </span>
</span>

Adding 'left' causes the image to be rendered in block context, so the outer ‎<span> becomes a ‎<figure>:

[[Image:Foo.jpg|left|<p>caption</p>]] (Note 5)

<figure typeof="mw:Image" class="mw-default-size">
 <a href="./File:Foo.jpg" class="mw-file-description" title="caption">
  <img resource="./File:Foo.jpg" src="http://upload.wikimedia.org/wikipedia/commons/3/3a/Foo.jpg"
       width="1941" height="220">
 </a>
 <figcaption><p>caption</p></figcaption>
</figure>

Scaling, vertical alignment of an inline image:

[[Image:Foobar.jpg|50px|middle]] (Note 1)

<span typeof="mw:Image" class="mw-valign-middle">
 <a href="./File:Foobar.jpg" class="mw-file-description">
  <img resource="./File:Foobar.jpg" src="http://upload.wikimedia.org/wikipedia/commons/3/3a/Foobar.jpg"
       width="50" height="6">
 </a>
</span>

Caption (containing disallowed markup) on an inline image:

[[Image:Foobar.jpg|500x10px|baseline|cap<div></div>tion]] (Note 5)

<span typeof="mw:Image" class="mw-valign-baseline"
    data-mw='{"caption":"cap<div></div>tion"}'>
 <a href="./File:Foobar.jpg" class="mw-file-description" title="caption">
  <img resource="./File:Foobar.jpg" src="http://upload.wikimedia.org/wikipedia/commons/3/3a/Foobar.jpg"
       width="89" height="10">
 </a>
</span>

[[Image:Foobar.jpg|50px|border|caption]]

<span typeof="mw:Image" class="mw-image-border"
    data-mw='{"caption":"caption"}'>
 <a href="./File:Foobar.jpg" class="mw-file-description" title="caption">
  <img resource="./File:Foobar.jpg" src="http://upload.wikimedia.org/wikipedia/commons/3/3a/Foobar.jpg"
       width="50" height="6">
 </a>
</span>

[[Image:Foobar.jpg|thumb|left|caption content]] (Note 3, Note 4)

<figure typeof="mw:Image/Thumb" 
  class="mw-halign-left mw-default-size">
   <a href="./File:Foobar.jpg" class="mw-file-description">
     <img src="http://upload.wikimedia.org/wikipedia/commons/3/3a/Foobar.jpg" width="180" height="20" 
        resource="./Image:Foobar.jpg" />
   </a>
   <figcaption>caption content</figcaption>
</figure>

[[Image:Foobar.jpg|thumb|50x50px|right|caption]] (Note 3)

<figure typeof="mw:Image/Thumb" class="mw-halign-right">
   <a href="./File:Foobar.jpg" class="mw-file-description">
     <img src="http://upload.wikimedia.org/wikipedia/commons/3/3a/Foobar.jpg" width="50" height="6" 
        resource="./Image:Foobar.jpg" />
   </a>
   <figcaption>caption</figcaption>
</figure>

[[Image:Foobar.jpg|frame|caption]]

<figure typeof="mw:Image/Frame" class="mw-default-size">
   <a href="./File:Foobar.jpg" class="mw-file-description">
     <img src="http://upload.wikimedia.org/wikipedia/commons/3/3a/Foobar.jpg" width="1941" height="220" 
        resource="./Image:Foo.jpg" />
   </a>
   <figcaption>caption</figcaption>
</figure>

[[Image:Foobar.jpg|500x50px|frame|left|caption]]

<figure typeof="mw:Image/Frame" class="mw-halign-left">
   <a href="./File:Foobar.jpg" class="mw-file-description">
     <img src="http://upload.wikimedia.org/wikipedia/commons/3/3a/Foobar.jpg" width="442" height="50" 
        resource="./Image:Foo.jpg" />
   </a>
   <figcaption>caption</figcaption>
</figure>

[[Image:Foobar.jpg|frameless|500x50px|caption]] (Note 5)

<figure typeof="mw:Image/Frameless">
   <a href="./File:Foobar.jpg" class="mw-file-description" title="caption">
     <img src="http://upload.wikimedia.org/wikipedia/commons/3/3a/Foobar.jpg" width="442" height="50" 
        resource="./Image:Foobar.jpg" />
   </a>
   <figcaption>caption</figcaption>
</figure>

Note that "border" can be combined with "frameless".

[[Image:Foobar.jpg|frameless|500x50px|border|caption]] (Note 5)

<figure typeof="mw:Image/Frameless" class="mw-image-border">
   <a href="./File:Foobar.jpg" class="mw-file-description" title="caption">
     <img src="http://upload.wikimedia.org/wikipedia/commons/3/3a/Foobar.jpg" width="442" height="50" 
        resource="./Image:Foobar.jpg" />
   </a>
   <figcaption>caption</figcaption>
</figure>

Manual thumbnails; note that the resource attribute points at the original image, the src attribute points to the manually-specific thumbnail image, and the data-mw attribute indicates the resource name of the thumbnail (so it doesn't have to be inferred from the img src):

[[File:Foobar.jpg|thumb=Thumb.png|Title]]

<figure class="mw-default-size" typeof="mw:Image/Thumb" data-mw='{"thumb":"Thumb.png"}'>
  <a href="File:Foobar.jpg" class="mw-file-description">
    <img src="//example.com/images/e/ea/Thumb.png" height="135" width="135"
         resource="./File:Foobar.jpg" />
  </a>
  <figcaption>Title</figcaption>
</figure>

Resizing images with the "scale" option:

[[File:Foobar.jpg|scale=0.5]]

<span typeof="mw:Image" class="mw-default-size" data-mw='{"scale":0.5}'>
 <a href="./File:Foobar.jpg" class="mw-file-description">
  <img resource="./File:Foobar.jpg" src="//upload.wikimedia.org/wikipedia/commons/3/3a/Foobar.jpg"
       width="971" height="110">
 </a>
</span>

Resizing thumbs with the "scale" option (this is a square 220x220px bounding box, see task T64671):
[[File:Foobar.jpg|thumb|scale=1]]

<figure class="mw-default-size" typeof="mw:Image/Thumb" data-mw='{"scale":1}'>
  <a href="File:Foobar.jpg" class="mw-file-description">
    <img src="//upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg"
         height="26" width="220" resource="./File:Foobar.jpg" />
  </a>
  <figcaption></figcaption>
</figure>

Resizing with the "upright" option (note that this is converted to an appropriate "scale" option, see above):
[[File:Foobar.jpg|thumb|upright=1]]

<figure class="mw-default-size" typeof="mw:Image/Thumb" data-mw='{"scale":1}'>
  <a href="File:Foobar.jpg" class="mw-file-description">
    <img src="//upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg"
         height="26" width="220" resource="./File:Foobar.jpg" />
  </a>
  <figcaption></figcaption>
</figure>

See enwiki help for all options, see mw for inline/float details

Note 1: The PHP parser adds a default alt attribute to the <img> tag, with content "Foobar.jpg". Client-side post-processing will need to add this for compatibility. (Parsoid does not add this attribute because it does not correspond to anything in the wikitext.)

Note 3: The PHP parser adds a <a href="./File:Foo.jpg" class="internal sprite details magnify" title="View photo details"></a> element inside the <figure>. Parsoid adds this with css.

Note 4: The default thumbnail width is a user-specified preference for the PHP parser. Parsoid uses a fixed 220px thumbnail width. The "mw-default-size" class indicates "no size given" and can be used to resize thumbs according to user preferences.

Note 5: In this example, the caption is not visible in PHP output, so the there should be a rule in the default stylesheet like (IE7+ and other modern browsers):

figure[typeof~="mw:Image/Frameless"] > figcaption,
figure[typeof~="mw:Image"] > figcaption { display: none }

Audio/Video

[edit]

Status: Implemented. See tracking bug for details.

The basic <figure> wrapper for audio and video media is identical to that for images, described in the section above, including provisions for inline players and captions. (Note that the PHP implementation does not properly render manual thumbnails or inline.)

The inner <video> element tracks the elements emitted by the video.js implementation in phab:T100106.

[[File:Folgers.ogv|thumb|50x50px|right|caption]]

<figure class="mw-halign-right" typeof="mw:Video/Thumb">
    <span>
        <video poster="//upload.wikimedia.org/wikipedia/commons/thumb/9/94/Folgers.ogv/50px--Folgers.ogv.jpg"
                controls=""
                preload="none"
                height="38"
                width="50"
                resource="./File:Folgers.ogv">
            <source src="https://upload.wikimedia.org/wikipedia/commons/9/94/Folgers.ogv"
                    type='video/ogg; codecs="theora, vorbis"'
                    data-file-width="352"
                    data-file-height="264"
                    data-title="Original Ogg file, 352 × 264 (637 kbps)"
                    data-shorttitle="Ogg source"/>
            <source src="https://upload.wikimedia.org/wikipedia/commons/transcoded/9/94/Folgers.ogv/Folgers.ogv.160p.webm"
                    type='video/webm; codecs="vp8, vorbis"'
                    data-width="214"
                    data-height="160"
                    data-title="Low bandwidth WebM (160P)"
                    data-shorttitle="WebM 160P"/>
            <track kind="subtitles"
                    type="text/x-srt"
                    src="https://commons.wikimedia.org/w/index.php?title=TimedText:Folgers.ogv.de.srt&amp;action=raw&amp;ctype=text%2Fx-srt"
                    srclang="de"
                    label="Deutsch (de) subtitles"
                    data-mwtitle="TimedText:Folgers.ogv.de.srt"
                    data-dir="ltr"/>
        </video>
    </span>
    <figcaption>caption</figcaption>
</figure>

Notes:

  • As a general rule, attributes derived from inspection of the original media file (original size, etc.) get data-file- prefixes. Attributes of derived/transcoded media get plain data- attributes. See T133670
  • The ‎<source> and ‎<track> tags are ignored during HTML-to-wikitext serialization; all information encoded in wikitext is represented on the ‎<figure>, ‎<span>, ‎<video>, and ‎<figcaption> elements.
  • The wikitext alt option does not exist for audio / video (it can be specified but is not added to output, since the html5 spec defines that it should not be present since accessibility for a/v is via captions specified by the ‎<track> element). It is represented in our html as a hidden attribute in data-mw.
  • The wikitext link option does not exist for audio / video (it can be specified but is not added to output, since we want the clicks to play the media, not follow a link) --videos always produce figure > span, never figure > a. It is represented in our html as a hidden attribute in data-mw.
  • The wikitext noicon, noplayer, and disablecontrols= options are deprecated and we mark them as bogus options, surfaced in linter for editors to clean up. See T134880 and T135537
  • Since it is not guaranteed that the original file is one of the sources listed, the resource attribute on ‎<video> represents that data.

More examples

[edit]

The thumbtime=$1 option is editable through a data-mw attribute and influences the seek time of the poster.

[[File:Folgers.ogv|thumbtime=1:25]]

<span class="mw-default-size" typeof="mw:Video" data-mw='{"thumbtime":"1:25"}'>
    <span>
        <video poster="//upload.wikimedia.org/wikipedia/commons/thumb/9/94/Folgers.ogv/seek%3D59-Folgers.ogv.jpg"
            controls=""
            preload="none"
            height="264"
            width="352"
            resource="./File:Folgers.ogv">
        ...

The start and end options are editable through data-mw attributes and influence the media fragments (#t=) on the source urls. [[File:Folgers.ogv|start=25|end=45]]

<span class="mw-default-size" typeof="mw:Video" data-mw='{"starttime":"25","endtime":"45"}'>
    <span>
        <video poster="//upload.wikimedia.org/wikipedia/commons/thumb/9/94/Folgers.ogv/seek%3D25-Folgers.ogv.jpg"
                controls=""
                preload="none"
                height="264"
                width="352"
                resource="./File:Folgers.ogv">
            <source src="https://upload.wikimedia.org/wikipedia/commons/9/94/Folgers.ogv#t=25,45"
                type='video/ogg; codecs="theora, vorbis"'
                data-file-width="352"
                data-file-height="264"
                data-title="Original Ogg file, 352 × 264 (637 kbps)"
                data-shorttitle="Ogg source"/>
            ...

Browsers will ignore dimensions on ‎<audio> elements but we supply them to be enforced dynamically, if desired. The wrapper is annotated with typeof="mw:Audio" to indicate audio files. See T133673 [[File:Continuity proof.ogg]]

<span class="mw-default-size mw-default-audio-height" typeof="mw:Audio">
    <span>
        <audio controls=""
                preload="none"
                height="20"
                width="220"
                resource="./File:Continuity_proof.ogg">
            <source src="https://upload.wikimedia.org/wikipedia/commons/4/4d/Continuity_proof.ogg"
                    type='audio/ogg; codecs="vorbis"'
                    data-title="Original Ogg file (25 kbps)"
                    data-shorttitle="Ogg source"/>
        </audio>
    </span>
</span>

Other Media

[edit]

Some complex media, like PDFs, permit previewing with the "page" option:

[[File:Foobar.pdf|thumb|page=3]]

<figure class="mw-default-size" typeof="mw:Image/Thumb" data-mw='{"page":"3"}'>
    <a href="./File:Foobar.pdf">
        <img resource="./File:Foobar.pdf" src="//upload.wikimedia.org/wikipedia/commons/thumb/a/a3/Foobar.pdf/page3-220px-Foobar.pdf.jpg" height="285" width="220"/>
    </a>
</figure>

Missing media

[edit]

If Parsoid fails to fetch the media info for a file, it keeps the same structure with stuffed span in place of the media element and links it to the missing media. See T169975

[[File:This_image_does_not_exist_yet.jpg|thumb|caption]]

<figure class="mw-default-size" typeof="mw:Error mw:Image/Thumb" data-mw='{"errors":[{"key":"apierror-filedoesnotexist","message":"This image does not exist."}]}'>
    <a href="./Special:FilePath/This_image_does_not_exist_yet.jpg">
        <span resource="./File:This_image_does_not_exist_yet.jpg" data-width="220">File:This image does not exist yet.jpg</span>
    </a>
    <figcaption>caption</figcaption>
</figure>
[edit]
[edit]
  • The href attribute is UTF8 (as everything else), with a relative link prefix that always navigates up to the top of the wiki namespace, especially in subpages / pages containing slashes in the title. Example: './Foo', or (in a subpage) './../Foo'. We percent-encode percents and question marks in hrefs to support following links to wiki pages with question marks in their name. On the way in (when posting HTML to Parsoid) we assume href values to be urlencoded and decode them during serialization. Modified link hrefs without ./ or ../ prefix are temporarily assumed to be absolute to the wiki namespace for now, but will also be interpreted as relative to the page soon to support relative links in other HTML content. After that change, the equivalent of an absolute wikilink [[Foo]] would need to return an href="/Foo" instead.

[[Main Page|alternate linked content]]

<a rel="mw:WikiLink" href="./Main_Page">alternate linked content</a>

[[Main Page]]

<a rel="mw:WikiLink" href="./Main_Page">Main Page</a>

Link with tail:

[[Potato]]es

<a rel="mw:WikiLink" href="./Potato">Potatoes</a>
[edit]

Media links of the form [[Media:Foo.jpg]] or [[Media:Foo.jpg|Link text]] are a special case of wikilinks and are represented as below. Note the mw:MediaLink rel attribute value.

[[Media:Foo.jpg]]

<a rel="mw:MediaLink" href="//upload.wikimedia.org/wikipedia/commons/0/06/Foo.jpg" title="Foo.jpg">Media:Foo.jpg</a>

[[Media:Foo.jpg|Link text]]

<a rel="mw:MediaLink" href="//upload.wikimedia.org/wikipedia/commons/0/06/Foo.jpg" title="Foo.jpg">Link text</a>
[edit]

[[Category:Foo]]

<link rel="mw:PageProp/Category" href="./Category:Foo">

[[Category:Foo|Bar baz#quux]]

<link rel="mw:PageProp/Category" href="./Category:Foo#Bar%20baz%23quux">
[edit]

[[en:Foo]]

<link rel="mw:PageProp/Language" href="http://en.wikipedia.org/wiki/Foo">
[edit]

[[:en:Foo]]

<a rel="mw:WikiLink/Interwiki" href="http://en.wikipedia.org/wiki/Foo">en:Foo</a>
[edit]

Autolinked URLs

[edit]

http://example.com

<a rel="mw:ExtLink" class="external free" href="http://example.com">http://example.com</a>
[edit]

[http://example.com]

<a rel="mw:ExtLink" class="external autonumber" href="http://example.com"></a>
[edit]

[http://example.com Link content]

<a rel="mw:ExtLink" class="external text" href="http://example.com">Link content</a>
[edit]
[edit]

ISBN 978-1413304541

<a rel="mw:WikiLink"
   href="./Special:BookSources/9781413304541">
  ISBN 978-1413304541
</a>
[edit]

RFC 1945

<a rel="mw:ExtLink" 
   href="http://tools.ietf.org/html/rfc1945">
  RFC 1945
</a>
[edit]

PMID 20610307

<a rel="mw:ExtLink"
   href="//www.ncbi.nlm.nih.gov/pubmed/20610307?dopt=Abstract">
  PMID 20610307
</a>

Nowiki blocks

[edit]

There are two options to handle nowiki editing:

  1. Strip the tags from the DOM and let the serializer add those that are needed after each edit
  2. Keep them in the DOM for more accurate round-tripping of manually created nowiki blocks, and prevent non-text content from being entered into these blocks in the editor (TODO)

We picked option 2 for now. The nowiki content remains editable. If the content is modified in a way that makes nowiki unnecessary Parsoid can remove the wrapper in the serializer.

<nowiki>[[foo]]</nowiki>

<span typeof="mw:Nowiki">[[foo]]</span>

HTML entities

[edit]

HTML entities are wrapped with a span tag with a mw:Entity typeof attribute. For example,&nbsp; in wikitext generates the following HTML output: <span typeof="mw:Entity">&nbsp;</span>

Editing clients that wish to prevent the entities from being decoded when transformed to wikitext have to wrap them with a span tag like above.

Display space

[edit]

An mw:DisplaySpace is a non-breaking space, added for the purpose of improving the visual display of punctuation, particularly for the French language. It's not present in the wikitext but added as a post-processing step on the output.

<span typeof="mw:DisplaySpace">&nbsp;</span>

(Previously, this had an additional mw:Placeholder typeof, which was removed in T254502.)

Behavior switches

[edit]

Behavior switches are primarily represented as a meta tag as a placeholder to mark the presence and place where the behavior switch showed up on the page. This lets editing clients support editing of these behavior switches in some fashion. The actual page modification that the behavior switch targets is not always flagged right now.

The table below shows the property string for the different behavior switch. The meta tag is of the form <meta property="mw:PageProp/property-string" />

Behavior Switch Property string Notes
__TOC__ toc Parsoid does not actually generate a Table of Contents
__NOTOC__ notoc No effect in Parsoid output
__FORCETOC__ forcetoc No effect in Parsoid output
__NEWSECTIONLINK__ newsectionlink -- To be documented --
__NONEWSECTIONLINK__ nonewsectionlink -- To be documented --
__NOGALLERY__ nogallery -- To be documented --
__HIDDENCAT__ hiddencat -- To be documented --
__NOCONTENTCONVERT__, __NOCC__ nocontentconvert -- To be documented --
__NOTITLECONVERT__, __NOTC__ notitleconvert -- To be documented --
__NOEDITSECTION__ noeditsection -- To be documented --
__NOINDEX__ noindex -- To be documented --
__INDEX__ index -- To be documented --
__STATICREDIRECT__ staticredirect -- To be documented --

Category default sort key

[edit]

{{DEFAULTSORT:foo}}

<meta property="mw:PageProp/categorydefaultsort" content="foo">

Displaytitle

[edit]

{{DISPLAYTITLE:foo}}

<meta property="mw:PageProp/displaytitle" content="foo">

Redirects

[edit]

#REDIRECT [[foo]]

<link rel="mw:PageProp/redirect" href="./Foo">

#REDIRECT [[:Category:Foo]]

<link rel="mw:PageProp/redirect" href="./Category:Foo">

#REDIRECT [[Category:Foo]]

<link rel="mw:PageProp/redirect" href="./Category:Foo">

(T104502: This no longer creates a category.)

#REDIRECT [[meatball:Foo]]

<link rel="mw:PageProp/redirect" href="http://www.usemod.com/cgi-bin/mb.pl?Foo"/>

Note that interwiki links generate redirect tags; the client is responsible for not doing an HTTP 301 or 302 redirect to an external site.

#REDIRECT [[:en:File:Wiki.png]]

<link rel="mw:PageProp/redirect" href="//en.wikipedia.org/wiki/File:Wiki.png"/>

Note that, unlike the PHP parser, using language links still generates correct redirect tags in Parsoid. The client is again responsible for not doing an HTTP redirect to an external wiki.

Template markup

[edit]

Regular transclusions

[edit]

Many transclusion parameters contain arbitrary wikitext, styles, template names and other non-semantic / DOM strings. We also have very little information about the type of each parameter (TemplateData may eventually provide this). So for now, we will thus expose all attributes in the "wt" (wikitext) format:

{{foo|unused value|paramname=used value}}

<body prefix="mw: http://mediawiki.org/rdf/
      mwns10: http://en.wikipedia.org/wiki/Template%58">
  
<span typeof="mw:Transclusion" about="#mwt1"
  data-mw='{"parts": [{"template":{"target":{"wt":"foo","href":"./Template:Foo"},"params":{"1":{"wt":"unused value"},"paramname":{"wt":"used value"}},"i":0}}]}'>
  Some text content
</span>
<table about="#mwt1">
  <tr>
    <td>used value</td>
  </tr>
</table>
</body>

The i property is used to associate additional information with each transclusion or extension fragment. This lets us support inline editing of things like infobox parameters in the future without changes to the JSON data structure.

Parameter names are represented by their index, if not explicitly named, or by the name that will be used when replacing them. In the case that the normalized parameter named is different from the actual parameter name in the text, a key.wt attribute is used to keep the name as it appears in the text. For example:

{{foo|param<!--comment-->name=value}}

<body prefix="mw: http://mediawiki.org/rdf/
      mwns10: http://en.wikipedia.org/wiki/Template%58">
  
<span typeof="mw:Transclusion" about="#mwt1"
  data-mw='{"parts": [{"template":{"target":{"wt":"foo","href":"./Template:Foo"},"params":{"paramname":{"wt":"value", "key":{"wt":"param&lt;!--comment-->name"}}},"i":0}}]}'>
  Some text content
</span>
<table about="#mwt1">
  <tr>
    <td>value</td>
  </tr>
</table>
</body>

Compound content blocks that include output from several transclusions like this football table is represented by interspersing wikitext strings with transclusion information in the data-mw.parts array:

{{table-start}}
{{cell|unused value|param=used value}}
|-
{{cell|unused value|param=used value}}
|-
|<math>1+1</math>
|}
<span typeof="mw:Transclusion" about="#mwt1"
  data-mw='{"parts":
[
  {"template":{"target":{"wt":"Table-start", "href": "./Template:Table-start"}},"i":0},
  "\n",
  {"template":{"target":{"wt":"Cell", "href": "./Template:Cell"},"params":{"1":{"wt":"unused value"},"param":{"wt":"used value"}}},"i":1},
  "\n|-\n",
  {"template":{"target":{"wt":"Cell", "href": "./Template:Cell"},"params":{"1":{"wt":"unused value"},"param":{"wt":"used value"}}},"i":2},
  "\n|-\n|",
  {"extension":{"name":"math","attrs": {}, "body":{"extsrc":"1+1","mathml":"<maybelater/>"}},"i":3},
  "|}"
]}'>
  Some text content
</span>
<table about="#mwt1">
  <tr>
    <td>used value</td>
  </tr>
</table>

Editing support for the interspersed wikitext is difficult to implement on the server side, as those wikitext edits need to be restricted in their effect to the original DOM range. A potential solution to this could be to wrap the multi-template compound block into a template hook that expands its content to a well-balanced DOM structure. Arbitrary wikitext edits within this tag would still only affect the original DOM range, both in Parsoid and the PHP parser. This is lower priority though, so for now the interspersed wikitext will be read-only.

Variables and Parser Functions

[edit]

These other magic words, apart from the two defined in the behaviour switches section above (DEFAULTSORT and DISPLAYTITLE), render similarly to templates but have a function property in their data-mw, as opposed to an href. For example, the wikitext {{!}} renders as,

<p about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"!","function":"!"},"params":{},"i":0}}]}'>|</p>

Generated attributes of HTML tags

[edit]

Status: Implemented. See task T54913

This is the representation of attributes in links, tables, and html tags whose keys and/or values were not present as literal text in the input. When only attributes are affected, the element is be assigned an mw:ExpandedAttrs typeof attribute and the data-mw JSON object will provide additional specific information about the keys or values that are fully or partially generated. If other parts of the content are also transclusion-affected, the element will be marked up as a general transclusion instead.

It is conceivable to think up use-cases where part of an attribute value is generated by a template (ex: color of a background-color of a style attribute), but not as much for attribute-keys. This spec also assumes that a template can only generate one attribute rather than multiple attributes.

data-mw = {
    "attribs": [
        [{"txt": "href","html": "..." }, {"html": "..."}],
        ["sortKey", { "html": "..." }],
        ["1", { "html": "..." }],
        ["2", { "html": "..." }]
    ]
}

A few examples are worked out below.

Example 1: [[F{{echo|o}}o|bar]]

<a href="./Foo"
  typeof="mw:ExpandedAttrs"
  rel="mw:WikiLink"
  about="#mwt2"
  title="Foo"
  data-mw='{
    "attribs": [
      [
        {"txt":"href"},
        {
          "html":"F&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\"
            data-mw=&apos;{\"parts\":[{\"template\":{\"target\":{\"wt\":\"1x\",\"href\":\"./Template:1x\"},\"params\":{\"1\":{\"wt\":\"o\"}},\"i\":0}}]}&apos;>o&lt;/span>o"
        }
      ]
    ]
  }'>
bar</a>

Example 2: <div style="{{1x|color:red;}}">...</div>

<div style="color:red;"
  typeof="mw:ExpandedAttrs"
  about="#mwt2"
  data-mw='{
    "attribs": [
      [
        {"txt":"style"},
        { "html": "&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\"
          data-mw=&apos;{\"parts\":[{\"template\":{\"target\":{\"wt\":\"1x\",\"href\":\"./Template:1x\"},\"params\":{\"1\":{\"wt\":\"color:red;\"}},\"i\":0}}]}&apos;>color:red;&lt;/span>" }
      ]
    ]
  }'>
...
</div>

Example 3: [[File:foo.jpg|{{1x|thumb}}|{{1x|160px}}]]

<figure
  typeof="mw:Image/Thumb mw:ExpandedAttrs"
  about="#mwt3"
  data-mw='{
    "attribs": [
      ["thumbnail",
        {"html":"&lt;span about=\"#mwt1\" typeof=\"mw:Transclusion\"
          data-mw=&apos;{\"parts\":[{\"template\":{\"target\":{\"wt\":\"1x\",\"href\":\"./Template:1x\"},\"params\":{\"1\":{\"wt\":\"thumb\"}},\"i\":0}}]}&apos;>thumb&lt;/span>"}
      ],
      ["width",
        {"html":"&lt;span about=\"#mwt2\" typeof=\"mw:Transclusion\" data-mw=&apos;{\"parts\":[{\"template\":{\"target\":{\"wt\":\"1x\",\"href\":\"./Template:1x\"},\"params\":{\"1\":{\"wt\":\"160px\"}},\"i\":0}}]}&apos;>160px&lt;/span>"}
      ]
    ]
  }'>
    ... Rest of image HTML here ...
</figure>

Parameter Substitution at the top-level

[edit]

This section is only present for the sake of completeness. Unexpanded parameter markup is unlikely to be useful in top-level content, and if found, it is either a draft, syntax error, or a copy-paste without being fixed up.

This section specifies wrapping for parameter uses in the top-level namespace where all parameter substitutions evaluate to a null value. The structure borrows heavily from transclusion content, described above, with some slight divergences. The target corresponds to the parameter name, and the params contain the default value.

{{{foo|''some italic'' plain text '''some bold'''}}}

<p about="#mwt1" typeof="mw:Param" data-mw='{"parts":[{"templatearg":{"target":{"wt":"foo"},"params":{"1":{"wt":"&apos;&apos;some italic&apos;&apos; plain text &apos;&apos;&apos;some bold&apos;&apos;&apos;"}},"i":0}}]}'>
    <i>some italic</i> plain text <b>some bold</b>
</p>

Extension tags

[edit]

<math>1+1</math>

<span about="#mwt1" typeof="mw:Extension/Math"
  data-mw='{"name": "math": "attrs": {}, "body": {"extsrc":"1+1"}}'>
  1 + 1
</span>

The data-mw attribute is a JSON object. It is meant as an extensible public interface, so more top-level members can be added. The top-level structure depends on the content type, with the main types being transclusions and extensions. See also the transclusion content section.

At present, Parsoid has few native extension handlers. See Specs/HTML/2.2.0/Extensions for details on editing their content.

Annotation tags

[edit]
<translate>
One paragraph.

And another.
</translate>
<meta typeof="mw:Annotation/translate" data-mw='{"rangeId":"mwa0","extendedRange":false,"wtOffsets":[0,11]}'/>
<p>One paragraph.</p>

<p>And another.
</p><meta typeof="mw:Annotation/translate/End" data-mw='{"wtOffsets":[41,53]}'/>

An annotated range is delimited by a pair of <meta> tags with the following attributes:

  • typeof: type of the annotation, value mw:Annotation/XXX, where XXX is the type of the annotation, for the start tag; mw:Annotation/XXX/End for the end tag.
  • data-mw: is a JSON object used in other contexts of this specification. The annotation tags add the following attributes to it:
    • rangeId: identifier of the range, in the start tag.
    • wtOffsets: in both the start end end tag, contains the original position (start/end character) of the annotation tag in the original wikitext - effectively a copy of the tsr range in the data-parsoid attribute (see Parsoid/Internals/data-parsoid for more information.)
    • extendedRange: if the range delimited by the meta tags has been extended (see below), this property is set to true in the data-mw attribute of the start meta tag.
    • attrs: if the original annotation tag has attributes (such as name for a tvar), they are added as key-value in the attrs property of the data-mw of the start meta tag.

Range extension

[edit]

If the range enclosed by the annotation tags in the wikitext does not correspond to a contiguous DOM forest, the range is extended so that it's the case. This means that the meta tags generated by Parsoid are guaranteed to enclose a contiguous DOM forest. When the annotation range has been extended, it is marked with the extendedRangeproperty of the data-mw attribute of the starting meta tag.

Additionally, ranges can be extended due to the fostering of one or both ends of the range. In that case, the fostered content as well as the table(s) at the origin of the fostering are between two meta tags that are marked as an extended range definition.

Edits by clients are discouraged in extended ranges. If edits happen in an extended range, it can happen that the round-trip loses the initial position of the annotation in the wikitext, which would result in a larger portion of the wikitext ending up between the annotation start and end tags.

Annotations in attributes

[edit]

It can happen that the annotated region of a tree corresponds to a single HTML tag attribute (or part thereof). This would for instance be the case for Some description , which would annotate the href attribute of the corresponding hyperlink. In this case, the corresponding attribute is handled as in #Generated attributes of HTML tags as expanded attributes. Additionally, the corresponding tag gets the typeof attribute corresponding to the annotation in the annotated attribute.

[[link|Some description]]
<p><a typeof="mw:ExpandedAttrs mw:Annotation/tvar" about="#mwt1" rel="mw:WikiLink" href="./Link" title="Link" class="new" data-mw='{"attribs":[[{"txt":"href"},{"html":"&lt;meta typeof=\"mw:Annotation/tvar\" data-parsoid=&apos;{\"dsr\":[2,18,null,null]}&apos; data-mw=&apos;{\"attrs\":{\"name\":\"link\"},\"rangeId\":\"mwa0\"}&apos;/>link"}]]}'>Some description</a></p>

noinclude / includeonly / onlyinclude

[edit]

We only care about these in the actual page context, not in transcluded pages / templates.

foo<noinclude>bar</noinclude>baz

<body prefix="mw: http://mediawiki.org/rdf/
      mwt0: http://en.wikipedia.org/wiki/Template%58"> 
<p>foo<meta typeof="mw:Includes/NoInclude" />bar<meta typeof="mw:Includes/NoInclude/End" />baz</p>
</body>

foo<onlyinclude>bar</onlyinclude>baz

<body prefix="mw: http://mediawiki.org/rdf/
      mwt0: http://en.wikipedia.org/wiki/Template%58"> 
<p>foo<meta typeof="mw:Includes/OnlyInclude" />bar<meta typeof="mw:Includes/OnlyInclude/End" />baz</p>
</body>

foo<includeonly>bar</includeonly>baz

<body prefix="mw: http://mediawiki.org/rdf/ mwt0: http://en.wikipedia.org/wiki/Template%58"> 
<p>foo<meta typeof="mw:Includes/IncludeOnly" data-mw='{"src":"&lt;includeonly>bar&lt;/includeonly>"}' /><meta typeof="mw:Includes/IncludeOnly/End" /></p>
</body>

The content in includeonly blocks is exposed to clients for editing and diffing, etc. using the data-mw attribute.

Language conversion blocks

[edit]

Status: experimental.

The attribute is named data-mw-variant since it affects the read-only rendering of the page, and data-mw attributes are supposed to be ignored for rendering and only needed for editing.

Top-level fields in the JSON are: disabled, twoway, oneway, name, filter, and describe. If the wikitext "show" flag is not present or implicit, the DOM markup will use the ‎<meta> element. If "show" is present or implicit, the DOM markup will use ‎<span> if all possible contents are inlineable, or ‎<div> otherwise.

foo-{bar baz}- quux

<p>
  foo<span typeof="mw:LanguageVariant" data-mw-variant='{"disabled":{"t":"bar baz"}}'></span> quux
</p>

a-{N|en}-b

<p>
a<span typeof="mw:LanguageVariant" data-mw-variant='{"name":{"t":"en"}}'></span>b
</p>

foo-{zh;zh-hans;zh-hant|blog, WEBJOURNAL, WEBLOG}- quux

<p>
  foo<span typeof="mw:LanguageVariant" data-mw-variant='{"filter":{"l":["zh","zh-hans","zh-hant"],"t":"blog, WEBJOURNAL, WEBLOG"}}'></span> quux
</p>

foo-{zh-cn:blog; zh-hk:WEBJOURNAL; zh-tw:WEBLOG;}- quux

<p>
  foo<span typeof="mw:LanguageVariant" data-mw-variant='{"twoway":[{"l":"zh-cn","t":"blog"},{"l":"zh-hk","t":"WEBJOURNAL"},{"l":"zh-tw","t":"WEBLOG"}]}'></span> quux
</p>

-{D|zh-cn:XA; zh-tw:YA}-

<p><span typeof="mw:LanguageVariant" data-mw-variant='{"describe":true,"twoway":[{"l":"zh-cn","t":"XA"},{"l":"zh-tw","t":"YA"}]}'></span></p>

foo-{H|WEBLOG=>zh-cn:blog;WEBLOG=>zh-hk:WEBJOURNAL}- quux

<p>
  foo<meta typeof="mw:LanguageVariant" data-mw-variant='{"add":true,"oneway":[{"f":"WEBLOG","l":"zh-cn","t":"blog"},{"f":"WEBLOG","l":"zh-hk","t":"WEBJOURNAL"}]}'/> quux
</p>

<span>a-{b<div>c</div>d}-e</span>

<p>
  <span>a</span>
</p>
<div typeof="mw:LanguageVariant" data-mw-variant='{"disabled":{"t":"b&lt;div data-parsoid=&apos;{\"stx\":\"html\",\"dsr\":[10,22,5,6]}&apos;>c&lt;/div>d"}}'></div>
<p>
  e
</p>

Further discussion (and historical background) at task T43716 and Language conversion blocks.

Error handling

[edit]

See task T50900:

  • For API errors because of a non-existing image, data-mw.errors.key is set to "missing-image".
  • For API errors getting image info, data-mw.errors.key is set to "api-error" and data-mw.errors.message has more information about the specific error.
  • For image wikitext where a manual thumbnail is specified and it is not present, the data-mw.errors.key is set to "missing-thumbnail" and data-mw.errors.message is set to "This thumbnail does not exist.".

Ex: [[File:Nonexisting.jpg|thumb|caption content]]

<figure typeof="mw:Image/Thumb mw:Error" 
  data-mw='{"errors":[{"key":"missing-image"}]}'
  class="mw-halign-right mw-default-size">
   <a href="./File:Foobar.jpg">
     <img alt="Nonexisting.jpg"
        resource="./File:Foobar.jpg" />
   </a>
   <figcaption>caption content</figcaption>
</figure>

Ex:[[File:Blah.jpg|thumb|caption content]]

<figure typeof="mw:Image/Thumb mw:Error" 
  data-mw='{"errors":[{"key":"api-error", "message": "... whatever the API returns here ..."}]}'
  class="mw-halign-right mw-default-size">
....
</figure>