filepond-plugin-file-validate-type.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /*!
  2. * FilePondPluginFileValidateType 1.2.8
  3. * Licensed under MIT, https://opensource.org/licenses/MIT/
  4. * Please visit https://pqina.nl/filepond/ for details.
  5. */
  6. /* eslint-disable */
  7. (function(global, factory) {
  8. typeof exports === 'object' && typeof module !== 'undefined'
  9. ? (module.exports = factory())
  10. : typeof define === 'function' && define.amd
  11. ? define(factory)
  12. : ((global = global || self),
  13. (global.FilePondPluginFileValidateType = factory()));
  14. })(this, function() {
  15. 'use strict';
  16. var plugin = function plugin(_ref) {
  17. var addFilter = _ref.addFilter,
  18. utils = _ref.utils;
  19. // get quick reference to Type utils
  20. var Type = utils.Type,
  21. isString = utils.isString,
  22. replaceInString = utils.replaceInString,
  23. guesstimateMimeType = utils.guesstimateMimeType,
  24. getExtensionFromFilename = utils.getExtensionFromFilename,
  25. getFilenameFromURL = utils.getFilenameFromURL;
  26. var mimeTypeMatchesWildCard = function mimeTypeMatchesWildCard(
  27. mimeType,
  28. wildcard
  29. ) {
  30. var mimeTypeGroup = (/^[^/]+/.exec(mimeType) || []).pop(); // image/png -> image
  31. var wildcardGroup = wildcard.slice(0, -2); // image/* -> image
  32. return mimeTypeGroup === wildcardGroup;
  33. };
  34. var isValidMimeType = function isValidMimeType(
  35. acceptedTypes,
  36. userInputType
  37. ) {
  38. return acceptedTypes.some(function(acceptedType) {
  39. // accepted is wildcard mime type
  40. if (/\*$/.test(acceptedType)) {
  41. return mimeTypeMatchesWildCard(userInputType, acceptedType);
  42. }
  43. // is normal mime type
  44. return acceptedType === userInputType;
  45. });
  46. };
  47. var getItemType = function getItemType(item) {
  48. // if the item is a url we guess the mime type by the extension
  49. var type = '';
  50. if (isString(item)) {
  51. var filename = getFilenameFromURL(item);
  52. var extension = getExtensionFromFilename(filename);
  53. if (extension) {
  54. type = guesstimateMimeType(extension);
  55. }
  56. } else {
  57. type = item.type;
  58. }
  59. return type;
  60. };
  61. var validateFile = function validateFile(
  62. item,
  63. acceptedFileTypes,
  64. typeDetector
  65. ) {
  66. // no types defined, everything is allowed \o/
  67. if (acceptedFileTypes.length === 0) {
  68. return true;
  69. }
  70. // gets the item type
  71. var type = getItemType(item);
  72. // no type detector, test now
  73. if (!typeDetector) {
  74. return isValidMimeType(acceptedFileTypes, type);
  75. }
  76. // use type detector
  77. return new Promise(function(resolve, reject) {
  78. typeDetector(item, type)
  79. .then(function(detectedType) {
  80. if (isValidMimeType(acceptedFileTypes, detectedType)) {
  81. resolve();
  82. } else {
  83. reject();
  84. }
  85. })
  86. .catch(reject);
  87. });
  88. };
  89. var applyMimeTypeMap = function applyMimeTypeMap(map) {
  90. return function(acceptedFileType) {
  91. return map[acceptedFileType] === null
  92. ? false
  93. : map[acceptedFileType] || acceptedFileType;
  94. };
  95. };
  96. // setup attribute mapping for accept
  97. addFilter('SET_ATTRIBUTE_TO_OPTION_MAP', function(map) {
  98. return Object.assign(map, {
  99. accept: 'acceptedFileTypes'
  100. });
  101. });
  102. // filtering if an item is allowed in hopper
  103. addFilter('ALLOW_HOPPER_ITEM', function(file, _ref2) {
  104. var query = _ref2.query;
  105. // if we are not doing file type validation exit
  106. if (!query('GET_ALLOW_FILE_TYPE_VALIDATION')) {
  107. return true;
  108. }
  109. // we validate the file against the accepted file types
  110. return validateFile(file, query('GET_ACCEPTED_FILE_TYPES'));
  111. });
  112. // called for each file that is loaded
  113. // right before it is set to the item state
  114. // should return a promise
  115. addFilter('LOAD_FILE', function(file, _ref3) {
  116. var query = _ref3.query;
  117. return new Promise(function(resolve, reject) {
  118. if (!query('GET_ALLOW_FILE_TYPE_VALIDATION')) {
  119. resolve(file);
  120. return;
  121. }
  122. var acceptedFileTypes = query('GET_ACCEPTED_FILE_TYPES');
  123. // custom type detector method
  124. var typeDetector = query('GET_FILE_VALIDATE_TYPE_DETECT_TYPE');
  125. // if invalid, exit here
  126. var validationResult = validateFile(
  127. file,
  128. acceptedFileTypes,
  129. typeDetector
  130. );
  131. var handleRejection = function handleRejection() {
  132. var acceptedFileTypesMapped = acceptedFileTypes
  133. .map(
  134. applyMimeTypeMap(
  135. query('GET_FILE_VALIDATE_TYPE_LABEL_EXPECTED_TYPES_MAP')
  136. )
  137. )
  138. .filter(function(label) {
  139. return label !== false;
  140. });
  141. var acceptedFileTypesMapped_unique = acceptedFileTypesMapped.filter(
  142. function(item, index) {
  143. return acceptedFileTypesMapped.indexOf(item) === index;
  144. }
  145. );
  146. reject({
  147. status: {
  148. main: query('GET_LABEL_FILE_TYPE_NOT_ALLOWED'),
  149. sub: replaceInString(
  150. query('GET_FILE_VALIDATE_TYPE_LABEL_EXPECTED_TYPES'),
  151. {
  152. allTypes: acceptedFileTypesMapped_unique.join(', '),
  153. allButLastType: acceptedFileTypesMapped_unique
  154. .slice(0, -1)
  155. .join(', '),
  156. lastType:
  157. acceptedFileTypesMapped_unique[
  158. acceptedFileTypesMapped.length - 1
  159. ]
  160. }
  161. )
  162. }
  163. });
  164. };
  165. // has returned new filename immidiately
  166. if (typeof validationResult === 'boolean') {
  167. if (!validationResult) {
  168. return handleRejection();
  169. }
  170. return resolve(file);
  171. }
  172. // is promise
  173. validationResult
  174. .then(function() {
  175. resolve(file);
  176. })
  177. .catch(handleRejection);
  178. });
  179. });
  180. // expose plugin
  181. return {
  182. // default options
  183. options: {
  184. // Enable or disable file type validation
  185. allowFileTypeValidation: [true, Type.BOOLEAN],
  186. // What file types to accept
  187. acceptedFileTypes: [[], Type.ARRAY],
  188. // - must be comma separated
  189. // - mime types: image/png, image/jpeg, image/gif
  190. // - extensions: .png, .jpg, .jpeg ( not enabled yet )
  191. // - wildcards: image/*
  192. // label to show when a type is not allowed
  193. labelFileTypeNotAllowed: ['File is of invalid type', Type.STRING],
  194. // nicer label
  195. fileValidateTypeLabelExpectedTypes: [
  196. 'Expects {allButLastType} or {lastType}',
  197. Type.STRING
  198. ],
  199. // map mime types to extensions
  200. fileValidateTypeLabelExpectedTypesMap: [{}, Type.OBJECT],
  201. // Custom function to detect type of file
  202. fileValidateTypeDetectType: [null, Type.FUNCTION]
  203. }
  204. };
  205. };
  206. // fire pluginloaded event if running in browser, this allows registering the plugin when using async script tags
  207. var isBrowser =
  208. typeof window !== 'undefined' && typeof window.document !== 'undefined';
  209. if (isBrowser) {
  210. document.dispatchEvent(
  211. new CustomEvent('FilePond:pluginloaded', { detail: plugin })
  212. );
  213. }
  214. return plugin;
  215. });