Cscott has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/306975

Change subject: Extend 'format' spec to include custom format strings.
......................................................................

Extend 'format' spec to include custom format strings.

Thanks to Thiemo Mättig for the suggestion and specification at
Wikimania 2016 in Esino Lario.

This is an extended version of Thiemo's original specification.  This
version also allows specification of "own line" properties for
templates; that is, whether the template should be preceded/followed
by a newline, as requested by James Forrester.

Bug: T138492
Bug: T135667
Change-Id: Idc6b2680330e6bf5caec2bf6fc86a705d25bc649
---
M Specification.md
M TemplateDataBlob.php
M extension.json
M i18n/en.json
M i18n/qqq.json
M modules/ext.templateDataGenerator.ui.tdDialog.js
M resources/ext.templateData.css
M tests/ext.templateData.tests.js
M tests/phpunit/TemplateDataBlobTest.php
9 files changed, 318 insertions(+), 36 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/TemplateData 
refs/changes/75/306975/1

diff --git a/Specification.md b/Specification.md
index 3929441..d0133b9 100644
--- a/Specification.md
+++ b/Specification.md
@@ -98,25 +98,14 @@
 Authors MUST ensure that the `maps` object contains only `Map` objects. 
Authors MAY include a parameter in multiple `Map` objects. Authors are NOT 
REQUIRED to reference each parameter in at least one `Map` object.
 
 #### 3.1.6 `format`
-* Value: `null` or `string` of either `'inline'` or `'block'`
+* Value: `null` or `FormatString` or `string` of either `'inline'` or `'block'`
 * Default: `null`
 
 How the template's wikitext representation SHOULD be laid out. Authors MAY 
choose to use this parameter to express that a template will be better 
understood by other human readers of the wikitext representation if a template 
is in one form or the other.
 
-If the parameter is set to `'block'`, Consumers SHOULD create a wikitext 
representation with a single newline after the template invocation and each 
parameter value, a single space between each pipe and its subsequent parameter 
key, and a space either side of the assignment separator between the parameter 
key and value, like so:
+If the parameter is set to `'block'`, it MUST be interpreted as the format 
string `'{{_\n| _ = _\n}}'`.  If the parameter is set to `'inline'` it MUST be 
interpreted as the format string `'{{_|_=_}}'`.
 
-```
-{{Foo
-| bar = baz
-| qux = quux
-}}
-```
-
-If the parameter is set to `'inline'`, Consumers SHOULD create a wikitext 
representation with no whitespace, like so:
-
-```
-{{Foo|bar=baz|qux=quux}}
-```
+If the parameter is not null, Consumers SHOULD create a wikitext 
representation corresponding to the given format string, as described in 
section 3.7.
 
 If the parameter is set to `null`, Consumers SHOULD create the same 
representation as for `'inline'` format for new template transclusions, and 
SHOULD attempt to use the same formatting for new parameters as for existing 
ones for existing transclusions that are edited.
 
@@ -289,6 +278,87 @@
 
 The key corresponds to the name of a Consumer variable that relates to the 
specified parameter(s).
 
