 
 NOOP = Function.prototype
 
-VALID_SUBJECT_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.gif', '.svg', '.mp3', '.m4a', '.mpeg']
+VALID_SUBJECT_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.gif', '.svg', '.mp3', '.m4a', '.mpeg', '.txt', '.json']
 INVALID_FILENAME_CHARS = ['/', '\\', ':', ',']
 MAX_FILE_SIZE = 1000 * 1024
 

        <p>You've reached your subject upload limit. Please <a href='/about/contact'> contact us</a> to request changes to your allowance.</p>
      else
        <p>
          <UploadDropTarget accept={"text/csv, text/tab-separated-values, image/*#{if isAdmin() then ', video/*, audio/*' else ''}"} multiple onSelect={@handleFileSelection}>
            <strong>Drag-and-drop or click to upload manifests and subject images here (you must select the media files as well as the manifest)</strong><br />
            Manifests must be <code>.csv</code> or <code>.tsv</code>. The first row should define metadata headers. All other rows should include at least one reference to an image filename in the same directory as the manifest.<br />
            Headers that begin with "#" or "//" denote private fields that will not be visible to classifiers in the main classification interface or in the Talk discussion tool.<br />

      if file.type in ['text/csv', 'text/tab-separated-values']
        @_addManifest file
        gotManifest = true
      else if file.type.indexOf('image/') is 0 or file.type.indexOf('video/') is 0 or file.type.indexOf('audio/') is 0 or file.type.indexOf('text/') is 0 or file.type.indexOf('application/json') is 0
        if file.size < MAX_FILE_SIZE or isAdmin()
          @state.files[file.name] = file
          gotFile = true
