// CodeMirror, copyright © by Marijn Haverbeke and others // Distributed under an MIT license: codemirror.net/LICENSE

(function(mod) {

if (typeof exports == "object" && typeof module == "object") // CommonJS
  mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
  define(["../../lib/codemirror"], mod);
else // Plain browser env
  mod(CodeMirror);

})(function(CodeMirror) { “use strict”;

var rfc2822 = [

"From", "Sender", "Reply-To", "To", "Cc", "Bcc", "Message-ID",
"In-Reply-To", "References", "Resent-From", "Resent-Sender", "Resent-To",
"Resent-Cc", "Resent-Bcc", "Resent-Message-ID", "Return-Path", "Received"

]; var rfc2822NoEmail = [

"Date", "Subject", "Comments", "Keywords", "Resent-Date"

];

CodeMirror.registerHelper(“hintWords”, “mbox”, rfc2822.concat(rfc2822NoEmail));

var whitespace = /^[ t]/; var separator = /^From /; // See RFC 4155 var rfc2822Header = new RegExp(“^(” + rfc2822.join(“|”) + “): ”); var rfc2822HeaderNoEmail = new RegExp(“^(” + rfc2822NoEmail.join(“|”) + “): ”); var header = /^[^:]+:/; // Optional fields defined in RFC 2822 var email = /^[^ ]+@[^ ]+/; var untilEmail = /^.*?(?=[^ ]+?@[^ ]+)/; var bracketedEmail = /^<.*?>/; var untilBracketedEmail = /^.*?(?=<.*>)/;

function styleForHeader(header) {

if (header === "Subject") return "header";
return "string";

}

function readToken(stream, state) {

if (stream.sol()) {
  // From last line
  state.inSeparator = false;
  if (state.inHeader && stream.match(whitespace)) {
    // Header folding
    return null;
  } else {
    state.inHeader = false;
    state.header = null;
  }

  if (stream.match(separator)) {
    state.inHeaders = true;
    state.inSeparator = true;
    return "atom";
  }

  var match;
  var emailPermitted = false;
  if ((match = stream.match(rfc2822HeaderNoEmail)) ||
      (emailPermitted = true) && (match = stream.match(rfc2822Header))) {
    state.inHeaders = true;
    state.inHeader = true;
    state.emailPermitted = emailPermitted;
    state.header = match[1];
    return "atom";
  }

  // Use vim's heuristics: recognize custom headers only if the line is in a
  // block of legitimate headers.
  if (state.inHeaders && (match = stream.match(header))) {
    state.inHeader = true;
    state.emailPermitted = true;
    state.header = match[1];
    return "atom";
  }

  state.inHeaders = false;
  stream.skipToEnd();
  return null;
}

if (state.inSeparator) {
  if (stream.match(email)) return "link";
  if (stream.match(untilEmail)) return "atom";
  stream.skipToEnd();
  return "atom";
}

if (state.inHeader) {
  var style = styleForHeader(state.header);

  if (state.emailPermitted) {
    if (stream.match(bracketedEmail)) return style + " link";
    if (stream.match(untilBracketedEmail)) return style;
  }
  stream.skipToEnd();
  return style;
}

stream.skipToEnd();
return null;

};

CodeMirror.defineMode(“mbox”, function() {

return {
  startState: function() {
    return {
      // Is in a mbox separator
      inSeparator: false,
      // Is in a mail header
      inHeader: false,
      // If bracketed email is permitted. Only applicable when inHeader
      emailPermitted: false,
      // Name of current header
      header: null,
      // Is in a region of mail headers
      inHeaders: false
    };
  },
  token: readToken,
  blankLine: function(state) {
    state.inHeaders = state.inSeparator = state.inHeader = false;
  }
};

});

CodeMirror.defineMIME(“application/mbox”, “mbox”); });