+### 3.7 FormatString
+* Value: `string`
+
+A format string describes how whitespace should be added to a template 
instantiation in wikitext.  A format string looks like `{{_|_=_}}`, with 
optional whitespace and extended underscores.  Formally, its structure is given 
by the following grammar:
+```
+FormatString = StartFormat ParameterFormat EndFormat
+StartFormat = nl? "{{" ws* Hole ws*
+ParameterFormat = nl? "|" nl? ws* Hole ws* "=" ws* Hole
+EndFormat = nl? ws* "}}" nl?
+Hole = "_"+
+ws = " "
+nl = "\n"
+```
+
+To format a template invocation according to the format string, first split it 
in three parts, corresponding to `StartFormat`, `ParameterFormat`, and 
`EndFormat` in the grammar above.  In the following, to "replace the `Hole`" 
with some value means to first pad a non-empty value with spaces on the right 
until it is at least as many characters long as the replaced underscore 
sequence.  Zero-length values are not padded.
+
+Begin with `StartFormat`, and replace the `Hole` with the name of the template 
to create the "output string".  If `StartFormat` begins with a newline and 
template is already at the start of a line (the character preceding this 
template invocation is a newline or the template is at the start of the 
output), delete the initial newline from the output string.
+
+For each parameter, append the `ParameterFormat` to the output string after 
replacing the first `Hole` with the name of the parameter and the second `Hole` 
with the value of the parameter.
+
+Finally, append the `EndFormat` to the output string.
+
+Some example format strings:
+
+Inline formatting: `{{_|_=_}}`
+```
+{{Foo|bar=baz|qux=quux}}{{Bar}}
+```
+
+Block formatting: `{{_\n| _ = _\n}}`
+```
+{{Foo
+| bar = baz
+| qux = quux
+}}{{Bar
+}}
+```
+
+No space before the parameter name, each template on its own line: `\n{{_\n|_ 
= _\n}}\n`
+```
+{{Foo
+|bar = baz
+|qux = quux
+}}
+{{Bar
+}}
+```
+
+Indent each parameter: `{{_\n |_ = _\n}}`
+```
+{{Foo
+ |bar = baz
+ |qux = quux
+}}{{Bar
+}}
+```
+
+Align all parameter names to a given length: `{{_\n|_______________ = _\n}}\n`
+```
+{{Foo
+|bar             = baz
+|qux             = quux
+|veryverylongparameter = bat
+}}
+{{Bar
+}}
+```
+
+Pipe characters at the end of the previous line: `{{_|\n  _______________ = 
_}}`
+```
+{{Foo|
+  bar             = baz|
+  qux             = quux}}{{Bar}}
+```
+
+Inline style with more spaces, must be at start of line: `\n{{_ | _ = _}}`
+```
+{{Foo | bar = baz | qux = quux}}
+{{Bar }}
+```
+
 ## 4 Examples
 
 ### 4.1 The "Unsigned" template
diff --git a/TemplateDataBlob.php b/TemplateDataBlob.php
index b8c8078..42e8b82 100644
--- a/TemplateDataBlob.php
+++ b/TemplateDataBlob.php
@@ -132,9 +132,8 @@
                ];
 
                static $formats = [
-                       null,
-                       'block',
-                       'inline'
+                       'block' => "{{_\n| _ = _\n}}",
+                       'inline' => '{{_|_=_}}',
                ];
 
                static $typeCompatMap = [
@@ -169,8 +168,13 @@
                }
 
                // Root.format
