<commit_before>'use strict';

var Handlebars = require('handlebars');

function Parser (keywordSpec) {
  // make new optional
  if (!(this instanceof Parser)) {
    return new Parser(keywordSpec);
  }

  // default JavaScript keywords from
  // https://www.gnu.org/savannah-checkouts/gnu/gettext/manual/html_node/xgettext-Invocation.html
  keywordSpec = keywordSpec || {
    _: {
      msgid: 0
    },
    gettext: {
      msgid: 0
    },
    dgettext: {
      msgid: 1
    },
    dcgettext: {
      msgid: 1
    },
    ngettext: {
      msgid: 0,
      msgid_plural: 1
    },
    dngettext: {
      msgid: 1,
      msgid_plural: 2
    },
    pgettext: {
      msgctxt: 0,
      msgid: 1
    },
    dpgettext: {
      msgctxt: 1,
      msgid: 2
    }
  };

  Object.keys(keywordSpec).forEach(function (keyword) {
    var positions = keywordSpec[keyword];

    if ('msgid' in positions) {
      return;
    } else if (Array.isArray(positions) && positions.indexOf('msgid') >= 0) {
      // maintain backwards compatibility with `_: ['msgid']` format
      keywordSpec[keyword] = positions.reduce(function (result, key, idx) {
        result[key] = idx;

        return result;
      }, {});
    } else if (Array.isArray(positions) && positions.length > 0) {
      // maintain backwards compatibility with `_: [0]` format
      var order = ['msgid', 'msgid_plural'];

      keywordSpec[keyword] = positions.slice(0).reduce(function (result, pos, idx) {
        result[order[idx]] = pos;

        return result;
      }, {});
    }
  });

  Object.keys(keywordSpec).forEach(function (keyword) {
    if (!('msgid' in keywordSpec[keyword])) {
      throw new Error('Every keyword must have a msgid key, but "' + keyword + '" doesn\'t have one');
    }
  });

  this.keywordSpec = keywordSpec;
}

// Same as what Jed.js uses
Parser.contextDelimiter = String.fromCharCode(4);

Parser.messageToKey = function (msgid, msgctxt) {
  return msgctxt ? msgctxt + Parser.contextDelimiter + msgid : msgid;
};

/**
 * Given a Handlebars template string returns the list of i18n strings.
 *
 * @param String template The content of a HBS template.
 * @return Object The list of translatable strings, the line(s) on which each appears and an optional plural form.
 */
Parser.prototype.parse = function (template) {
  var keywordSpec = this.keywordSpec,
    keywords = Object.keys(keywordSpec),
    tree = Handlebars.parse(template);

  var isMsg = function (msgs, statement) {
    switch (statement.type) {
    case 'MustacheStatement':
    case 'SubExpression':
      if (keywords.indexOf(statement.path.original) !== -1) {
        var spec = keywordSpec[statement.path.original];
        var params = statement.params;
        var msgidParam = params[spec.msgid];

        if (msgidParam) { // don't extract {{gettext}} without param
          var msgid = msgidParam.original;
          var contextIndex = spec.msgctxt;<commit_msg>expose default keywords<commit_after>'use strict';

var Handlebars = require('handlebars');

function Parser (keywordSpec) {
  // make new optional
  if (!(this instanceof Parser)) {
    return new Parser(keywordSpec);
  }

  keywordSpec = keywordSpec || Parser.keywordSpec;

  Object.keys(keywordSpec).forEach(function (keyword) {
    var positions = keywordSpec[keyword];

    if ('msgid' in positions) {
      return;
    } else if (Array.isArray(positions) && positions.indexOf('msgid') >= 0) {
      // maintain backwards compatibility with `_: ['msgid']` format
      keywordSpec[keyword] = positions.reduce(function (result, key, idx) {
        result[key] = idx;

        return result;
      }, {});
    } else if (Array.isArray(positions) && positions.length > 0) {
      // maintain backwards compatibility with `_: [0]` format
      var order = ['msgid', 'msgid_plural'];

      keywordSpec[keyword] = positions.slice(0).reduce(function (result, pos, idx) {
        result[order[idx]] = pos;

        return result;
      }, {});
    }
  });

  Object.keys(keywordSpec).forEach(function (keyword) {
    if (!('msgid' in keywordSpec[keyword])) {
      throw new Error('Every keyword must have a msgid key, but "' + keyword + '" doesn\'t have one');
    }
  });

  this.keywordSpec = keywordSpec;
}

// default keywords, copied from GNU xgettext's JavaScript keywords
Parser.keywordSpec = {
  _: {
    msgid: 0
  },
  gettext: {
    msgid: 0
  },
  dgettext: {
    msgid: 1
  },
  dcgettext: {
    msgid: 1
  },
  ngettext: {
    msgid: 0,
    msgid_plural: 1
  },
  dngettext: {
    msgid: 1,
    msgid_plural: 2
  },
  pgettext: {
    msgctxt: 0,
    msgid: 1
  },
  dpgettext: {
    msgctxt: 1,
    msgid: 2
  }
};

// Same as what Jed.js uses
Parser.contextDelimiter = String.fromCharCode(4);

Parser.messageToKey = function (msgid, msgctxt) {
  return msgctxt ? msgctxt + Parser.contextDelimiter + msgid : msgid;
};

/**
 * Given a Handlebars template string returns the list of i18n strings.
 *
 * @param String template The content of a HBS template.
 * @return Object The list of translatable strings, the line(s) on which each appears and an optional plural form.
 */
Parser.prototype.parse = function (template) {
  var keywordSpec = this.keywordSpec,
    keywords = Object.keys(keywordSpec),
    tree = Handlebars.parse(template);

  var isMsg = function (msgs, statement) {
    switch (statement.type) {
    case 'MustacheStatement':
    case 'SubExpression':
      if (keywords.indexOf(statement.path.original) !== -1) {
        var spec = keywordSpec[statement.path.original];
        var params = statement.params;
        var msgidParam = params[spec.msgid];

        if (msgidParam) { // don't extract {{gettext}} without param
          var msgid = msgidParam.original;
          var contextIndex = spec.msgctxt;
{'fraction_non_alphanumeric': 0.1286061870003476, 'fraction_numerical': 0.006951685783802572, 'mean_word_length': 2.8624161073825505, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2687515', 'n_tokens_mistral': 1825, 'n_tokens_neox': 1723, 'n_words': 472}