{
	"$schema": "http://json-schema.org/schema#",
	"description": "MediaWiki extension.json schema",
	"type": "object",
	"additionalProperties": false,
	"properties": {
		"manifest_version": {
			"type": "integer",
			"description": "Version of the extension.json schema the extension.json file is in.",
			"required": true
		},
		"name": {
			"type": "string",
			"description": "The extension's canonical name.",
			"required": true
		},
		"namemsg": {
			"type": "string",
			"description": "i18n message key of the extension's name."
		},
		"type": {
			"type": "string",
			"description": "The extension's type, as an index to $wgExtensionCredits.",
			"default": "other"
		},
		"author": {
			"type": [
				"string",
				"array"
			],
			"description": "Extension's authors.",
			"items": {
				"type": "string"
			}
		},
		"version": {
			"type": "string",
			"description": "The version of this release of the extension."
		},
		"url": {
			"type": "string",
			"description": "URL to the homepage for the extension.",
			"format": "uri-reference"
		},
		"description": {
			"type": "string",
			"description": "Raw description of the extension."
		},
		"descriptionmsg": {
			"type": "string",
			"description": "Message key for a i18n message describing the extension."
		},
		"license-name": {
			"type": "string",
			"description": "SPDX identifier for the license under which the extension is released."
		},
		"requires": {
			"type": "object",
			"description": "Indicates what versions of MediaWiki core or extensions are required. This syntax may be extended in the future, for example to check dependencies between other services.",
			"additionalProperties": false,
			"properties": {
				"MediaWiki": {
					"type": "string",
					"description": "Version constraint string against MediaWiki core."
				},
				"extensions": {
					"type": "object",
					"description": "Set of version constraint strings against specific extensions."
				},
				"skins": {
					"type": "object",
					"description": "Set of version constraint strings against specific skins."
				}
			}
		},
		"ResourceFileModulePaths": {
			"type": "object",
			"description": "Default paths to use for all ResourceLoader file modules",
			"additionalProperties": false,
			"properties": {
				"localBasePath": {
					"type": "string",
					"description": "Base path to prepend to all local paths, relative to current directory"
				},
				"remoteExtPath": {
					"type": "string",
					"description": "Base path to prepend to all remote paths, relative to $wgExtensionAssetsPath"
				},
				"remoteSkinPath": {
					"type": "string",
					"description": "Base path to prepend to all remote paths, relative to $wgStylePath"
				}
			}
		},
		"ResourceModules": {
			"type": "object",
			"description": "ResourceLoader modules to register",
			"patternProperties": {
				"^[a-zA-Z0-9-\\.]+$": {
					"type": "object",
					"anyOf": [
						{
							"description": "A ResourceLoaderFileModule definition",
							"additionalProperties": false,
							"properties": {
								"localBasePath": {
									"type": "string",
									"description": "Base path to prepend to all local paths in $options. Defaults to $IP"
								},
								"remoteBasePath": {
									"type": "string",
									"description": "Base path to prepend to all remote paths in $options. Defaults to $wgScriptPath"
								},
								"remoteExtPath": {
									"type": "string",
									"description": "Equivalent of remoteBasePath, but relative to $wgExtensionAssetsPath"
								},
								"skipFunction": {
									"type": "string",
									"description": "Path to a file containing a JavaScript \"skip function\", if desired."
								},
								"scripts": {
									"type": ["string", "array"],
									"description": "Scripts to always include (array of file paths)",
									"items": {
										"type": "string"
									}
								},
								"languageScripts": {
									"type": "object",
									"description": "Scripts to include in specific language contexts (mapping of language code to file path(s))",
									"patternProperties": {
										"^[a-zA-Z0-9-]{2,}$": {
											"type": [
												"string",
												"array"
											],
											"items": {
												"type": "string"
											}
										}
									}
								},
								"skinScripts": {
									"type": "object",
									"description": "Scripts to include in specific skin contexts (mapping of skin name to script(s)",
									"patternProperties": {
										".+": {
											"type": [
												"string",
												"array"
											],
											"items": {
												"type": "string"
											}
										}
									}
								},
								"debugScripts": {
									"type": ["string", "array"],
									"description": "Scripts to include in debug contexts",
									"items": {
										"type": "string"
									}
								},
								"loaderScripts": {
									"type": ["string", "array"],
									"description": "Scripts to include in the startup module",
									"items": {
										"type": "string"
									}
								},
								"dependencies": {
									"type": ["string", "array"],
									"description": "Modules which must be loaded before this module",
									"items": {
										"type": "string"
									}
								},
								"styles": {
									"type": ["string", "array", "object"],
									"description": "Styles to always load",
									"items": {
										"type": "string"
									}
								},
								"skinStyles": {
									"type": "object",
									"description": "Styles to include in specific skin contexts (mapping of skin name to style(s))",
									"patternProperties": {
										".+": {
											"type": [
												"string",
												"array"
											],
											"items": {
												"type": "string"
											}
										}
									}
								},
								"messages": {
									"type": ["string", "array"],
									"description": "Messages to always load",
									"items": {
										"type": "string"
									}
								},
								"group": {
									"type": "string",
									"description": "Group with which this module should be loaded"
								},
								"deprecated": {
									"type": ["object", "boolean"],
									"description": "Whether the module is deprecated and usage is discouraged. Either a boolean or an object with key message can be used to customise deprecation message."
								},
								"position": {
									"type": "string",
									"description": "Position on the page to load this module at",
									"enum": [
										"bottom",
										"top"
									]
								},
								"templates": {
									"type": ["object", "array"],
									"description": "Templates to be loaded for client-side usage"
								},
								"targets": {
									"type": ["string", "array"],
									"description": "ResourceLoader target the module can run on",
									"items": {
										"type": "string"
									}
								},
								"noflip": {
									"type": "boolean",
									"description": "Whether to skip CSSJanus LTR-to-RTL flipping for this module. Recommended for styles imported from libraries that already properly handle their RTL styles. Default is false, meaning CSSJanus will be applied on RTL-mode output."
								}
							}
						},
						{
							"description": "A ResourceLoaderWikiModule definition",
							"additionalProperties": false,
							"properties": {
								"class": {
									"enum": ["ResourceLoaderWikiModule"]
								},
								"group": {
									"type": "string",
									"description": "Group with which this module should be loaded"
								},
								"position": {
									"type": "string",
									"description": "Position on the page to load this module at",
									"enum": [
										"bottom",
										"top"
									]
								},
								"targets": {
									"type": ["string", "array"],
									"description": "ResourceLoader target the module can run on",
									"items": {
										"type": "string"
									}
								},
								"scripts": {
									"type": "array",
									"description": "A list of on-wiki pages containing JavaScript that should be loaded",
									"items": {
										"type": "string"
									}
								},
								"styles": {
									"type": "array",
									"description": "A list of on-wiki pages containing CSS that should be loaded",
									"items": {
										"type": "string"
									}
								}
							}
						},
						{
							"description": "A ResourceLoaderImageModule definition",
							"additionalProperties": false,
							"properties": {
								"class": {
									"enum": ["ResourceLoaderImageModule"]
								},
								"data": {
									"type": "string"
								},
								"prefix": {
									"type": "string"
								},
								"selector": {
									"type": "string"
								},
								"selectorWithoutVariant": {
									"type": "string"
								},
								"selectorWithVariant": {
									"type": "string"
								},
								"variants": {
									"type": "object"
								},
								"images": {
									"type": "object"
								},
								"position": {
									"enum": [
										"top",
										"bottom"
									]
								}
							}
						},
						{
							"description": "An arbitrary ResourceLoaderModule definition by class",
							"properties": {
								"class": {
									"type": "string",
									"pattern": "^((?!ResourceLoader(File|Image)Module).)*$"
								}
							},
							"required": ["class"]
						},
						{
							"description": "An arbitrary ResourceLoaderModule definition with instantiator",
							"properties": {
								"factory": {
									"type": "string",
									"description": "A static instantiator function for creating the ResourceLoaderModule object."
								}
							},
							"required": ["factory"]
						}
					]
				}
			}
		},
		"ResourceModuleSkinStyles": {
			"type": "object",
			"description": "ResourceLoader modules for custom skin styles"
		},
		"ResourceLoaderSources": {
			"type": "object",
			"description": "ResourceLoader sources to register"
		},
		"ResourceLoaderLESSVars": {
			"type": "object",
			"description": "ResourceLoader LESS variables"
		},
		"ConfigRegistry": {
			"type": "object",
			"description": "Registry of factory functions to create Config objects"
		},
		"SessionProviders": {
			"type": "object",
			"description": "Session providers"
		},
		"AuthManagerAutoConfig": {
			"type": "object",
			"description": "AuthManager auto-configuration",
			"additionalProperties": false,
			"properties": {
				"preauth": {
					"type": "object",
					"description": "Pre-authentication providers"
				},
				"primaryauth": {
					"type": "object",
					"description": "Primary authentication providers"
				},
				"secondaryauth": {
					"type": "object",
					"description": "Secondary authentication providers"
				}
			}
		},
		"CentralIdLookupProviders": {
			"type": "object",
			"description": "Central ID lookup providers"
		},
		"ChangeCredentialsBlacklist": {
			"type": "object",
			"description": "AuthenticationRequest classes which can only be used internally for credentials change"
		},
		"RemoveCredentialsBlacklist": {
			"type": "object",
			"description": "AuthenticationRequest classes which can only be used internally for credentials removal"
		},
		"namespaces": {
			"type": "array",
			"description": "Method to add extra namespaces",
			"items": {
				"type": "object",
				"properties": {
					"id": {
						"type": "integer"
					},
					"constant": {
						"type": "string"
					},
					"name": {
						"type": "string"
					},
					"gender": {
						"type": "object",
						"properties": {
							"male": {
								"type": "string"
							},
							"female": {
								"type": "string"
							}
						}
					},
					"subpages": {
						"type": "boolean",
						"default": false
					},
					"content": {
						"type": "boolean",
						"default": false
					},
					"defaultcontentmodel": {
						"type": "string"
					},
					"protection": {
						"type": ["string", "array"],
						"description": "Userright(s) required to edit in this namespace"
					},
					"capitallinkoverride": {
						"type": "boolean",
						"description": "Set $wgCapitalLinks on a per-namespace basis"
					},
					"conditional": {
						"type": "boolean",
						"description": "Whether the namespace is conditional upon configuration and should not be registered (requires separate registration via a hook)",
						"default": false
					}
				},
				"required": ["id", "constant", "name"]
			}
		},
		"TrackingCategories": {
			"type": "array",
			"description": "Tracking category message keys",
			"items": {
				"type": "string"
			}
		},
		"DefaultUserOptions": {
			"type": "object",
			"description": "Default values of user options"
		},
		"HiddenPrefs": {
			"type": "array",
			"description": "Preferences users cannot set",
			"items": {
				"type": "string"
			}
		},
		"GroupPermissions": {
			"type": "object",
			"description": "Default permissions to give to user groups",
			"patternProperties": {
				"^[a-z]+$": {
					"type": "object",
					"patternProperties": {
						"^[a-z]+$": {
							"type": "boolean"
						}
					}
				}
			}
		},
		"RevokePermissions": {
			"type": "object",
			"description": "Default permissions to revoke from user groups",
			"patternProperties": {
				"^[a-z]+$": {
					"type": "object",
					"patternProperties": {
						"^[a-z]+$": {
							"type": "boolean"
						}
					}
				}
			}
		},
		"GrantPermissions": {
			"type": "object",
			"description": "Map of permissions granted to authorized consumers to their bundles, called 'grants'",
			"patternProperties": {
				"^[a-z]+$": {
					"type": "object",
					"patternProperties": {
						"^[a-z]+$": {
							"type": "boolean"
						}
					}
				}
			}
		},
		"GrantPermissionGroups": {
			"type": "object",
			"description": "Map of grants to their UI grouping",
			"patternProperties": {
				"^[a-z]+$": {
					"type": "string"
				}
			}
		},
		"ImplicitGroups": {
			"type": "array",
			"description": "Implicit groups"
		},
		"GroupsAddToSelf": {
			"type": "object",
			"description": "Groups a user can add to themselves"
		},
		"GroupsRemoveFromSelf": {
			"type": "object",
			"description": "Groups a user can remove from themselves"
		},
		"AddGroups": {
			"type": "object",
			"description": "Groups a user can add to users"
		},
		"RemoveGroups": {
			"type": "object",
			"description": "Groups a user can remove from users"
		},
		"AvailableRights": {
			"type": "array",
			"description": "User rights added by the extension",
			"items": {
				"type": "string"
			}
		},
		"ContentHandlers": {
			"type": "object",
			"description": "Mapping of model ID to class name",
			"patternProperties": {
				"^[A-Za-z]+$": {
					"type": "string"
				}
			}
		},
		"RateLimits": {
			"type": "object",
			"description": "Rate limits"
		},
		"RecentChangesFlags": {
			"type": "object",
			"description": "Flags (letter symbols) shown on RecentChanges pages"
		},
		"MediaHandlers": {
			"type": "object",
			"description": "Plugins for media file type handling. Each entry in the array maps a MIME type to a PHP class name."
		},
		"ExtensionFunctions": {
			"type": [
				"array",
				"string"
			],
			"description": "Function to call after setup has finished",
			"items": {
				"type": "string"
			}
		},
		"ExtensionMessagesFiles": {
			"type": "object",
			"description": "File paths containing PHP internationalization data"
		},
		"MessagesDirs": {
			"type": "object",
			"description": "Directory paths containing JSON internationalization data"
		},
		"ExtensionEntryPointListFiles": {
			"type": "object"
		},
		"SpecialPages": {
			"type": "object",
			"description": "SpecialPages implemented in this extension (mapping of page name to class name)"
		},
		"AutoloadClasses": {
			"type": "object"
		},
		"Hooks": {
			"type": [ "string", "object" ],
			"description": "Hooks this extension uses (mapping of hook name to callback)"
		},
		"JobClasses": {
			"type": "object",
			"description": "Job types this extension implements (mapping of job type to class name or factory function)"
		},
		"LogTypes": {
			"type": "array",
			"description": "List of new log types this extension uses"
		},
		"LogRestrictions": {
			"type": "object"
		},
		"FilterLogTypes": {
			"type": "object"
		},
		"ActionFilteredLogs": {
			"type": "object",
			"description": "List of log types which can be filtered by log actions",
			"patternProperties": {
				"^[a-z-]+$": {
					"type": "object",
					"patternProperties": {
						"^[a-z-]+$": {
							"type": "array",
							"items": {
								"type": "string"
							}
						}
					}
				}
			}
		},
		"LogNames": {
			"type": "object"
		},
		"LogHeaders": {
			"type": "object"
		},
		"LogActions": {
			"type": "object"
		},
		"LogActionsHandlers": {
			"type": "object"
		},
		"Actions": {
			"type": "object"
		},
		"APIModules": {
			"type": "object"
		},
		"APIFormatModules": {
			"type": "object"
		},
		"APIMetaModules": {
			"type": "object"
		},
		"APIPropModules": {
			"type": "object"
		},
		"APIListModules": {
			"type": "object"
		},
		"ValidSkinNames": {
			"type": "object"
		},
		"FeedClasses": {
			"type": "object",
			"description": "Available feeds objects"
		},
		"SkinOOUIThemes": {
			"type": "object",
			"description": "Map of skin names to OOjs UI themes to use. Same format as ResourceLoaderOOUIModule::$builtinSkinThemeMap."
		},
		"PasswordPolicy": {
			"type": "object",
			"description": "Password policies"
		},
		"FileExtensions": {
			"type": "array",
			"description": "Preferred file extensions for uploading",
			"items": {
				"type": "string"
			}
		},
		"callback": {
			"type": [
				"array",
				"string"
			],
			"description": "A function to be called right after MediaWiki processes this file"
		},
		"config_prefix": {
			"type": "string",
			"default": "wg",
			"description": "Prefix to put in front of configuration settings when exporting them to $GLOBALS"
		},
		"config": {
			"type": "object",
			"description": "Configuration options for this extension",
			"patternProperties": {
				"^[a-zA-Z_\u007f-\u00ff][a-zA-Z0-9_\u007f-\u00ff]*$": {
					"type": "object",
					"properties": {
						"value": {
							"required": true
						},
						"merge_strategy": {
							"type": "string",
							"enum": [
								"array_merge_recursive",
								"array_replace_recursive",
								"array_plus_2d",
								"array_plus",
								"array_merge"
							],
							"default": "array_merge"
						},
						"path": {
							"description": "Whether this should be interpreted as a filesystem path, relative to extension directory root",
							"type": "boolean",
							"default": false
						},
						"description": {
							"type": ["string", "array"],
							"description": "A description of the config setting, mostly for documentation/developers"
						},
						"decriptionmsg": {
							"type": "string",
							"description": "The message key which should be used as a description for this configuration option in a user interface. If empty, description will be used."
						},
						"public": {
							"type": "boolean",
							"default": false,
							"description": "Whether this configuration option and its value is allowed to be revealed in public or not."
						}
					}
				}
			}
		},
		"ParserTestFiles": {
			"type": "array",
			"description": "Parser test suite files to be run by parserTests.php when no specific filename is passed to it"
		},
		"ServiceWiringFiles": {
			"type": "array",
			"description": "List of service wiring files to be loaded by the default instance of MediaWikiServices"
		},
		"attributes": {
			"description":"Registration information for other extensions",
			"type": "object",
			"patternProperties": {
				".*": {
					"type": "object",
					"patternProperties": {
						".*": {
							"type": ["array", "object"]
						}
					}
				}
			}
		},
		"load_composer_autoloader": {
			"type": "boolean",
			"description": "Load the composer autoloader for this extension, if one is present"
		}
	}
}