-               if ( isset( $data->format ) ) {
-                       if ( !in_array( $data->format, $formats ) ) {
+               if ( isset( $data->format ) && $data->format !== null ) {
+                       $f = isset( $formats[$data->format] ) ? 
$formats[$data->format] :
+                               $data->format;
+                       if (
+                               !is_string( $f ) ||
+                               !preg_match( '/^\n?\{\{ *_+ *\n?\|\n? *_+ *= 
*_+\n? *\}\}\n?$/', $f )
+                       ) {
                                return Status::newFatal(
                                        'templatedata-invalid-format',
                                        'format'
@@ -701,6 +705,13 @@
 
        public function getHtml( Language $lang ) {
                $data = $this->getDataInLanguage( $lang->getCode() );
+               if ( $data->format === null ) {
+                       $formatMsg = null;
+               } elseif ( isset( $formats[$data->format] ) ) {
+                       $formatMsg = $data->format;
+               } else {
+                       $formatMsg = 'custom';
+               }
                $html =
                        Html::openElement( 'div', [ 'class' => 
'mw-templatedata-doc-wrap' ] )
                        . Html::element(
@@ -724,16 +735,19 @@
                                        [],
                                        wfMessage( 'templatedata-doc-params' 
)->inLanguage( $lang )->text()
                                )
-                               . ( $data->format !== null ?
+                               . ( $formatMsg !== null ?
                                        Html::rawElement(
                                                'p',
                                                [],
-                                               new OOUI\IconWidget( [ 'icon' 
=> 'template-format-' . $data->format ] )
+                                               new OOUI\IconWidget( [ 'icon' 
=> 'template-format-' . $formatMsg ] )
                                                . Html::element(
                                                        'span',
                                                        [ 'class' => 
'mw-templatedata-format' ],
-                                                       // Messages: 
templatedata-modal-format-inline, templatedata-modal-format-block
-                                                       wfMessage( 
'templatedata-doc-format-' . $data->format )->inLanguage( $lang )->text()
+                                                       // Messages that can be 
used here:
+                                                       // * 
templatedata-doc-format-block
+                                                       // * 
templatedata-doc-format-custom
+                                                       // * 
templatedata-doc-format-inline
+                                                       wfMessage( 
'templatedata-doc-format-' . $formatMsg )->inLanguage( $lang )->text()
                                                )
                                        ) :
                                        '' )
diff --git a/extension.json b/extension.json
index bc1d111..af80549 100644
--- a/extension.json
+++ b/extension.json
@@ -122,9 +122,11 @@
                                "templatedata-modal-current-language",
                                "templatedata-modal-errormsg",
                                "templatedata-modal-errormsg-import-noparams",
-                               "templatedata-modal-format-inline",
                                "templatedata-modal-format-block",
+                               "templatedata-modal-format-custom",
+                               "templatedata-modal-format-inline",
                                "templatedata-modal-format-null",
+                               "templatedata-modal-format-placeholder",
                                "templatedata-modal-json-error-replace",
                                "templatedata-modal-notice-import-numparams",
                                "templatedata-modal-placeholder-paramkey",
@@ -152,6 +154,7 @@
                                "templatedata-modal-title-paramorder",
                                "templatedata-modal-title-templatedesc",
                                "templatedata-modal-title-templateformat",
+                               "templatedata-modal-title-templateformatstring",
                                
"templatedata-modal-title-templateparam-details",
                                "templatedata-modal-title-templateparams",
                                "templatedata-helplink",
diff --git a/i18n/en.json b/i18n/en.json
index 8f59418..aa41c90 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -12,8 +12,9 @@
        "apihelp-templatedata-param-lang": "Return localized values in this 
language. By default all available translations are returned.",
        "templatedata-desc": "Implement data storage for template parameters 
(using JSON)",
        "templatedata-doc-desc-empty": "No description.",
-       "templatedata-doc-format-inline": "This template prefers inline 
formatting of parameters.",
        "templatedata-doc-format-block": "This template prefers block 
formatting of parameters.",
+       "templatedata-doc-format-custom": "This template has custom 
formatting.",
+       "templatedata-doc-format-inline": "This template prefers inline 
formatting of parameters.",
        "templatedata-doc-no-params-set": "No parameters specified",
        "templatedata-doc-param-autovalue": "Auto value",
        "templatedata-doc-param-autovalue-empty": "empty",
@@ -52,7 +53,7 @@
        "templatedata-helplink-target": 
"//www.mediawiki.org/wiki/Special:MyLanguage/Help:TemplateData",
        "templatedata-invalid-duplicate-value": "Property \"$1\" (\"$3\") is a 
duplicate of \"$2\".",
        "templatedata-invalid-empty-array": "Property \"$1\" must have at least 
one value in its array.",
-       "templatedata-invalid-format": "Property \"$1\" is expected to be 
\"inline\" or \"block\".",
+       "templatedata-invalid-format": "Property \"$1\" is expected to be 
\"inline\", \"block\", or a valid format string.",
        "templatedata-invalid-length": "Data too large to save 
({{formatnum:$1}} {{PLURAL:$1|byte|bytes}}, {{PLURAL:$2|limit is}} 
{{formatnum:$2}})",
        "templatedata-invalid-missing": "Required property \"$1\" not found.",
        "templatedata-invalid-param": "Invalid parameter \"$1\" for property 
\"$2\".",
@@ -75,9 +76,11 @@
        "templatedata-modal-current-language": "Current language: $1",
        "templatedata-modal-errormsg": "Errors found. Please make sure there 
are no empty or duplicate parameter names, and that the parameter name does not 
include \"$1\", \"$2\" or \"$3\".",
        "templatedata-modal-errormsg-import-noparams": "No new parameters found 
during import.",
-       "templatedata-modal-format-inline": "Inline",
        "templatedata-modal-format-block": "Block",
+       "templatedata-modal-format-custom": "Custom",
+       "templatedata-modal-format-inline": "Inline",
        "templatedata-modal-format-null": "Unspecified",
+       "templatedata-modal-format-placeholder": "Template parameter format 
string",
        "templatedata-modal-json-error-replace": "Replace",
        "templatedata-modal-notice-import-numparams": "$1 new 
{{PLURAL:$1|parameter was|parameters were}} imported: $2",
        "templatedata-modal-placeholder-paramkey": "Parameter name",
@@ -105,6 +108,7 @@
        "templatedata-modal-title-paramorder": "Parameter order",
        "templatedata-modal-title-templatedesc": "Template description ($1)",
        "templatedata-modal-title-templateformat": "Template preferred format",
+       "templatedata-modal-title-templateformatstring": "Custom format string",
        "templatedata-modal-title-templateparam-details": "Parameter details: 
$1",
        "templatedata-modal-title-templateparams": "Template parameters"
 }
diff --git a/i18n/qqq.json b/i18n/qqq.json
index 23ddc0b..36965bd 100644
--- a/i18n/qqq.json
+++ b/i18n/qqq.json
@@ -22,8 +22,9 @@
        "apihelp-templatedata-param-lang": 
"{{doc-apihelp-param|templatedata|lang}}",
        "templatedata-desc": "{{desc|name=Template 
Data|url=https://www.mediawiki.org/wiki/Extension:TemplateData}}";,
        "templatedata-doc-desc-empty": "Displayed when a template has no 
description (should be a valid sentence).\n{{Identical|No description}}",
-       "templatedata-doc-format-inline": "Use inline formatting of the 
template parameters in wikitext.",
        "templatedata-doc-format-block": "Use block formatting of the template 
parameters in wikitext.",
+       "templatedata-doc-format-custom": "Use custom formatting of the 
template in wikitext.",
+       "templatedata-doc-format-inline": "Use inline formatting of the 
template parameters in wikitext.",
        "templatedata-doc-no-params-set": "A message shown when there are no 
parameters set in the TemplateData string.",
        "templatedata-doc-param-autovalue": "Used as column heading in the 
table for auto fill value.\n{{Related|Templatedata-doc-param}}",
        "templatedata-doc-param-autovalue-empty": "Displayed when a template 
parameter has no auto filled value (should not be a full sentence, used in a 
table).\n{{Identical|Empty}}",
@@ -85,9 +86,11 @@
        "templatedata-modal-current-language": "Label displaying the current 
language in the edit dialog. Parameters:\n* $1 - currently showing 
language\n{{Identical|Current language}}",
        "templatedata-modal-errormsg": "Error message that appears in the 
TemplateData generator GUI in case there are empty, duplicate or invalid 
parameter names.\n\nInvalid characters are supplied as parameters to avoid 
parsing errors in translation strings.\n\nParameters:\n* $1 - pipe 
(<code>|</code>)\n* $2 - equal sign (<code>=</code>)\n* $3 - double curly 
brackets (<code><nowiki>}}</nowiki></code>)",
        "templatedata-modal-errormsg-import-noparams": "Error message that 
appears in the TemplateData generator GUI in case no template parameters were 
found during the import attempt.",
-       "templatedata-modal-format-inline": "Label for inline 
format\n{{Identical|Inline}}",
        "templatedata-modal-format-block": "Label for block 
format\n{{Identical|Block}}",
+       "templatedata-modal-format-custom": "Label for custom format 
string\n{{Identical|Custom}}",
+       "templatedata-modal-format-inline": "Label for inline 
format\n{{Identical|Inline}}",
        "templatedata-modal-format-null": "Label for null 
format\n{{Identical|Unspecified}}",
+       "templatedata-modal-format-placeholder": "Placeholder text describing 
the format string entry widget",
        "templatedata-modal-json-error-replace": "Label for the button in the 
error message, agreeing to replace the existing faulty TemplateData string with 
a new one.\n{{Identical|Replace}}",
        "templatedata-modal-notice-import-numparams": "Message that appears in 
the TemplateData generator GUI showing how many new parameters were imported 
into the GUI from an existing template.\n\nParameters:\n* $1 - number of 
parameters\n* $2 - list of parameters that were imported",
        "templatedata-modal-placeholder-paramkey": "Placeholder for the input 
that contains new parameter name in the add parameter panel in the edit 
dialog.",
@@ -115,6 +118,7 @@
        "templatedata-modal-title-paramorder": "The title for the parameter 
order drag/drop widget in the edit dialog.",
        "templatedata-modal-title-templatedesc": "The title for the template 
description textbox. Parameters:\n* $1 - currently used language",
        "templatedata-modal-title-templateformat": "The title for the template 
preferred format",
+       "templatedata-modal-title-templateformatstring": "The title for the 
template custom format string",
        "templatedata-modal-title-templateparam-details": "The title for the 
parameter information section. Parameters:\n* $1 - The parameter name",
        "templatedata-modal-title-templateparams": "The title for the template 
parameters table\nof a single template."
 }
diff --git a/modules/ext.templateDataGenerator.ui.tdDialog.js 
b/modules/ext.templateDataGenerator.ui.tdDialog.js
index 4e23e6c..f58912e 100644
--- a/modules/ext.templateDataGenerator.ui.tdDialog.js
+++ b/modules/ext.templateDataGenerator.ui.tdDialog.js
@@ -153,6 +153,10 @@
        this.templateFormatSelectWidget = new OO.ui.ButtonSelectWidget();
        this.templateFormatSelectWidget.addItems( [
                new OO.ui.ButtonOptionWidget( {
+                       data: null,
+                       label: mw.msg( 'templatedata-modal-format-null' )
+               } ),
+               new OO.ui.ButtonOptionWidget( {
                        data: 'inline',
                        icon: 'template-format-inline',
                        label: mw.msg( 'templatedata-modal-format-inline' )
@@ -163,15 +167,25 @@
                        label: mw.msg( 'templatedata-modal-format-block' )
                } ),
                new OO.ui.ButtonOptionWidget( {
-                       data: null,
-                       label: mw.msg( 'templatedata-modal-format-null' )
+                       data: 'custom',
+                       label: mw.msg( 'templatedata-modal-format-custom' )
                } )
        ] );
+       this.templateFormatInputWidget = new OO.ui.TextInputWidget( {
+               placeholder: mw.msg( 'templatedata-modal-format-placeholder' )
+       } );
 
        templateFormatFieldSet = new OO.ui.FieldsetLayout( {
                label: mw.msg( 'templatedata-modal-title-templateformat' )
        } );
-       templateFormatFieldSet.$element.append( 
this.templateFormatSelectWidget.$element );
+       templateFormatFieldSet.addItems( [
+               new OO.ui.FieldLayout( this.templateFormatSelectWidget, {
+               } ),
+               new OO.ui.FieldLayout( this.templateFormatInputWidget, {
+                       align: 'top',
+                       label: mw.msg( 
'templatedata-modal-title-templateformatstring' )
+               } )
+       ] );
 
        // Param details panel
        this.$paramDetailsContainer = $( '<div>' )
@@ -236,6 +250,10 @@
        } );
        this.paramImport.connect( this, { click: 
'importParametersFromTemplateCode' } );
        this.templateFormatSelectWidget.connect( this, { choose: 
'onTemplateFormatSelectWidgetChoose' } );
+       this.templateFormatInputWidget.connect( this, {
+               change: 'onTemplateFormatInputWidgetChange',
+               enter: 'onTemplateFormatInputWidgetEnter'
+       } );
 
 };
 
