2

I need to convert this...

# 4.0.0 - 2016-01-01
- some text without category

# 3.12.0 - 2016-02-01
- Category: some text

# 3.11.4 - 2016-03-01
- Category: some multiple text
- Something: some text
- Anything: more text

...into an (object)array. I don't know how to keep all elements connected to its version.

The result should be look like this (example for last block)

[
    { 
        major: 3,
        minor: 11,
        patch = 4,
        date = '2016-03-01',
        entries = [
            { category: 'Category', 'some multiple text' },
            { category: 'Something', 'some text' },
            { category: 'Anything', 'more text' }
        ]
    }
]

As you can see in the first block, in entries the field category is optional.

This is how I try do it:

var lines = text.split('\n');
for(var i = 0;i < lines.length;i++){
    var meta = lines[i].split(' ');
    var version = meta[1].split('.');
    result['major'] = version[0];
    result['minor'] = version[1];
    result['patch'] = version[2];
    result['date'] = meta[3]
}

But this only works for the first line of each block.

2
  • Does it have to be in JavaScript ? Other engines (e.g. PCRE in PHP) provide better functionality like \G. Commented Mar 6, 2016 at 8:57
  • yes, it has to be JS. Commented Mar 6, 2016 at 9:01

2 Answers 2

2

This proposal split the string into chunks and test the chunks for # or -. These line are evaluated and added to the result.

var text = '# 4.0.0 - 2016-01-01\n- some text without category\n- Just a text: with double point\n\n# 3.12.0 - 2016-02-01\n- Category: some text\n\n# 3.11.4 - 2016-03-01\n- Category: some multiple text\n- Something: some text\n- Anything: more text',
    result = function (text) {
        var array = text.split('\n'),
            o, r = [];
        array.forEach(function (a) {
            var p, v;
            if (a[0] === '#') {
                o = {};
                p = a.match(/^# ((.*) - )?(.*)$/);
                v = p[2].split('.');
                o.major = v[0];
                o.minor = v[1];
                o.patch = v[2];
                o.date = p[3];
                r.push(o);
            }
            if (a[0] === '-') {
                if (!o.entries) {
                    o.entries = [];
                }
                p = a.match(/^- ((\w*): )?(.*)$/);
                o.entries.push({ category: p[2], value: p[3] });
            }
        });
        return r;
    }(text);

document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');

Sign up to request clarification or add additional context in comments.

2 Comments

Just one thing: Category should be only extracted if it is one single word. Example: Category: Some Text will give me a category field. But Just a text: with double point doesn't give me a category field, but only the value field.
@user3142695, please see edit, with edited regex: /^- ((\w*): )?(.*)$/ for word only search.
1

This can be solved with writing different functions for the different types of lines and some regular expressions:

var text = `# 4.0.0 - 2016-01-01
- some text without category

# 3.12.0 - 2016-02-01
- Category: some text

# 3.11.4 - 2016-03-01
- Category: some multiple text
- Something: some text
- Anything: more text`;

var lines = text.split('\n');
var all = [];
for(var i = 0;i < lines.length;i++){
  var firstChar = lines[i].substr(0, 1);
  if (firstChar === '#'){
    all.push(extractVersionInfo(lines[i]));
  }
  else if (firstChar === "-"){
    all[all.length-1].entries.push(extractNote(lines[i]));
  }
}
console.log(all);

function extractNote(text){
  var withoutDash = text.substr(2);
  if (withoutDash.indexOf(":") !== -1){
    var parts = withoutDash.split(":");
    return {category: parts[0],
        value: parts[1]
       };
  }
  else {
    return {value: withoutDash};
  }
}

function extractVersionInfo(text){
  var pattern = /# ([0-9]+)\.([0-9]+)\.([0-9]+) - ([0-9]{4}-[0-9]{2}-[0-9]{2})/;
  var match = text.match(pattern);
  result = {};
  result.major = match[1];
  result.minor = match[2];
  result.patch = match[3];
  result.date = match[4];
  result.entries = [];
  return result;
}

Output:

[ { major: '4',
    minor: '0',
    patch: '0',
    date: '2016-01-01',
    entries: [ { value: 'some text without category' } ] },
  { major: '3',
    minor: '12',
    patch: '0',
    date: '2016-02-01',
    entries: [ { category: 'Category', value: ' some text' } ] },
  { major: '3',
    minor: '11',
    patch: '4',
    date: '2016-03-01',
    entries: 
     [ { category: 'Category', value: ' some multiple text' },
       { category: 'Something', value: ' some text' },
       { category: 'Anything', value: ' more text' } ] } ]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.