diff --git a/compat-data-schema.md b/compat-data-schema.md new file mode 100644 index 00000000000000..0d8e25f5d9b291 --- /dev/null +++ b/compat-data-schema.md @@ -0,0 +1,365 @@ +# The browser-compat-data JSON format + +Maintained by the [MDN team at Mozilla](https://wiki.mozilla.org/MDN). + +## Browser compatibility information +MDN needs the compatibility information for each feature of the Web platform. In +order to make it easier to maintain and easy to reuse by third-party tool, we +decided to store this data into a set of JSON files, stored in a git repository. + +In order to ensure the coherence of the data, we define a JSON schema that +describes the content of the JSON files storing the info. Before accepting a +PR, we validate the changes against this schema with _travis-ci_. + +This document describes the format in lay-man terms so that a human can create +a JSON browser-compat-data file without having to decrypt the schema from +scratch. + +__Note:__ The schema tries to capture as many constraints and rules about the +browser-compat-data JSON format. Nevertheless there are constraints that cannot +be described inside a schema, and won't be checked by automated tests. We tried +to mark such cases in the following text with a __Not enforced by the +schema__ notice. + +## The JSON format + +### Division in files +The browser-compat-data schema has been designed so the division in files doesn't +convey any meaning. That means that browser compatibility information about features +can be stored in one single large files or being divided in smaller files. + +The division in separate files, themselves in different directories is guided +by making it easy to maintain by humans. + +### Schema versioning +There one single information that is tied to each file, and is mandatory. It is +the version of schema used inside the file. + + { + "version": "1.0.0", + "data": { + … + } + } + +We are using semantic versioning, so the version is a `string` containing three +integers separate by a dot (`.`). No whitespace or additional characters are +allowed. To see detail of the meaing fo the 3 integers, see the +[Semantic Versioning 2.0.0 specification](http://semver.org/). + +The "data" contains a list of _features_, with their identifier, their description, +their support status, and thir status. + +__Note:__ You cannot mix two schemas in the same file. `"version"` is unique in +a given file. + +### Feature identifier +A _feature_ is a functionality of the platform. It is an entity that can be used +independently. A _sub-feature_ is a specific value or behavior of a feature. The +division is a bit arbitrary, but matches the way developers perceive features of +a platform + +* For CSS, an entity like a property, a pseudo-class, a pseudo-element, an +at-rule, or a descriptor is a feature. A value, a new syntax change, or a +specific behavior, like if a property applies to a set of elements or another +are sub-features. + +* For HTML, an element or an attribute are features, while specific values of an +attribute are sub-features. + +* For Web APIs or JavaScript, an interface, a method, a property, a constructor +are features, while arguments or special values of an enumerated type are +sub-features. + +Each feature is identified by a unique hierarchy of strings. E.g the +`text-align` property is identified by `css.properties.text-align`. + +The strings of an identifier are not intended to be displayed and are therefore +not translatable. + +In JSON, this gives: + + "data": { + "css": { + "properties": { + "text-align": {…}, + … + }, + … + }, + … + } + + That way, each feature is uniquely identifier, independently of the file it is + defined in. + + The hierarchy of identifiers is not defined inside the schema. It is a + convention of the project using the schema. + + In the MDN browser-compat case, it is: + + _Note: this list will evolve as we migrate our data_ + + "data": { + "css": { + "properties": {…} + "pseudo-classes": {…} + "pseudo-elements": {…} + "at-rules": {…} + }, + "html": { + "elements": { + …, + "": { + …, + "": {…}, + … + } + } + "global_attributes": {…} + } + } + +### Feature description + +A feature is represented by an identifier containing the `"__compat"` property. +In this compat property, you'll find the list of sub-features associated to the +feature. + +A feature has at least one sub-feature, representing the basic support. It is +always named `"basic_support"`. + +The basic support feature represents the minimal set of functionality included +when a feature is qualified of 'supported'. What this represents depends of the +evolution of the feature over time, both in term of specification and of browser +support. Another way of seeing it is to consider `"basic_support"` as representing all +the functionality of the feature that doesn't have its own sub-feature(s). + +### Sub-feature + +A sub-feature is the basic entity having browser compatibility information. As +explained in the previous paragraph, any feature has at least one sub-feature +called `'basic_support'`, but it may many more. + +A sub-feature may have three properties. + +* __Sub-feature description__ contained in the `"desc"` property. It is a +`string` that contains a human-readable description of the sub-feature. As it is +intended to be used as a kind of caption or title for the feature, keep it short. +the `` and ``, as well as the macros `{{cssxref}}`, `{{HTMLElement}}`, +`{{htmlattrxref}}`, and `{{domxref}}` can be used. See the localization section +below for an explanation about how this string will be localized. +* __Compat information__ contained in the `"support"` property. It contains an +object listing the compat information for each browser. (See the description +below.) +* __Status information__ contained in the `"status"` object. It contains the +information about the stability of the sub-feature: Is it a functionality that +is standard? Is it stable? Has it been deprecated and shouldn't be used anymore +(See the description below.) + +### The `"support"` object +Each sub-feature has support information. For each browser identifier, it +contains a compat object with the information about versions, prefixes or +alternate names, as well as notes. + +The currently accepted browser identifiers are: +* `"webview_android"`, Webview, the former stock browser on Android, +* `"chrome"`, Google Chrome (on desktops), +* `"chrome_android"`, Google Chrome (on Android), +* `"edge"`, MS Edge (on Windows), +* `"edge_mobile"`, MS Edge, the mobile version, +* `"firefox`", Mozilla Firefox (on desktops), +* `"firefox_android"`, Firefox for Android, sometimes nicknamed Fennec, +* `"ie_mobile"`, Microsoft Internet Explorer, the mobile version, +* `"ie"`, Microsoft Internet Explorer (discontinued) +* `"opera"`, the Opera browser (desktop), based on Blink since Opera 15, +* `"opera_android"`, the Opera browser (Android version) +* `"safari"`, Apple Safari, on Mac OS, +* `"safari_ios"`, Apple Safari, on iOS, +* `"servo"`, the experimental Mozilla engine. + +No value is mandatory. + +Each of these properties contains a `support-statement` object with the +practical compatibility information for this sub-feature and this browser. + +### The `support-statement` object +This object is the key element of each browser compat information. It is a +support-statement object. It is an array of `support` objects, but if there +are only one of them, the array can be ommitted + + +Example of an `support` compat object (with 2 entries): + + { + "support": [ + { + "version_added": "6.0" + }, + { + "prefix": "-moz-", + "version_added": "3.5", + "version_removed": "9.0" + } + + ] + } + +Example of a `support` compat object (with 1 entry, array ommitted): + + { + "support": { "version_added": "6.0" } + } + +### Compat information in a `"support"` field. +Compatibility information is stored in a `"support"` field. It may consist of the +following properties: + +#### `"version_added"` +Contains a string with the version number the sub-feature has +been added (and is therefore supported), the Boolean values to indicate the +sub-feature is supported (`true`, with the additional meaning that the we don't +know in which version) or not (`false`). A value of `null` indicates that we +don't have support information for it. + +* Support from version 3.5 (included) + + { + "version_added": "3.5" + } + +* Support, but version unknown + + { + "version_added": true + } + +* No support + + { + "version_added": false + } + +* Support unknown (default value) + + { + "version_added" : null + } + +#### `"version_removed"` +Contains a string with the version number the sub-feature +stopped to be supported. It may be a Boolean value of (`true` or `false`), or the +`null` value. If `"version_added"` is set to a Boolean or a `string`, `"version_removed"` +default value is `false`; if it is `null`, the default value of `"version_removed"` +is `null` too. + +* Removed in version 10 (start in 3.5): + + { + "version_added": "3.5", + "version_removed": "10" + } + +* Not removed (default if `"version_added"` is not `null`): + + { + "version_added": "3.5", + "version_removed": false + } + + +#### `"prefix"` +Contains the prefix to add to the sub-feature name (default to the empty +string). Note that leading and trailing `-` must be included. + +* Prefixed sub-feature: + + { + "prefix": "-moz-", + "version_added": "3.5" + } + +#### `"alternative_name"` +For the cases when prefixing is not enough, contains the whole name of the sub-feature. ( A +sub-feature may have a completely different name in some older version. + +* Prefixed version had a different capitalization + + { + "alternative_name": "mozRequestFullScreen", + "version_added": "true", + "version_removed": "9.0" + } + +#### `"flags"` +Is a specific object indicating what kind of flags must be set for this feature +to work. It consists of three values: +* `"type"`, an enum that indicates what kind of flag it is: `"preference"` represents +a flag that the user can set himself on its browser, like in `about:config` on Firefox; +or `"compile_flag"` that is a flag that has to be set before the compilation of the browser. +* `"name"`, a `string` representing the flag or preference to modify. +* `"value_to_set"` representing the actual to set the flag to. It is a string, that may be +converted to the right type (that is `true` or `false` for Boolean value, or `4` for an +integer valuie). + +#### `partial_implementation` +Is a `boolean` value indicating if the implementation of the subfeature follows the current +spec close enough not to create major interoperability problem. It defaults to `false` (no +interoperability problem expected). If set `true`, it is recommended to add a note indicating +how it diverges from the standard (implement an old version of the standard, …) + +#### `"notes"` +Is an `array` of zero or more translatable `string` containing +additional pertinent information. If there are only 1 entry in the array, +the array can be ommitted + +* Indication of an experimental support behind a flag + + { + "version_added" : false, + "notes": "Experimental implementation available when layout.css.text-align is set to true." + } + +* Linking to a bug and indicating a restriction + + { + "version_added": "3.5", + "notes": ["See bug 123456.", + "Do not work on {{cssxref('::first-letter)}} pseudo-elements."] + } + +Each `string` that contains a human-readable description of the sub-feature. The +`` and ``, as well as the macros `{{cssxref}}`, `{{HTMLElement}}`, +`{{htmlattrxref}}`, and `{{domxref}}` can be used. See the localization section +below for an explanation about how this string will be localized. + +### Status information +The status indicates the stability of the feature. It is an object named +`"status"` and has four mandatory properties: +* `"experimental"`, a `boolean` value that indicates this functionality is +intended to be an addition to the Web platform. Some features are added to +conduct tests. Set to `false`, it means the functionality is mature, and no +significant incompatible changes is expected in the future. +* `"standard_track"`, a `boolean` value indicating if the feature is in a +standard track. +* `"obsolete`", a `"boolean"` value that indicates if the functionality is only +kept for compatibility purpose and shouldn't be used anymore. It may be removed +from the Web platform in the future. + +## Localization +There is no localization happening inside the .json files themselves; l10n is +handled separately in order to take advantage of existing toolchains. + +In the case of MDN, .po files with the translated string will be created. We +will work on them once the prototype validating the structure of the json will +be done. + +The plan is: + +1. Define all source strings as English in the spec, as well as which data elements are plain text, HTML, etc. Avoiding HTML is a good idea, but being clear about it is necessary if you can't avoid it. +2. Create a script to extract strings into the standard gettext format +3. Manage translation using gettext conventions, like Kuma, perhaps even using Pontoon to translate the strings. With gettext, you get fuzzy translations, notifications of changed strings, etc. etc. for free. +4. Create a second script to export gettext-formatted files to a JSON data structure. +5. Implement a gettext-like translation in KumaScript (I'm pretty sure this is already done, and multiple times). + +1. is done in this document. diff --git a/compat-data.schema.json b/compat-data.schema.json new file mode 100644 index 00000000000000..1f32a8bd4a2f7c --- /dev/null +++ b/compat-data.schema.json @@ -0,0 +1,133 @@ +{ + "$schema": "http://json-schema.org/schema#", + + "definitions": { + + "simple_support_statement": { + "type": "object", + "properties": { + "prefix": { "type": "string" }, + "alternative_name": { "type": "string" }, + "flag": { "type": "object", + "properties": { + "type": { "type": "string", "enum": ["preference", "compile_flag"] }, + "name": { "type": "string" }, + "value_to_set": { "type": "string"} + }, + "additionalProperties": false + }, + "partial_implementation": { "type": "boolean" }, + "version_added": { "type": ["string", "boolean", "null"] }, + "version_removed": { "type": ["string", "boolean", "null"] }, + "notes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + } + ] + } + }, + "required": ["version_added"], + "additionalProperties": false + }, + + "array_support_statement": { + "type": "array", + "items": { + "$ref": "#/definitions/simple_support_statement" + } + }, + + "support_statement": { + "anyOf": [ + { "$ref": "#/definitions/simple_support_statement" }, + { "$ref": "#/definitions/array_support_statement" } + ] + }, + + "status_statement": { + "type": "object", + "properties": { + "experimental": { "type": ["string", "boolean"] }, + "standard_track": { "type": ["string", "boolean"] }, + "obsolete": { "type": ["string", "boolean"] } + }, + "required": ["experimental", "standard_track", "obsolete"], + "additionalProperties": false + }, + + "subfeature": { + "type": "object", + "properties": { + "desc": { "type": ["string"] }, + "support": { "$ref": "#/definitions/compat_block" }, + "status": { "$ref": "#/definitions/status_statement" } + }, + "additionalProperties": false + }, + + "compat_block": { + "type": "object", + "properties": { + "webview_android": { "$ref": "#/definitions/support_statement" }, + "chrome": { "$ref": "#/definitions/support_statement" }, + "chrome_android": { "$ref": "#/definitions/support_statement" }, + "edge": { "$ref": "#/definitions/support_statement" }, + "edge_mobile": { "$ref": "#/definitions/support_statement" }, + "firefox": { "$ref": "#/definitions/support_statement" }, + "firefox_android": { "$ref": "#/definitions/support_statement" }, + "ie_mobile": { "$ref": "#/definitions/support_statement" }, + "ie": { "$ref": "#/definitions/support_statement" }, + "opera": { "$ref": "#/definitions/support_statement" }, + "opera_android": { "$ref": "#/definitions/support_statement" }, + "safari": { "$ref": "#/definitions/support_statement" }, + "safari_ios": { "$ref": "#/definitions/support_statement" }, + "servo": { "$ref": "#/definitions/support_statement" } + }, + "additionalProperties": true + }, + + "subfeature_set": { + "type": "object", + "properties": { + "basic_support": { "$ref": "#/definitions/subfeature" } + }, + "required": ["basic_support"], + "additionalProperties": { "$ref": "#/definitions/subfeature" } + }, + + "identifier": { + "type": "object", + "properties": { + "__compat": { "$ref": "#/definitions/subfeature_set" } + }, + "patternProperties":{ + "^(?!__compat).*$" : { "$ref": "#/definitions/identifier" } + }, + "additionalProperties": false + }, + + "compat_data": { + "type": "object", + "patternProperties": { + "^(?!__compat).*$" : { "$ref": "#/definitions/identifier" } + }, + "additionalProperties": false + } + + }, + + "type": "object", + "properties": { + "version": { "type": "string"}, + "data": { "$ref" : "#/definitions/compat_data" } + }, + "required": ["version", "data"], + "additionalProperties": false +}