@@ -434,7 +452,67 @@
  * @param {OO.ui.OptionWidget} item Format item
  */
 mw.TemplateData.Dialog.prototype.onTemplateFormatSelectWidgetChoose = function 
( item ) {
-       this.model.setTemplateFormat( item.getData() );
+       var format = item.getData(),
+               shortcuts = {
+                       inline: '{{_|_=_}}',
+                       block: '{{_\n| _ = _\n}}'
+               };
+       if ( format !== 'custom' ) {
+               this.model.setTemplateFormat( format );
+               this.templateFormatInputWidget.setDisabled( true );
+               if ( format !== null ) {
+                       this.templateFormatInputWidget.setValue(
+                               this.formatToDisplay( shortcuts[ format ] )
+                       );
+               }
+       } else {
+               this.templateFormatInputWidget.setDisabled( false );
+               this.onTemplateFormatInputWidgetChange(
+                       this.templateFormatInputWidget.getValue()
+               );
+       }
+};
+
+mw.TemplateData.Dialog.prototype.formatToDisplay = function ( s ) {
+       // Use '↵' (\u21b5) as a fancy newline (which doesn't start a new line).
+       return s.replace( /\n/g, '\u21b5' );
+};
+mw.TemplateData.Dialog.prototype.displayToFormat = function ( s ) {
+       // Allow user to type \n or \\n (literal backslash, n) for a new line.
+       return s.replace( /\n|\\n|\u21b5/g, '\n' );
+};
+
+/**
+ * Respond to change event from the template format input widget
+ *
+ * @param {string} value Input widget value
+ */
+mw.TemplateData.Dialog.prototype.onTemplateFormatInputWidgetChange = function 
( value ) {
+       var item = this.templateFormatSelectWidget.getSelectedItem(),
+               format,
+               newValue;
+       if ( item.getData() === 'custom' ) {
+               // Convert literal newlines or backslash-n to our fancy 
character
+               // replacement.
+               format = this.displayToFormat( value );
+               newValue = this.formatToDisplay( format );
+               if ( newValue !== value ) {
+                       this.templateFormatInputWidget.setValue( newValue );
+                       // Will recurse to actually set value in model.
+               } else {
+                       this.model.setTemplateFormat( format );
+               }
+       }
+};
+
+/**
+ * Respond to enter event from the template format input widget
+ */
+mw.TemplateData.Dialog.prototype.onTemplateFormatInputWidgetEnter = function 
() {
+       /* Synthesize a '\n' when enter is pressed. */
+       this.templateFormatInputWidget.insertContent(
+               this.formatToDisplay( '\n' )
+       );
 };
 
 mw.TemplateData.Dialog.prototype.onParamPropertyInputChange = function ( 
property, value ) {
@@ -874,11 +952,21 @@
  * after initialization of the model.
  */
 mw.TemplateData.Dialog.prototype.setupDetailsFromModel = function () {
+       var format;
+
        // Set up description
        this.descriptionInput.setValue( this.model.getTemplateDescription( 
this.language ) );
 
        // Set up format
-       this.templateFormatSelectWidget.selectItemByData( 
this.model.getTemplateFormat() );
+       format = this.model.getTemplateFormat();
+       if ( format === 'inline' || format === 'block' || format === null ) {
+               this.templateFormatSelectWidget.selectItemByData( format );
+               this.templateFormatInputWidget.setDisabled( true );
+       } else {
+               this.templateFormatSelectWidget.selectItemByData( 'custom' );
+               this.templateFormatInputWidget.setValue( this.formatToDisplay( 
format ) );
+               this.templateFormatInputWidget.setDisabled( false );
+       }
 
        // Repopulate the parameter list
        this.repopulateParamSelectWidget();
diff --git a/resources/ext.templateData.css b/resources/ext.templateData.css
index 2e06095..f1593f3 100644
--- a/resources/ext.templateData.css
+++ b/resources/ext.templateData.css
@@ -41,3 +41,8 @@
        /* @embed */
        background-image: url( ../modules/images/inline.svg );
 }
+
+.oo-ui-icon-template-format-custom {
+       /* @embed */
+       background-image: url( ../modules/images/block-ltr.svg );
+}
diff --git a/tests/ext.templateData.tests.js b/tests/ext.templateData.tests.js
index 7eea8c9..9770b74 100644
--- a/tests/ext.templateData.tests.js
+++ b/tests/ext.templateData.tests.js
@@ -144,7 +144,8 @@
                                        'day'
                                ]
                        }
