jenkins-bot has submitted this change and it was merged. Change subject: Semiautomatically compare and synchronise JS and PHP docs ......................................................................
Semiautomatically compare and synchronise JS and PHP docs I wrote two Ruby scripts to compare the documentation, reviewed their output and tweaked all of the files to match as well as possible. I intend to use them further to generate some data for unit testing. == docparser.rb == A quick documentation parser for our JS and PHP code, mostly compatible with JSDuck and Doxygen syntaxes we use. Generates a JSON file containing most of the interesting information for a set of files. Run with -h for usage instructions and examples. It has pretty much no error handling, so please write the docs correctly ;) Some of the syntax errors I found running it are fixed in previous commit I50fd658b, probably some more in this one. * Supported keywords: constructor, class, method, property, var, event, extends, mixins, param, cfg, return, private, static, ignore * Unsupported keywords: abstract, inheritable, deprecated, singleton, throws, chainable, fires, localdoc, inheritdoc == doccomparer.rb == A quick documentation comparison tool for our JS and PHP code, using docparser.rb. Generates a pretty-printed comparison of documentation for two sets of files. Run with -h for usage instructions and examples. Includes some hacks to lower the number of false positives where JS and PHP language features, inheritance hierarchy or doc format capabilities differ. (See #smart_compare_process and #sanitize_description.) Example output snippet: FieldLayout: JS/PHP Basic: Methods: #constructor: MISMATCH config: MISMATCH help: PHP missing onFieldDisable: PHP missing onLabelClick: PHP missing Properties: align: JS missing So FieldLayout is missing documentation for the 'help' configuration option in PHP (which is unimplemented right now), several event-handling methods in PHP, and the 'align' property (we don't have JS non-static properties documented at all right now). One notable issue is that having a static and non-static property with the same name is not handled, and several JS classes depend on that. We should probably avoid it, as it's not allowed in PHP. Bug: 72455 Change-Id: If9115dd5ac5dc7fb355abd03bb016a436eb3fca1 --- A bin/doccomparer.rb A bin/docparser.rb M php/OoUiElement.php M php/OoUiLayout.php M php/OoUiTheme.php M php/OoUiWidget.php M php/elements/OoUiButtonElement.php M php/elements/OoUiFlaggedElement.php M php/elements/OoUiGroupElement.php M php/elements/OoUiIconElement.php M php/elements/OoUiIndicatorElement.php M php/elements/OoUiLabelElement.php M php/elements/OoUiTitledElement.php M php/layouts/OoUiFieldLayout.php M php/layouts/OoUiFieldsetLayout.php M php/layouts/OoUiFormLayout.php M php/layouts/OoUiGridLayout.php M php/layouts/OoUiPanelLayout.php M php/themes/OoUiMediaWikiTheme.php M php/widgets/OoUiButtonGroupWidget.php M php/widgets/OoUiButtonInputWidget.php M php/widgets/OoUiButtonWidget.php M php/widgets/OoUiCheckboxInputWidget.php M php/widgets/OoUiIconWidget.php M php/widgets/OoUiIndicatorWidget.php M php/widgets/OoUiInputWidget.php M php/widgets/OoUiLabelWidget.php M php/widgets/OoUiTextInputWidget.php M src/Element.js M src/Theme.js M src/elements/ButtonElement.js M src/elements/FlaggedElement.js M src/elements/GroupElement.js M src/elements/IconElement.js M src/elements/IndicatorElement.js M src/elements/LabelElement.js M src/elements/TitledElement.js M src/layouts/FieldLayout.js M src/layouts/FieldsetLayout.js M src/themes/mediawiki/MediaWikiTheme.js M src/widgets/ButtonGroupWidget.js M src/widgets/ButtonInputWidget.js M src/widgets/CheckboxInputWidget.js M src/widgets/InputWidget.js M src/widgets/TextInputWidget.js 45 files changed, 587 insertions(+), 127 deletions(-) Approvals: Trevor Parscal: Looks good to me, approved jenkins-bot: Verified diff --git a/bin/doccomparer.rb b/bin/doccomparer.rb new file mode 100644 index 0000000..da1c7c9 --- /dev/null +++ b/bin/doccomparer.rb @@ -0,0 +1,156 @@ +require 'pp' +require_relative 'docparser' + +# convert [ {name: 'foo'}, … ] to { foo: {name: 'foo'}, … } +def reindex arg + if arg.is_a?(Array) && arg.all?{|v| v.is_a? Hash } + Hash[ arg.map{|v| [ v[:name], reindex(v) ] } ] + elsif arg.is_a? Hash + arg.each_pair{|k, v| arg[k] = reindex(v) } + else + arg + end +end + +def indent text, tabs + text == '' ? text : text.gsub(/^/, ' '*tabs) +end + +# whitespace-insensitive strings +def canonicalize value + if value.is_a? String + value.strip.gsub(/\s+/, ' ') + elsif value.is_a? Array + value.map{|v| canonicalize v } + elsif value.is_a? Hash + value.each_pair{|k, v| value[k] = canonicalize v } + else + value + end +end + +def sanitize_description text + cleanup_class_name(text) + .gsub('null and undefined', 'null') + .gsub('undefined and null', 'null') + .gsub('array()', '[]') + .gsub('jQuery|string|Function', 'string') + .gsub('string|Function', 'string') + .gsub('object', 'array') + .gsub(/#(\w+)/, '\1()') +end + +def smart_compare_process val, type + val[:description] = sanitize_description val[:description] + + case type + when :class + val = val.dup + val[:mixins].delete 'OO.EventEmitter' # JS only + val[:mixins].delete 'PendingElement' # JS only + val.delete :parent if val[:parent] == 'ElementMixin' # PHP only + val.delete :methods + val.delete :properties + val.delete :events + + when :method + if val[:name] == '#constructor' + val[:params].delete 'element' # PHP only + end + val[:config].each_pair{|k, v| + default = v.delete :default + v[:description] << " (default: #{default})" if default + v[:description] = sanitize_description v[:description] + v[:type] = sanitize_description v[:type] + } + val[:params].each_pair{|k, v| + default = v.delete :default + v[:description] << " (default: #{default})" if default + v[:description] = sanitize_description v[:description] + v[:type] = sanitize_description v[:type] + } + + when :property + val[:description] = sanitize_description val[:description] + val[:type] = sanitize_description val[:type] + + end + val +end + +def smart_compare a, b, a_name, b_name, type + a = smart_compare_process a, type + b = smart_compare_process b, type + compare_hash a, b, a_name, b_name +end + +def smart_compare_methods a, b, a_name, b_name + smart_compare a, b, a_name, b_name, :method +end +def smart_compare_properties a, b, a_name, b_name + smart_compare a, b, a_name, b_name, :property +end + +def compare_hash a, b, a_name, b_name, nested=:compare_hash + keys = (a ? a.keys: []) + (b ? b.keys : []) + out = keys.to_a.sort.uniq.map do |key| + a_val = a ? canonicalize(a[key]) : nil + b_val = b ? canonicalize(b[key]) : nil + + if [a_val, b_val] == [{}, []] || [a_val, b_val] == [[], {}] + a_val, b_val = {}, {} + end + + if a_val.is_a? Hash and b_val.is_a? Hash + comparison_result = indent method(nested).call(a_val, b_val, a_name, b_name), 2 + if comparison_result.strip == '' + "#{key}: match" if $VERBOSE + else + "#{key}: MISMATCH\n#{comparison_result}" + end + else + if a_val == b_val + "#{key}: match" if $VERBOSE + elsif a_val == nil + "#{key}: #{a_name} missing" + elsif b_val == nil + "#{key}: #{b_name} missing" + else + "#{key}: MISMATCH\n #{a_name}: #{a_val.inspect}\n #{b_name}: #{b_val.inspect}" + end + end + end + out.compact.join "\n" +end + + +if ARGV.empty? || ARGV == ['-h'] || ARGV == ['--help'] + $stderr.puts "usage: ruby [-v] #{$0} <dirA> <dirB> <nameA> <nameB>" + $stderr.puts " ruby #{$0} src php JS PHP > compare.txt" +else + dir_a, dir_b, name_a, name_b = ARGV + + js = parse_any_path dir_a + php = parse_any_path dir_b + + js = reindex js + php = reindex php + + (js.keys + php.keys).sort.uniq.each do |class_name| + where = [js.key?(class_name) ? name_a : nil, php.key?(class_name) ? name_b : nil].compact + puts "\n#{class_name}: #{where.join '/'}" if $VERBOSE || where.length == 2 + + if where.length == 2 + data = [ + "Basic:", + ( indent smart_compare(js[class_name], php[class_name], name_a, name_b, :class), 2 ), + "Methods:", + ( indent compare_hash(js[class_name][:methods], php[class_name][:methods], name_a, name_b, :smart_compare_methods), 2 ), + "Properties:", + ( indent compare_hash(js[class_name][:properties], php[class_name][:properties], name_a, name_b, :smart_compare_properties), 2 ), + ] + puts indent data.select{|d| d != ''}.join("\n"), 2 + end + end +end + diff --git a/bin/docparser.rb b/bin/docparser.rb new file mode 100644 index 0000000..db83248 --- /dev/null +++ b/bin/docparser.rb @@ -0,0 +1,232 @@ +require 'pp' +require 'json' + +def parse_dir dirname + Dir.entries(dirname).map{|filename| + if filename == '.' || filename == '..' + nil + else + parse_any_path "#{dirname}/#{filename}" + end + }.compact.inject(:+) +end + +def cleanup_class_name class_name + class_name.sub(/OoUi/, '').sub(/OO\.ui\./, '') +end + +def parse_file filename + if filename !~ /\.(php|js)$/ + return nil + end + filetype = filename[/\.(php|js)$/, 1].to_sym + + text = File.read filename, encoding: 'utf-8' + + # ewwww + # some docblocks are missing and we really need them + text = text.sub(/(?<!\*\/\n)^class/, "/**\n*/\nclass") + # text = text.sub('public static $targetPropertyName', "/**\n*/\npublic static $targetPropertyName") + + # find all documentation blocks, together with the following line (unless it contains another docblock) + docblocks = text.scan(/\/\*\*[\s\S]+?\*\/\n[ \t]*(?:(?=\/\*\*)|.*)/) + + current_class = nil + output = [] + previous_item = {} # dummy + + docblocks.map{|d| + kind = nil + previous_item = data = { + name: nil, + description: '', + parent: nil, + mixins: [], + methods: [], + properties: [], + events: [], + params: [], + config: [], + visibility: :public, + type: nil, + # static: false, # unnecessary, skip it + } + valid_for_all = %I[name description] + valid_per_kind = { + class: valid_for_all + %I[parent mixins methods properties events], + method: valid_for_all + %I[params config return visibility static], + property: valid_for_all + %I[type static], + event: valid_for_all + %I[params], + } + + js_class_constructor = false + js_class_constructor_desc = '' + ignore = false + + comment, code_line = d.split '*/' + comment.split("\n").each{|c| + next if c.strip == '/**' + c.sub!(/^[ \t]*\*[ \t]?/, '') # strip leading * + + m = c.match(/^@(\w+)[ \t]*(.*)/) + if !m + previous_item[:description] << c + "\n" + next + end + + keyword, content = m.captures + + # handle JS class/constructor conundrum + if keyword == 'class' || keyword == 'constructor' + js_class_constructor = true + end + + case keyword + when 'constructor' + # handle JS class/constructor conundrum + js_class_constructor_desc = data[:description] + data[:description] = '' + kind = :method + when 'class' + kind = :class + when 'method' + kind = :method + when 'property', 'var' + kind = :property + m = content.match(/^\{?(.+?)\}?( .+)?$/) + if m.captures + type, description = m.captures + data[:type] = type + data[:description] = description if description + end + when 'event' + kind = :event + data[:name] = content.strip + when 'extends' + data[:parent] = cleanup_class_name(content.strip) + when 'mixins' + data[:mixins] << cleanup_class_name(content.strip) + when 'param' + case filetype + when :js + type, name, default, description = content.match(/^\{(.+?)\} \[?([\w.$]+?)(?:=(.+?))?\]?( .+)?$/).captures + next if type == 'Object' && name == 'config' + data[:params] << {name: name, type: cleanup_class_name(type), description: description||'', default: default} + previous_item = data[:params][-1] + when :php + type, name, config, description = content.match(/^(\S+) \$(\w+)(?:\['(\w+)'\])?( .+)?$/).captures + next if type == 'array' && name == 'config' && !config + if config && name == 'config' + data[:config] << {name: config, type: cleanup_class_name(type), description: description||''} + previous_item = data[:config][-1] + else + data[:params] << {name: name, type: cleanup_class_name(type), description: description||''} + previous_item = data[:params][-1] + end + end + when 'cfg' # JS only + type, name, default, description = content.match(/^\{(.+?)\} \[?([\w.$]+?)(?:=(.+?))?\]?( .+)?$/).captures + data[:config] << {name: name, type: cleanup_class_name(type), description: description||'', default: default} + previous_item = data[:config][-1] + when 'return' + case filetype + when :js + type, description = content.match(/^\{(.+?)\}( .+)?$/).captures + data[:return] = {type: cleanup_class_name(type), description: description||''} + previous_item = data[:return] + when :php + type, description = content.match(/^(\S+)( .+)?$/).captures + data[:return] = {type: cleanup_class_name(type), description: description||''} + previous_item = data[:return] + end + when 'private' + data[:visibility] = :private + when 'static' + data[:static] = true + when 'ignore' + ignore = true + when 'abstract', 'inheritable', 'deprecated', 'singleton', 'throws', 'chainable', 'fires', 'localdoc', 'inheritdoc' + # skip + else + raise "unrecognized keyword: #{keyword}" + end + } + + next if ignore + + if code_line && code_line.strip != '' + case filetype + when :js + m = code_line.match(/(?:(static|prototype)\.)?(\w+) = /) + kind_, name = m.captures + data[:static] = true if kind_ == 'static' + kind = {'static' => :property, 'prototype' => :method}[ kind_.strip ] if kind_ && !kind + data[:name] = cleanup_class_name(name) + when :php + m = code_line.match(/\s*(?:(public|protected|private) )?(?:(static) )?(function[ \t]|class[ \t]|\$)(\w+)(?: extends (\w+))?/) + visibility, static, kind_, name, parent = m.captures + kind = {'$' => :property, 'function' => :method, 'class' => :class}[ kind_.strip ] + data[:visibility] = {'private' => :private, 'protected' => :private, 'public' => :public}[ visibility ] || :public + data[:static] = true if static + data[:parent] = cleanup_class_name(parent) if parent + data[:name] = cleanup_class_name(name) + end + end + + # handle JS class/constructor conundrum + if kind == :class || js_class_constructor + if current_class + output << current_class + end + current_class = data.select{|k,v| valid_per_kind[:class].include? k } + current_class[:description] = js_class_constructor_desc if js_class_constructor_desc != '' + previous_item = current_class + end + + # standardize + if data[:name] == '__construct' || js_class_constructor + data[:name] = '#constructor' + end + + # put into the current class + if kind && kind != :class + keys = { + method: :methods, + property: :properties, + event: :events, + } + current_class[keys[kind]] << data.select{|k,v| valid_per_kind[kind].include? k } + previous_item = current_class[keys[kind]] + end + } + + # this is evil, assumes we only have one class in a file, but we'd need a proper parser to do it better + if current_class + current_class[:mixins] += + text.scan(/\$this->mixin\( .*?new (\w+)\( \$this/).flatten.map(&method(:cleanup_class_name)) + end + + output << current_class if current_class + output +end + +def parse_any_path path + if File.directory? path + parse_dir path + else + parse_file path + end +end + +if __FILE__ == $0 + if ARGV.empty? || ARGV == ['-h'] || ARGV == ['--help'] + $stderr.puts "usage: ruby #{$0} <files...>" + $stderr.puts " ruby #{$0} src > docs-js.json" + $stderr.puts " ruby #{$0} php > docs-php.json" + else + out = JSON.pretty_generate ARGV.map{|a| parse_any_path a }.inject(:+) + # ew + out = out.gsub(/\{\s+\}/, '{}').gsub(/\[\s+\]/, '[]') + puts out + end +end diff --git a/php/OoUiElement.php b/php/OoUiElement.php index 6ee02c9..65fda51 100644 --- a/php/OoUiElement.php +++ b/php/OoUiElement.php @@ -1,5 +1,8 @@ <?php +/** + * DOM element abstraction. + */ class OoUiElement extends OoUiTag { /* Static properties */ @@ -25,10 +28,8 @@ /* Methods */ /** - * Create element. - * * @param array $config Configuration options - * @param array $config['classes'] CSS class names to add + * @param string[] $config['classes'] CSS class names to add * @param array $config['content'] Content to append, text or OoUiElement objects */ public function __construct( array $config = array() ) { @@ -105,9 +106,9 @@ } /** - * Check if element or a mixin supports a method. + * Check if element supports one or more methods. * - * @param string|array $method Method to check + * @param string|string[] $methods Method or list of methods to check * @return boolean Method is supported */ public function supports( $methods ) { diff --git a/php/OoUiLayout.php b/php/OoUiLayout.php index 9e36f37..7159076 100644 --- a/php/OoUiLayout.php +++ b/php/OoUiLayout.php @@ -1,9 +1,10 @@ <?php +/** + * Container for elements. + */ class OoUiLayout extends OoUiElement { /** - * Create layout. - * * @param array $config Configuration options */ public function __construct( array $config = array() ) { diff --git a/php/OoUiTheme.php b/php/OoUiTheme.php index 4db4c2a..f4efd51 100644 --- a/php/OoUiTheme.php +++ b/php/OoUiTheme.php @@ -1,5 +1,8 @@ <?php +/** + * Theme logic. + */ class OoUiTheme { /* Members */ @@ -23,8 +26,8 @@ /** * Get a list of classes to be applied to a widget. * - * @localdoc The 'on' and 'off' lists combined MUST contain keys for all classes the theme adds or - * removes, otherwise state transitions will not work properly. + * The 'on' and 'off' lists combined MUST contain keys for all classes the theme adds or removes, + * otherwise state transitions will not work properly. * * @param OoUiElement $element Element for which to get classes * @return array Categorized class names with `on` and `off` lists diff --git a/php/OoUiWidget.php b/php/OoUiWidget.php index c412146..0ac745b 100644 --- a/php/OoUiWidget.php +++ b/php/OoUiWidget.php @@ -1,5 +1,8 @@ <?php +/** + * User interface control. + */ class OoUiWidget extends OoUiElement { /* Properties */ @@ -14,9 +17,8 @@ /* Methods */ /** - * Create widget. - * * @param array $config Configuration options + * @param boolean $config['disabled'] Disable (default: false) */ public function __construct( array $config = array() ) { // Initialize config diff --git a/php/elements/OoUiButtonElement.php b/php/elements/OoUiButtonElement.php index 058273e..26a4bf6 100644 --- a/php/elements/OoUiButtonElement.php +++ b/php/elements/OoUiButtonElement.php @@ -1,5 +1,11 @@ <?php +/** + * Element with a button. + * + * Buttons are used for controls which can be clicked. They can be configured to use tab indexing + * and access keys for accessibility purposes. + */ class OoUiButtonElement extends OoUiElementMixin { /** * Button is framed. @@ -11,12 +17,11 @@ public static $targetPropertyName = 'button'; /** - * Mixin button element. - * * @param OoUiElement $element Element being mixed into * @param array $config Configuration options - * @param boolean $config['framed'] Render button with a frame - * @param number $config['tabIndex'] Button's tab index, use -1 to prevent tab focusing + * @param boolean $config['framed'] Render button with a frame (default: true) + * @param number $config['tabIndex'] Button's tab index. Use 0 to use default ordering, use -1 to + * prevent tab focusing. (default: 0) */ public function __construct( OoUiElement $element, array $config = array() ) { // Parent constructor @@ -47,7 +52,7 @@ } /** - * Check if button is framed. + * Check if button has a frame. * * @return boolean Button is framed */ diff --git a/php/elements/OoUiFlaggedElement.php b/php/elements/OoUiFlaggedElement.php index 6f297ef..d81429d 100644 --- a/php/elements/OoUiFlaggedElement.php +++ b/php/elements/OoUiFlaggedElement.php @@ -1,5 +1,11 @@ <?php +/** + * Element with named flags that can be added, removed, listed and checked. + * + * A flag, when set, adds a CSS class on the `$element` by combining `oo-ui-flaggedElement-` with + * the flag name. Flags are primarily useful for styling. + */ class OoUiFlaggedElement extends OoUiElementMixin { /** * Flags. @@ -11,11 +17,10 @@ public static $targetPropertyName = 'flagged'; /** - * Mixin flagged element. - * * @param OoUiElement $element Element being mixed into * @param array $config Configuration options - * @param string|string[] $config['flags'] Flags + * @param string|string[] $config['flags'] Styling flags, e.g. 'primary', 'destructive' or + * 'constructive' */ public function __construct( OoUiElement $element, array $config = array() ) { // Parent constructor diff --git a/php/elements/OoUiGroupElement.php b/php/elements/OoUiGroupElement.php index 2a068f6..a798d93 100644 --- a/php/elements/OoUiGroupElement.php +++ b/php/elements/OoUiGroupElement.php @@ -1,5 +1,8 @@ <?php +/** + * Element containing a sequence of child elements. + */ class OoUiGroupElement extends OoUiElementMixin { /** * List of items in the group. @@ -11,8 +14,6 @@ public static $targetPropertyName = 'group'; /** - * Element containing a sequence of child elements. - * * @param OoUiElement $element Element being mixed into * @param array $config Configuration options */ @@ -41,7 +42,7 @@ } /** - * Add items at the end. + * Add items. * * Adding an existing item will move it. * diff --git a/php/elements/OoUiIconElement.php b/php/elements/OoUiIconElement.php index 2c591c3..5a22901 100644 --- a/php/elements/OoUiIconElement.php +++ b/php/elements/OoUiIconElement.php @@ -1,8 +1,16 @@ <?php +/** + * Element containing an icon. + * + * Icons are graphics, about the size of normal text. They can be used to aid the user in locating + * a control or convey information in a more space efficient way. Icons should rarely be used + * without labels; such as in a toolbar where space is at a premium or within a context where the + * meaning is very clear to the user. + */ class OoUiIconElement extends OoUiElementMixin { /** - * Icon value. + * Symbolic icon name. * * @var string */ @@ -11,11 +19,9 @@ public static $targetPropertyName = 'icon'; /** - * Mixin icon element. - * * @param OoUiElement $element Element being mixed into * @param array $config Configuration options - * @param string $config['icon'] Icon value + * @param string $config['icon'] Symbolic icon name */ public function __construct( OoUiElement $element, array $config = array() ) { // Parent constructor @@ -29,9 +35,9 @@ } /** - * Set icon value. + * Set icon name. * - * @param string $icon Icon value + * @param string|null $icon Symbolic icon name * @chainable */ public function setIcon( $icon = null ) { @@ -42,9 +48,9 @@ } /** - * Get icon value. + * Get icon name. * - * @return string Icon value + * @return string Icon name */ public function getIcon() { return $this->icon; diff --git a/php/elements/OoUiIndicatorElement.php b/php/elements/OoUiIndicatorElement.php index 5017267..c7ae701 100644 --- a/php/elements/OoUiIndicatorElement.php +++ b/php/elements/OoUiIndicatorElement.php @@ -1,21 +1,27 @@ <?php +/** + * Element containing an indicator. + * + * Indicators are graphics, smaller than normal text. They can be used to describe unique status or + * behavior. Indicators should only be used in exceptional cases; such as a button that opens a menu + * instead of performing an action directly, or an item in a list which has errors that need to be + * resolved. + */ class OoUiIndicatorElement extends OoUiElementMixin { /** - * Indicator value. + * Symbolic indicator name * - * @var string + * @var string|null */ protected $indicator = null; public static $targetPropertyName = 'indicator'; /** - * Mixin indicator element. - * * @param OoUiElement $element Element being mixed into * @param array $config Configuration options - * @param string $config['indicator'] Indicator value + * @param string $config['indicator'] Symbolic indicator name */ public function __construct( OoUiElement $element, array $config = array() ) { // Parent constructor @@ -31,9 +37,9 @@ } /** - * Set indicator value. + * Set indicator name. * - * @param string $indicator Indicator value + * @param string|null $indicator Symbolic name of indicator to use or null for no indicator * @chainable */ public function setIndicator( $indicator = null ) { @@ -44,9 +50,9 @@ } /** - * Get indicator value. + * Get indicator name. * - * @return string Indicator value + * @return string Indicator name */ public function getIndicator() { return $this->indicator; diff --git a/php/elements/OoUiLabelElement.php b/php/elements/OoUiLabelElement.php index 8659032..627e5bb 100644 --- a/php/elements/OoUiLabelElement.php +++ b/php/elements/OoUiLabelElement.php @@ -1,21 +1,22 @@ <?php +/** + * Element containing a label. + */ class OoUiLabelElement extends OoUiElementMixin { /** * Label value. * - * @var string + * @var string|null */ - protected $label; + protected $label = null; public static $targetPropertyName = 'label'; /** - * Mixin label element. - * * @param OoUiElement $element Element being mixed into * @param array $config Configuration options - * @param string $config['label'] Label value + * @param string $config['label'] Label text */ public function __construct( OoUiElement $element, array $config = array() ) { // Parent constructor @@ -29,9 +30,11 @@ } /** - * Set label value. + * Set the label. * - * @param string $label Label value + * An empty string will result in the label being hidden. + * + * @param string|null $label Label text * @chainable */ public function setLabel( $label ) { @@ -45,9 +48,9 @@ } /** - * Get label value. + * Get the label. * - * @return string Label value + * @return string Label text */ public function getLabel() { return $this->label; diff --git a/php/elements/OoUiTitledElement.php b/php/elements/OoUiTitledElement.php index d15fa3a..a44af36 100644 --- a/php/elements/OoUiTitledElement.php +++ b/php/elements/OoUiTitledElement.php @@ -1,8 +1,14 @@ <?php +/** + * Element with a title. + * + * Titles are rendered by the browser and are made visible when hovering the element. Titles are + * not visible on touch devices. + */ class OoUiTitledElement extends OoUiElementMixin { /** - * Title. + * Title text. * * @var string */ @@ -11,13 +17,11 @@ public static $targetPropertyName = 'titled'; /** - * Mixin titled element. - * - * If the 'title' config option is not provided, the static property '$title' of $element is used. + * * * @param OoUiElement $element Element being mixed into * @param array $config Configuration options - * @param string $config['title'] Title + * @param string $config['title'] Title. If not provided, the static property 'title' is used. */ public function __construct( OoUiElement $element, array $config = array() ) { // Parent constructor @@ -32,7 +36,7 @@ } /** - * Add one or more flags. + * Set title. * * @param string|null $title Title text or null for no title * @chainable diff --git a/php/layouts/OoUiFieldLayout.php b/php/layouts/OoUiFieldLayout.php index 594bf3e..ce48de6 100644 --- a/php/layouts/OoUiFieldLayout.php +++ b/php/layouts/OoUiFieldLayout.php @@ -1,5 +1,18 @@ <?php +/** + * Layout made of a field and optional label. + * + * Available label alignment modes include: + * - left: Label is before the field and aligned away from it, best for when the user will be + * scanning for a specific label in a form with many fields + * - right: Label is before the field and aligned toward it, best for forms the user is very + * familiar with and will tab through field checking quickly to verify which field they are in + * - top: Label is before the field and above it, best for when the user will need to fill out all + * fields from top to bottom in a form with few fields + * - inline: Label is after the field and aligned toward it, best for small boolean fields like + * checkboxes or radio buttons + */ class OoUiFieldLayout extends OoUiLayout { /** * Alignment. @@ -9,12 +22,10 @@ protected $align; /** - * Create field layout. - * * @param OoUiWidget $fieldWidget Field widget * @param array $config Configuration options * @param string $config['align'] Alignment mode, either 'left', 'right', 'top' or 'inline' - * @param string $config['help'] Explanatory text shown as a '?' icon (not implemented). + * (default: 'left') */ public function __construct( OoUiWidget $fieldWidget, array $config = array() ) { // Config initialization @@ -26,7 +37,7 @@ // Properties $this->field = new OoUiTag( 'div' ); $this->fieldWidget = $fieldWidget; - $this->help = ""; // TODO implement + $this->help = ''; // TODO implement // Mixins $this->mixin( new OoUiLabelElement( $this, $config ) ); diff --git a/php/layouts/OoUiFieldsetLayout.php b/php/layouts/OoUiFieldsetLayout.php index 1e7b2dd..42953ac 100644 --- a/php/layouts/OoUiFieldsetLayout.php +++ b/php/layouts/OoUiFieldsetLayout.php @@ -1,5 +1,10 @@ <?php +/** + * Layout made of a fieldset and optional legend. + * + * Just add OoUiFieldLayout items. + */ class OoUiFieldsetLayout extends OoUiLayout { /** * Alignment. @@ -9,10 +14,8 @@ protected $align; /** - * Create fieldset layout. - * * @param array $config Configuration options - * @param OoUiFieldLayout $config['items'] Items to add + * @param OoUiFieldLayout[] $config['items'] Items to add */ public function __construct( array $config = array() ) { // Parent constructor diff --git a/php/layouts/OoUiFormLayout.php b/php/layouts/OoUiFormLayout.php index e4c7922..7c42892 100644 --- a/php/layouts/OoUiFormLayout.php +++ b/php/layouts/OoUiFormLayout.php @@ -1,5 +1,8 @@ <?php +/** + * Layout with an HTML form. + */ class OoUiFormLayout extends OoUiLayout { /* Static properties */ @@ -7,8 +10,6 @@ public static $tagName = 'form'; /** - * Create form layout. - * * @param array $config Configuration options * @param string $config['method'] HTML form `method` attribute * @param string $config['action'] HTML form `action` attribute diff --git a/php/layouts/OoUiGridLayout.php b/php/layouts/OoUiGridLayout.php index bd697c6..c093427 100644 --- a/php/layouts/OoUiGridLayout.php +++ b/php/layouts/OoUiGridLayout.php @@ -1,5 +1,8 @@ <?php +/** + * Layout made of proportionally sized columns and rows. + */ class OoUiGridLayout extends OoUiLayout { /* Properties */ @@ -26,8 +29,6 @@ protected $heights = array(); /** - * Create field layout. - * * @param OoUiPanelLayout[] $panels Panels in the grid * @param array $config Configuration options * @param number[] $config['widths'] Widths of columns as ratios diff --git a/php/layouts/OoUiPanelLayout.php b/php/layouts/OoUiPanelLayout.php index 126924f..5d71b52 100644 --- a/php/layouts/OoUiPanelLayout.php +++ b/php/layouts/OoUiPanelLayout.php @@ -1,9 +1,10 @@ <?php +/** + * Layout that expands to cover the entire area of its parent, with optional scrolling and padding. + */ class OoUiPanelLayout extends OoUiLayout { /** - * Create panel layout. - * * @param array $config Configuration options * @param boolean $config['scrollable'] Allow vertical scrolling (default: false) * @param boolean $config['padded'] Pad the content from the edges (default: false) diff --git a/php/themes/OoUiMediaWikiTheme.php b/php/themes/OoUiMediaWikiTheme.php index c83a58c..947275c 100644 --- a/php/themes/OoUiMediaWikiTheme.php +++ b/php/themes/OoUiMediaWikiTheme.php @@ -4,15 +4,6 @@ /* Methods */ - /** - * Get a list of classes to be applied to a widget. - * - * @localdoc The 'on' and 'off' lists combined MUST contain keys for all classes the theme adds or - * removes, otherwise state transitions will not work properly. - * - * @param OoUiElement $element Element for which to get classes - * @return array Categorized class names with `on` and `off` lists - */ public function getElementClasses( OoUiElement $element ) { $variants = array( 'invert' => false, diff --git a/php/widgets/OoUiButtonGroupWidget.php b/php/widgets/OoUiButtonGroupWidget.php index c1d035a..ae8b18d 100644 --- a/php/widgets/OoUiButtonGroupWidget.php +++ b/php/widgets/OoUiButtonGroupWidget.php @@ -1,11 +1,14 @@ <?php +/** + * Group widget for multiple related buttons. + * + * Use together with OoUiButtonWidget. + */ class OoUiButtonGroupWidget extends OoUiWidget { /** - * Create button group widget. - * * @param array $config Configuration options - * @param array $config['items'] Buttons to add + * @param OoUiButtonWidget[] $config['items'] Buttons to add */ public function __construct( array $config = array() ) { // Parent constructor diff --git a/php/widgets/OoUiButtonInputWidget.php b/php/widgets/OoUiButtonInputWidget.php index c42a8d7..87a3746 100644 --- a/php/widgets/OoUiButtonInputWidget.php +++ b/php/widgets/OoUiButtonInputWidget.php @@ -1,9 +1,10 @@ <?php +/** + * A button that is an input widget. Intended to be used within a OoUiFormLayout. + */ class OoUiButtonInputWidget extends OoUiInputWidget { /** - * Create button input widget. - * * @param array $config Configuration options * @param string $config['type'] HTML tag `type` attribute, may be 'button', 'submit' or 'reset' * (default: 'button') @@ -62,7 +63,7 @@ * * Overridden to support setting the 'value' of `<input/>` elements. * - * @param string $label Label value + * @param string|null $label Label text * @chainable */ public function setLabel( $label ) { diff --git a/php/widgets/OoUiButtonWidget.php b/php/widgets/OoUiButtonWidget.php index 3693153..65e7489 100644 --- a/php/widgets/OoUiButtonWidget.php +++ b/php/widgets/OoUiButtonWidget.php @@ -1,5 +1,8 @@ <?php +/** + * Generic widget for buttons. + */ class OoUiButtonWidget extends OoUiWidget { /** @@ -17,9 +20,9 @@ protected $target = null; /** - * Create button widget. - * * @param array $config Configuration options + * @param string $config['href'] Hyperlink to visit when clicked + * @param string $config['target'] Target to open hyperlink in */ public function __construct( array $config = array() ) { // Configuration initialization diff --git a/php/widgets/OoUiCheckboxInputWidget.php b/php/widgets/OoUiCheckboxInputWidget.php index 4c0db6a..ff6bae8 100644 --- a/php/widgets/OoUiCheckboxInputWidget.php +++ b/php/widgets/OoUiCheckboxInputWidget.php @@ -1,10 +1,11 @@ <?php +/** + * Checkbox input widget. + */ class OoUiCheckboxInputWidget extends OoUiInputWidget { /** - * Create checkbox input widget. - * * @param array $config Configuration options */ public function __construct( array $config = array() ) { diff --git a/php/widgets/OoUiIconWidget.php b/php/widgets/OoUiIconWidget.php index 019948f..fcfab87 100644 --- a/php/widgets/OoUiIconWidget.php +++ b/php/widgets/OoUiIconWidget.php @@ -1,5 +1,10 @@ <?php +/** + * Icon widget. + * + * See OoUiIconElement for more information. + */ class OoUiIconWidget extends OoUiWidget { /* Static properties */ @@ -7,8 +12,6 @@ public static $tagName = 'span'; /** - * Create icon widget. - * * @param array $config Configuration options */ public function __construct( array $config = array() ) { diff --git a/php/widgets/OoUiIndicatorWidget.php b/php/widgets/OoUiIndicatorWidget.php index 08b1206..6c6cbf5 100644 --- a/php/widgets/OoUiIndicatorWidget.php +++ b/php/widgets/OoUiIndicatorWidget.php @@ -1,5 +1,10 @@ <?php +/** + * Indicator widget. + * + * See OoUiIndicatorElement for more information. + */ class OoUiIndicatorWidget extends OoUiWidget { /* Static properties */ @@ -7,8 +12,6 @@ public static $tagName = 'span'; /** - * Create indicator widget. - * * @param array $config Configuration options */ public function __construct( array $config = array() ) { diff --git a/php/widgets/OoUiInputWidget.php b/php/widgets/OoUiInputWidget.php index c94a849..2b8c913 100644 --- a/php/widgets/OoUiInputWidget.php +++ b/php/widgets/OoUiInputWidget.php @@ -1,5 +1,8 @@ <?php +/** + * Base class for input widgets. + */ class OoUiInputWidget extends OoUiWidget { /* Properties */ @@ -19,8 +22,6 @@ protected $readOnly = false; /** - * Create input widget. - * * @param array $config Configuration options * @param string $config['name'] HTML input name (default: '') * @param string $config['value'] Input value (default: '') @@ -126,7 +127,8 @@ } /** - * Set the read-only state of the widget. + * Set the read-only state of the widget. This should probably change the widgets's appearance and + * prevent it from being used. * * @param boolean $state Make input read-only * @chainable diff --git a/php/widgets/OoUiLabelWidget.php b/php/widgets/OoUiLabelWidget.php index f3a2033..29e6cc1 100644 --- a/php/widgets/OoUiLabelWidget.php +++ b/php/widgets/OoUiLabelWidget.php @@ -1,5 +1,8 @@ <?php +/** + * Label widget. + */ class OoUiLabelWidget extends OoUiWidget { /* Static properties */ @@ -7,8 +10,6 @@ public static $tagName = 'span'; /** - * Create label widget. - * * @param array $config Configuration options */ public function __construct( array $config = array() ) { diff --git a/php/widgets/OoUiTextInputWidget.php b/php/widgets/OoUiTextInputWidget.php index a343591..80093ea 100644 --- a/php/widgets/OoUiTextInputWidget.php +++ b/php/widgets/OoUiTextInputWidget.php @@ -1,5 +1,8 @@ <?php +/** + * Input widget with a text field. + */ class OoUiTextInputWidget extends OoUiInputWidget { /* Properties */ @@ -12,9 +15,8 @@ protected $multiline = false; /** - * Create text input widget. - * * @param array $config Configuration options + * @param string $config['placeholder'] Placeholder text * @param string $config['type'] HTML tag `type` attribute (default: 'text') * @param boolean $config['multiline'] Allow multiple lines of text (default: false) */ @@ -57,11 +59,11 @@ } /** - * Check if the widget is read-only. + * Check if input supports multiple lines. * * @return boolean */ - public function isMultiLine() { + public function isMultiline() { return (bool)$this->multiline; } } diff --git a/src/Element.js b/src/Element.js index 8a79c9d..93ef8d2 100644 --- a/src/Element.js +++ b/src/Element.js @@ -7,7 +7,7 @@ * @constructor * @param {Object} [config] Configuration options * @cfg {Function} [$] jQuery for the frame the widget is in - * @cfg {string[]} [classes] CSS class names + * @cfg {string[]} [classes] CSS class names to add * @cfg {string} [text] Text to insert * @cfg {jQuery} [$content] Content elements to append (after text) */ @@ -325,7 +325,7 @@ * * @static * @param {HTMLElement} el Element to scroll into view - * @param {Object} [config={}] Configuration config + * @param {Object} [config] Configuration options * @param {string} [config.duration] jQuery animation duration value * @param {string} [config.direction] Scroll in only one direction, e.g. 'x' or 'y', omit * to scroll in both directions @@ -426,7 +426,7 @@ * Check if element supports one or more methods. * * @param {string|string[]} methods Method or list of methods to check - * @return boolean All methods are supported + * @return {boolean} All methods are supported */ OO.ui.Element.prototype.supports = function ( methods ) { var i, len, @@ -531,7 +531,7 @@ /** * Scroll element into view. * - * @param {Object} [config={}] + * @param {Object} [config] Configuration options */ OO.ui.Element.prototype.scrollElementIntoView = function ( config ) { return OO.ui.Element.scrollIntoView( this.$element[0], config ); diff --git a/src/Theme.js b/src/Theme.js index 7f0ab98..bb9bebd 100644 --- a/src/Theme.js +++ b/src/Theme.js @@ -21,8 +21,8 @@ /** * Get a list of classes to be applied to a widget. * - * @localdoc The 'on' and 'off' lists combined MUST contain keys for all classes the theme adds or - * removes, otherwise state transitions will not work properly. + * The 'on' and 'off' lists combined MUST contain keys for all classes the theme adds or removes, + * otherwise state transitions will not work properly. * * @param {OO.ui.Element} element Element for which to get classes * @return {Object.<string,string[]>} Categorized class names with `on` and `off` lists @@ -36,7 +36,7 @@ * * For elements with theme logic hooks, this should be called anytime there's a state change. * - * @param {OO.ui.Element} Element for which to update classes + * @param {OO.ui.Element} element Element for which to update classes * @return {Object.<string,string[]>} Categorized class names with `on` and `off` lists */ OO.ui.Theme.prototype.updateElementClasses = function ( element ) { diff --git a/src/elements/ButtonElement.js b/src/elements/ButtonElement.js index a6d5b1c..58a57a0 100644 --- a/src/elements/ButtonElement.js +++ b/src/elements/ButtonElement.js @@ -11,7 +11,8 @@ * @param {Object} [config] Configuration options * @cfg {jQuery} [$button] Button node, assigned to #$button, omit to use a generated `<a>` * @cfg {boolean} [framed=true] Render button with a frame - * @cfg {number} [tabIndex=0] Button's tab index, use null to have no tabIndex + * @cfg {number} [tabIndex=0] Button's tab index. Use 0 to use default ordering, use -1 to prevent + * tab focusing. * @cfg {string} [accessKey] Button's access key */ OO.ui.ButtonElement = function OoUiButtonElement( config ) { diff --git a/src/elements/FlaggedElement.js b/src/elements/FlaggedElement.js index 7d7eb13..7ad6ee8 100644 --- a/src/elements/FlaggedElement.js +++ b/src/elements/FlaggedElement.js @@ -9,7 +9,7 @@ * * @constructor * @param {Object} [config] Configuration options - * @cfg {string[]} [flags=[]] Styling flags, e.g. 'primary', 'destructive' or 'constructive' + * @cfg {string|string[]} [flags] Styling flags, e.g. 'primary', 'destructive' or 'constructive' * @cfg {jQuery} [$flagged] Flagged node, assigned to #$flagged, omit to use #$element */ OO.ui.FlaggedElement = function OoUiFlaggedElement( config ) { diff --git a/src/elements/GroupElement.js b/src/elements/GroupElement.js index 3017718..1b5e3f8 100644 --- a/src/elements/GroupElement.js +++ b/src/elements/GroupElement.js @@ -113,7 +113,7 @@ /** * Add items. * - * Adding an existing item (by value) will move it. + * Adding an existing item will move it. * * @param {OO.ui.Element[]} items Items * @param {number} [index] Index to insert items at diff --git a/src/elements/IconElement.js b/src/elements/IconElement.js index 79b6a22..832fb3a 100644 --- a/src/elements/IconElement.js +++ b/src/elements/IconElement.js @@ -92,7 +92,7 @@ }; /** - * Set icon. + * Set icon name. * * @param {Object|string|null} icon Symbolic icon name, or map of icon names keyed by language ID; * use the 'default' key to specify the icon to be used when there is no icon in the user's @@ -148,9 +148,9 @@ }; /** - * Get icon. + * Get icon name. * - * @return {string} Icon + * @return {string} Icon name */ OO.ui.IconElement.prototype.getIcon = function () { return this.icon; diff --git a/src/elements/IndicatorElement.js b/src/elements/IndicatorElement.js index 59b80e2..60bee6f 100644 --- a/src/elements/IndicatorElement.js +++ b/src/elements/IndicatorElement.js @@ -42,7 +42,7 @@ * * @static * @inheritable - * @property {string|null} Symbolic indicator name or null for no indicator + * @property {string|null} Symbolic indicator name */ OO.ui.IndicatorElement.static.indicator = null; @@ -81,7 +81,7 @@ }; /** - * Set indicator. + * Set indicator name. * * @param {string|null} indicator Symbolic name of indicator to use or null for no indicator * @chainable @@ -134,7 +134,7 @@ }; /** - * Get indicator. + * Get indicator name. * * @return {string} title Symbolic name of indicator */ diff --git a/src/elements/LabelElement.js b/src/elements/LabelElement.js index 504d675..fdbdad7 100644 --- a/src/elements/LabelElement.js +++ b/src/elements/LabelElement.js @@ -62,7 +62,7 @@ * Set the label. * * An empty string will result in the label being hidden. A string containing only whitespace will - * be converted to a single + * be converted to a single ` `. * * @param {jQuery|string|Function|null} label Label nodes; text; a function that returns nodes or * text; or null for no label diff --git a/src/elements/TitledElement.js b/src/elements/TitledElement.js index 5b37757..43b19aa 100644 --- a/src/elements/TitledElement.js +++ b/src/elements/TitledElement.js @@ -10,7 +10,8 @@ * @constructor * @param {Object} [config] Configuration options * @cfg {jQuery} [$titled] Titled node, assigned to #$titled, omit to use #$element - * @cfg {string|Function} [title] Title text or a function that returns text + * @cfg {string|Function} [title] Title text or a function that returns text. If not provided, the + * static property 'title' is used. */ OO.ui.TitledElement = function OoUiTitledElement( config ) { // Config intialization diff --git a/src/layouts/FieldLayout.js b/src/layouts/FieldLayout.js index d3b0122..2b669d8 100644 --- a/src/layouts/FieldLayout.js +++ b/src/layouts/FieldLayout.js @@ -1,10 +1,6 @@ /** * Layout made of a field and optional label. * - * @class - * @extends OO.ui.Layout - * @mixins OO.ui.LabelElement - * * Available label alignment modes include: * - left: Label is before the field and aligned away from it, best for when the user will be * scanning for a specific label in a form with many fields @@ -14,6 +10,10 @@ * fields from top to bottom in a form with few fields * - inline: Label is after the field and aligned toward it, best for small boolean fields like * checkboxes or radio buttons + * + * @class + * @extends OO.ui.Layout + * @mixins OO.ui.LabelElement * * @constructor * @param {OO.ui.Widget} fieldWidget Field widget @@ -106,6 +106,7 @@ /** * Set the field alignment mode. * + * @private * @param {string} value Alignment mode, either 'left', 'right', 'top' or 'inline' * @chainable */ diff --git a/src/layouts/FieldsetLayout.js b/src/layouts/FieldsetLayout.js index ec3401c..d407e8e 100644 --- a/src/layouts/FieldsetLayout.js +++ b/src/layouts/FieldsetLayout.js @@ -5,8 +5,8 @@ * * @class * @extends OO.ui.Layout - * @mixins OO.ui.LabelElement * @mixins OO.ui.IconElement + * @mixins OO.ui.LabelElement * @mixins OO.ui.GroupElement * * @constructor diff --git a/src/themes/mediawiki/MediaWikiTheme.js b/src/themes/mediawiki/MediaWikiTheme.js index d02a972..31a7d34 100644 --- a/src/themes/mediawiki/MediaWikiTheme.js +++ b/src/themes/mediawiki/MediaWikiTheme.js @@ -1,6 +1,6 @@ /** * @class - * @extends {OO.ui.Theme} + * @extends OO.ui.Theme * * @constructor */ diff --git a/src/widgets/ButtonGroupWidget.js b/src/widgets/ButtonGroupWidget.js index 74413fe..5fd1dc9 100644 --- a/src/widgets/ButtonGroupWidget.js +++ b/src/widgets/ButtonGroupWidget.js @@ -9,7 +9,7 @@ * * @constructor * @param {Object} [config] Configuration options - * @cfg {OO.ui.ButtonWidget} [items] Buttons to add + * @cfg {OO.ui.ButtonWidget[]} [items] Buttons to add */ OO.ui.ButtonGroupWidget = function OoUiButtonGroupWidget( config ) { // Parent constructor diff --git a/src/widgets/ButtonInputWidget.js b/src/widgets/ButtonInputWidget.js index 862658d..b7b0244 100644 --- a/src/widgets/ButtonInputWidget.js +++ b/src/widgets/ButtonInputWidget.js @@ -1,5 +1,5 @@ /** - * A button that is an input widget. Intended to be used within FormLayouts. + * A button that is an input widget. Intended to be used within a OO.ui.FormLayout. * * @class * @extends OO.ui.InputWidget @@ -70,6 +70,7 @@ /** * Get input element. * + * @private * @param {Object} [config] Configuration options * @return {jQuery} Input element */ @@ -79,7 +80,7 @@ }; /** - * Set the label. + * Set label value. * * Overridden to support setting the 'value' of `<input/>` elements. * diff --git a/src/widgets/CheckboxInputWidget.js b/src/widgets/CheckboxInputWidget.js index f05319f..537edf5 100644 --- a/src/widgets/CheckboxInputWidget.js +++ b/src/widgets/CheckboxInputWidget.js @@ -24,6 +24,7 @@ /** * Get input element. * + * @private * @return {jQuery} Input element */ OO.ui.CheckboxInputWidget.prototype.getInputElement = function () { diff --git a/src/widgets/InputWidget.js b/src/widgets/InputWidget.js index 9ecea58..e9b3b70 100644 --- a/src/widgets/InputWidget.js +++ b/src/widgets/InputWidget.js @@ -58,6 +58,7 @@ /** * Get input element. * + * @private * @param {Object} [config] Configuration options * @return {jQuery} Input element */ @@ -128,8 +129,9 @@ /** * Sanitize incoming value. * - * Ensures value is a string, and converts undefined and null to empty strings. + * Ensures value is a string, and converts undefined and null to empty string. * + * @private * @param {string} value Original value * @return {string} Sanitized value */ diff --git a/src/widgets/TextInputWidget.js b/src/widgets/TextInputWidget.js index 05c578d..b5f7234 100644 --- a/src/widgets/TextInputWidget.js +++ b/src/widgets/TextInputWidget.js @@ -208,6 +208,7 @@ /** * Get input element. * + * @private * @param {Object} [config] Configuration options * @return {jQuery} Input element */ -- To view, visit https://gerrit.wikimedia.org/r/168835 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: If9115dd5ac5dc7fb355abd03bb016a436eb3fca1 Gerrit-PatchSet: 2 Gerrit-Project: oojs/ui Gerrit-Branch: master Gerrit-Owner: Bartosz Dziewoński <matma....@gmail.com> Gerrit-Reviewer: Catrope <roan.katt...@gmail.com> Gerrit-Reviewer: Jforrester <jforres...@wikimedia.org> Gerrit-Reviewer: Legoktm <legoktm.wikipe...@gmail.com> Gerrit-Reviewer: Trevor Parscal <tpars...@wikimedia.org> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits