angular-gettext icon indicating copy to clipboard operation
angular-gettext copied to clipboard

Data-bound shorthand-if with <= breaks extraction

Open rubenswieringa opened this issue 10 years ago • 2 comments

(Originally posted in angular-gettext-tools repo, but haven't heard back a month and a half later, so reposting here in hopes it will be seen)


tl;dr: The following breaks string-extraction: <p translate>{{ n <= 1 ? 'a' : 'b' }}</p>

When I did a quick scan through already-filed issues I couldn't find any similar to this – sorry if I missed it and this is a duplicate.

Steps to reproduction

  1. In an html-element with a translate-attribute, use a smaller-than-or-equal-to operator (<=) in a data-bounds ({{ }}) expression.
  2. Run the nggettext_extract grunt-task

Expected:

  • Only the inner contents of the html-element should be extracted by the grunt-task. ({{ n <= 1 ? 'a' : 'b' }})

Actual:

  • Everything after the opening tag of the html-element is extracted (the extracted string might look something like {{ n <= 1 ? 'a' : 'b' }}</p></div></section>)

Tests/code

The following will break on the 4th <p>:

<!-- test/fixtures/shorthand_if.html -->
<html>
    <body>
        <p translate>1 start {{ n > 1 ? 'if' : 'else' }} end</p>
        <!-- comment after 1st line -->
        <span>after first</span>
        <p translate>2 start {{ n >= 1 ? 'if' : 'else' }} end</p>
        <!-- comment after 2nd line -->
        <span>after second</span>
        <p translate>3 start {{ n < 1 ? 'if' : 'else' }} end</p>
        <!-- comment after 3rd line -->
        <span>after third</span>
        <p translate>4 start {{ n <= 1 ? 'if' : 'else' }} end</p>
        <!-- comment after 4th line -->
        <span>after fourth</span>
    </body>
</html>
// test/extract_shorthand_if.js

var assert = require('assert');
var fs = require('fs');
var Extractor = require('..').Extractor;
var testExtract = require('./utils').testExtract;

describe('String extractor', function () {
    it('extracts strings with data-bound shorthand-if statements containing smaller-than-or-equal-to operators', function () {
        var files = [
            'test/fixtures/shorthand_if.html'
        ];

        var paragraphs = [
            "1 start {{ n > 1 ? 'if' : 'else' }} end",
            "2 start {{ n >= 1 ? 'if' : 'else' }} end",
            "3 start {{ n < 1 ? 'if' : 'else' }} end",
            "4 start {{ n <= 1 ? 'if' : 'else' }} end"
        ];

        var catalog = testExtract(files);
        assert.equal(catalog.items.length, paragraphs.length);

        for ( var i = 0; i < paragraphs.length; i++ ) {
            assert.equal(catalog.items[i].msgid, paragraphs[i]);
            assert.equal(catalog.items[i].msgstr, '');
            assert.deepEqual(catalog.items[i].references, ['test/fixtures/shorthand_if.html:' + ( 3 + i * 3 )]);
        }
    });
});

Result/output

AssertionError: "4 start {{ n <= 1=\"\" ?=\"\" 'if'=\"\" :=\"\" 'else'=\"\" }}=\"\" end<=\"\" p=\"\">\n        <!-- comment after 4th line -->\n == "4 start {{ n <= 1 ? 'if' : 'else' }} end"
+ expected - actual

-4 start {{ n <= 1="" ?="" 'if'="" :="" 'else'="" }}="" end<="" p="">
-        <!-- comment after 4th line -->
-        <span>after fourth</span>
-    </=>
+4 start {{ n <= 1 ? 'if' : 'else' }} end

Workaround

Use a greater-than operator (>) and swap your ‘if’ and ‘else’ values.

rubenswieringa avatar Oct 14 '15 12:10 rubenswieringa

angular-gettext-tools is the right project to file this against, I just haven't had time to dig into what's happening. My guess is that htmlparser2, which we use by way of cheerio, is parsing the <= as a start tag. I can't say for certain though without spending more time debugging.

Also, thanks for the awesome write up of the bug.

On Wednesday, October 14, 2015, rubenswieringa [email protected] wrote:

*(Originally posted in angular-gettext-tools repo https://github.com/rubenv/angular-gettext-tools/issues/108, but haven't heard back a month and a half later, so reposting here in hopes it will be

seen)*

tl;dr: The following breaks string-extraction:

{{ n <= 1 ? 'a' : 'b' }}

When I did a quick scan through already-filed issues I couldn't find any similar to this – sorry if I missed it and this is a duplicate. Steps to reproduction

  1. In an html-element with a translate-attribute, use a smaller-than-or-equal-to operator (<=) in a data-bounds ({{ }}) expression.
  2. Run the nggettext_extract grunt-task

Expected:

  • Only the inner contents of the html-element should be extracted by the grunt-task. ({{ n <= 1 ? 'a' : 'b' }})

Actual:

  • Everything after the opening tag of the html-element is extracted (the extracted string might look something like {{ n <= 1 ? 'a' : 'b' }})

Tests/code

The following will break on the 4th

:

1 start {{ n > 1 ? 'if' : 'else' }} end

after first

2 start {{ n >= 1 ? 'if' : 'else' }} end

after second

3 start {{ n after third

4 start {{ n after fourth

// test/extract_shorthand_if.js var assert = require('assert');var fs = require('fs');var Extractor = require('..').Extractor;var testExtract = require('./utils').testExtract;

describe('String extractor', function () { it('extracts strings with data-bound shorthand-if statements containing smaller-than-or-equal-to operators', function () { var files = [ 'test/fixtures/shorthand_if.html' ];

    var paragraphs = [
        "1 start {{ n > 1 ? 'if' : 'else' }} end",
        "2 start {{ n >= 1 ? 'if' : 'else' }} end",
        "3 start {{ n < 1 ? 'if' : 'else' }} end",
        "4 start {{ n <= 1 ? 'if' : 'else' }} end"
    ];

    var catalog = testExtract(files);
    assert.equal(catalog.items.length, paragraphs.length);

    for ( var i = 0; i < paragraphs.length; i++ ) {
        assert.equal(catalog.items[i].msgid, paragraphs[i]);
        assert.equal(catalog.items[i].msgstr, '');
        assert.deepEqual(catalog.items[i].references, ['test/fixtures/shorthand_if.html:' + ( 3 + i * 3 )]);
    }
});

});

Result/output

AssertionError: "4 start {{ n <= 1="" ?="" 'if'="" :="" 'else'="" }}="" end<="" p="">\n \n == "4 start {{ n <= 1 ? 'if' : 'else' }} end"

  • expected - actual

-4 start {{ n <= 1="" ?="" 'if'="" :="" 'else'="" }}="" end<="" p="">

  •    <!-- comment after 4th line -->
    
  •    <span>after fourth</span>
    
  • </=> +4 start {{ n <= 1 ? 'if' : 'else' }} end

Workaround

Use a greater-than operator (>) and swap your ‘if’ and ‘else’ values.

— Reply to this email directly or view it on GitHub https://github.com/rubenv/angular-gettext/issues/230.

gabegorelick avatar Oct 14 '15 22:10 gabegorelick

Alright, thanks for getting back to me. Feel free to close either one of the issues (no need to maintain two separate discussions). Do let me know if you find anything out about this :)

rubenswieringa avatar Oct 15 '15 08:10 rubenswieringa