-               ]
+               ],
+               format: 'inline'
        };
        finalJson.description[ currLanguage ] = 'Label unsigned comments in a 
conversation.';
 
@@ -507,6 +508,8 @@
                        2 * paramAddTest.length +
                        // Change properties tests
                        paramChangeTest.length +
+                       // Format tests
+                       8 +
                        // Json output
                        3
                );
@@ -566,6 +569,29 @@
                                // Delete parameter
                                model.deleteParam( 'day' );
 
+                               // Format checks
+                               assert.deepEqual(
+                                       model.getTemplateFormat(),
+                                       null,
+                                       'Initial template format (unspecified)'
+                               );
+                               [
+                                       '\n{{_ |\n__ = __}}',
+                                       '{{_|_=_\n}}\n',
+                                       '{{_|_=_}}', // No newlines
+                                       '\n{{  __  \n|\n  __  =  __\n  }}\n', 
// Max newlines/ws
+                                       null,
+                                       'block',
+                                       'inline'
+                               ].forEach( function ( f ) {
+                                       model.setTemplateFormat( f );
+                                       assert.deepEqual(
+                                               model.getTemplateFormat(),
+                                               f,
+                                               'Set template format to ' + 
JSON.stringify( f )
+                                       );
+                               } );
+
                                // Ouput a final templatedata
                                assert.deepEqual(
                                        model.outputTemplateData(),
diff --git a/tests/phpunit/TemplateDataBlobTest.php 
b/tests/phpunit/TemplateDataBlobTest.php
index 0da7bdc..09a5c7d 100644
--- a/tests/phpunit/TemplateDataBlobTest.php
+++ b/tests/phpunit/TemplateDataBlobTest.php
@@ -499,7 +499,75 @@
                                        },
                                        "format": "meshuggah format"
                                }',
-                               'status' => 'Property "format" is expected to 
be "inline" or "block".'
+                               'status' => 'Property "format" is expected to 
be "inline", "block", or a valid format string.'
+                       ],
+                       [
+                               'input' => '{
+                                       "params": {},
+                                       "format": "inline"
+                               }',
+                               'output' => '{
+                                       "description": null,
+                                       "params": {},
+                                       "paramOrder": [],
+                                       "sets": [],
+                                       "format": "inline",
+                                       "maps": {}
+                               }
+                               ',
+                               'msg' => '"inline" is a valid format string',
+                               'status' => true
+                       ],
+                       [
+                               'input' => '{
+                                       "params": {},
+                                       "format": "block"
+                               }',
+                               'output' => '{
+                                       "description": null,
+                                       "params": {},
+                                       "paramOrder": [],
+                                       "sets": [],
+                                       "format": "block",
+                                       "maps": {}
+                               }
+                               ',
+                               'msg' => '"block" is a valid format string',
+                               'status' => true
+                       ],
+                       [
+                               'input' => '{
+                                       "params": {},
+                                       "format": "{{_ |\n ___ = _}}"
+                               }',
+                               'output' => '{
+                                       "description": null,
+                                       "params": {},
+                                       "paramOrder": [],
+                                       "sets": [],
+                                       "format": "{{_ |\n ___ = _}}",
+                                       "maps": {}
+                               }
+                               ',
+                               'msg' => 'Custom parameter format string (1)',
+                               'status' => true
+                       ],
+                       [
+                               'input' => '{
+                                       "params": {},
+                                       "format": "{{_|_=_\n}}\n"
+                               }',
+                               'output' => '{
+                                       "description": null,
+                                       "params": {},
+                                       "paramOrder": [],
+                                       "sets": [],
+                                       "format": "{{_|_=_\n}}\n",
+                                       "maps": {}
+                               }
+                               ',
+                               'msg' => 'Custom parameter format string (2)',
+                               'status' => true
                        ],
                        [
                                // Should be long enough to trigger this 
condition after gzipping.

-- 
To view, visit https://gerrit.wikimedia.org/r/306975
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Idc6b2680330e6bf5caec2bf6fc86a705d25bc649
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/TemplateData
Gerrit-Branch: master
Gerrit-Owner: Cscott <canan...@wikimedia.org>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to