[TASK] Modernize TypeScript setup and fix module paths 21/53021/17
authorJohannes Goslar <jogo@kronberger-spiele.de>
Fri, 2 Jun 2017 19:57:31 +0000 (21:57 +0200)
committerFrank Naegler <frank.naegler@typo3.org>
Mon, 5 Jun 2017 15:37:52 +0000 (17:37 +0200)
Resolves: #81416
Releases: master, 8.7
Change-Id: If7e3893baa73c1392f3317d5b871be51eeab41b5
Reviewed-on: https://review.typo3.org/53021
Reviewed-by: Oliver Hader <oliver.hader@typo3.org>
Tested-by: Oliver Hader <oliver.hader@typo3.org>
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Frank Naegler <frank.naegler@typo3.org>
Tested-by: Frank Naegler <frank.naegler@typo3.org>
16 files changed:
Build/Gruntfile.js
Build/package-lock.json
Build/package.json
Build/tsconfig.json
Build/tslint.json
Build/types/TYPO3/index.d.ts
typo3/sysext/backend/Resources/Private/TypeScript/ColorPicker.ts
typo3/sysext/backend/Resources/Private/TypeScript/FormEngineReview.ts
typo3/sysext/backend/Resources/Private/TypeScript/ImageManipulation.ts
typo3/sysext/backend/Resources/Private/TypeScript/Popover.ts
typo3/sysext/backend/Resources/Private/TypeScript/RenameFile.ts
typo3/sysext/backend/Resources/Public/JavaScript/ColorPicker.js
typo3/sysext/backend/Resources/Public/JavaScript/FormEngineReview.js
typo3/sysext/backend/Resources/Public/JavaScript/ImageManipulation.js
typo3/sysext/backend/Resources/Public/JavaScript/Popover.js
typo3/sysext/backend/Resources/Public/JavaScript/RenameFile.js

index 5a07093..a2ef228 100644 (file)
@@ -192,14 +192,8 @@ module.exports = function (grunt) {
                                src: '<%= paths.workspaces %>Public/Css/*.css'
                        }
                },
-               ts: {
-                       default: {
-                               tsconfig: true,
-                               options: {
-                                       verbose: false,
-                                       additionalFlags: '--typeRoots "node_modules/@types,types"'
-                               }
-                       }
+               exec: {
+                       ts: './node_modules/.bin/tsc --project tsconfig.json'
                },
                tslint: {
                        options: {
@@ -433,10 +427,10 @@ module.exports = function (grunt) {
                                           see https://github.com/claviska/jquery-minicolors/issues/206
                                           'jquery.minicolors.js': '../node_modules/@claviska/jquery-minicolors/jquery.minicolors.min.js',
                                           '../../Images/colorpicker/jquery.minicolors.png': '../node_modules/@claviska/jquery-minicolors/jquery.minicolors.png'
-                                       */
+                                        */
                                        /* disabled until autocomplete formatGroup is fixed to pass on the index too
                                           'jquery.autocomplete.js': '../node_modules/devbridge-autocomplete/dist/jquery.autocomplete.min.js',
-                                       */
+                                        */
                                        'd3/d3.js': 'd3/build/d3.min.js',
                                        /**
                                         * copy needed parts of jquery
@@ -487,7 +481,7 @@ module.exports = function (grunt) {
        grunt.loadNpmTasks('grunt-contrib-uglify');
        grunt.loadNpmTasks('grunt-postcss');
        grunt.loadNpmTasks('grunt-contrib-copy');
-       grunt.loadNpmTasks("grunt-ts");
+       grunt.loadNpmTasks('grunt-exec');
        grunt.loadNpmTasks('grunt-tslint');
        grunt.loadNpmTasks('grunt-stylelint');
 
@@ -554,14 +548,63 @@ module.exports = function (grunt) {
         * - 2) Compiles all TypeScript files (*.ts) which are located in sysext/<EXTKEY>/Resources/Private/TypeScript/*.ts
         * - 3) Copy all generated JavaScript and Map files to public folders
         */
-       grunt.registerTask('scripts', ['tslint', 'tsclean', 'ts', 'copy:ts_files']);
+       grunt.registerTask('scripts', ['tsconfig', 'tslint', 'tsclean', 'exec:ts', 'copy:ts_files']);
 
+       /**
+        * grunt tsclean task
+        *
+        * call "$ grunt tsclean"
+        *
+        * Clean the JavaScript output folder before building
+        */
        grunt.task.registerTask('tsclean', function () {
                grunt.option('force');
                grunt.file.delete("JavaScript");
        });
 
        /**
+        * grunt tsdev task
+        *
+        * call "$ grunt tsdev"
+        *
+        * this task copies and modifies the TypeScript configuration for a developer system
+        * most TypeScript tooling expects tsconfig.json to be in a domineering/root-level position
+        */
+       grunt.task.registerTask('tsdev', function () {
+               var content = grunt.file.read("tsconfig.json");
+               content = content.replace(/..\/typo3\//g, 'typo3/');
+               content = content.replace('"rootDir": "../",', '"rootDir": "./",');
+               content = content.replace('./JavaScript', './Build/JavaScript');
+               content = content.replace('"node_modules/@types"', '"Build/node_modules/@types"');
+               content = content.replace('"types"', '"Build/types"');
+               grunt.file.write('../tsconfig.json', content);
+               grunt.file.copy('./tslint.json', '../tslint.json');
+       });
+
+       /**
+        * grunt tsconfig task
+        *
+        * call "$ grunt tsconfig"
+        *
+        * this task updates the tsconfig.json file with modules paths for all sysexts
+        */
+       grunt.task.registerTask('tsconfig', function () {
+               var config = grunt.file.readJSON("tsconfig.json");
+               config.compilerOptions.paths = {};
+               grunt.file.expand('../typo3/sysext/*/Resources/Public/JavaScript').forEach( function(dir){
+                       var extname = '_' + dir.match(/sysext\/(.*?)\//)[1],
+                               extname = extname.replace(/_./g, function(match){
+                                       return match.charAt(1).toUpperCase();
+                               });
+                       var namespace = 'TYPO3/CMS/' + extname + '/*',
+                               path = dir + "/*";
+                       config.compilerOptions.paths[namespace] = [path];
+               });
+
+               grunt.file.write('tsconfig.json', JSON.stringify(config, null, 4));
+       });
+
+       /**
         * grunt build task
         *
         * call "$ grunt build"
index 281324b..b69283d 100644 (file)
       "integrity": "sha1-RIIg7bQq3QoLcC9xIl01kF8MuUg=",
       "dev": true
     },
+    "@types/ckeditor": {
+      "version": "0.0.38",
+      "resolved": "https://registry.npmjs.org/@types/ckeditor/-/ckeditor-0.0.38.tgz",
+      "integrity": "sha512-xclEOGCP/s9Qzfc1LdvyJwFqaqhlcG4+9RbdB7bsLY4WR1/S5bDajL4qXJwao/xiso+aiRwURHaC1AwRMsg6Pg==",
+      "dev": true
+    },
+    "@types/imagesloaded": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/@types/imagesloaded/-/imagesloaded-4.1.0.tgz",
+      "integrity": "sha1-46xF7bBc4xhgnAt4avJxubKKo6w=",
+      "dev": true
+    },
     "@types/jasmine": {
       "version": "2.5.48",
       "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-2.5.48.tgz",
       "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
       "dev": true
     },
-    "async-each": {
-      "version": "0.1.6",
-      "resolved": "https://registry.npmjs.org/async-each/-/async-each-0.1.6.tgz",
-      "integrity": "sha1-tn6Z7c3fllQeRK9WKQzX1cbnBDk=",
-      "dev": true
-    },
     "async-foreach": {
       "version": "0.1.3",
       "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz",
       "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=",
       "dev": true
     },
+    "babel-code-frame": {
+      "version": "6.22.0",
+      "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz",
+      "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=",
+      "dev": true
+    },
     "backo2": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
         }
       }
     },
-    "chokidar": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.0.6.tgz",
-      "integrity": "sha1-ChwLzh4kmTr8EFpbgeom3aAeI68=",
-      "dev": true,
-      "dependencies": {
-        "glob-parent": {
-          "version": "1.3.0",
-          "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-1.3.0.tgz",
-          "integrity": "sha1-lx7dgW7V21hwW1gHlkemTQrveWg=",
-          "dev": true,
-          "dependencies": {
-            "is-glob": {
-              "version": "2.0.1",
-              "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
-              "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
-              "dev": true
-            }
-          }
-        },
-        "is-glob": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-1.1.3.tgz",
-          "integrity": "sha1-tMZLgwPTkRRJKkYNNkzPsNPAoEU=",
-          "dev": true
-        }
-      }
-    },
     "chosen-js": {
       "version": "1.7.0",
       "resolved": "https://registry.npmjs.org/chosen-js/-/chosen-js-1.7.0.tgz",
       "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=",
       "dev": true
     },
-    "csproj2ts": {
-      "version": "0.0.7",
-      "resolved": "https://registry.npmjs.org/csproj2ts/-/csproj2ts-0.0.7.tgz",
-      "integrity": "sha1-drEJRoMlbponCf1cY+7ya/R6FEI=",
-      "dev": true,
-      "dependencies": {
-        "es6-promise": {
-          "version": "2.3.0",
-          "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-2.3.0.tgz",
-          "integrity": "sha1-lu258v2wGZWCKyY92KratnSBgbw=",
-          "dev": true
-        }
-      }
-    },
     "css-color-list": {
       "version": "0.0.1",
       "resolved": "https://registry.npmjs.org/css-color-list/-/css-color-list-0.0.1.tgz",
       "integrity": "sha1-jjGcnwRTv1ddN0lAplWSDlnKVRI=",
       "dev": true
     },
-    "es6-promise": {
-      "version": "0.1.2",
-      "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-0.1.2.tgz",
-      "integrity": "sha1-8RLCn+paCZhTn8tqL9IUQ9KPBfc=",
-      "dev": true
-    },
     "es6-symbol": {
       "version": "3.1.1",
       "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz",
       "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
       "dev": true
     },
-    "fsevents": {
-      "version": "0.3.8",
-      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-0.3.8.tgz",
-      "integrity": "sha1-mZLxAyySXIKVVNDVmAHcoDE6U1Y=",
-      "dev": true,
-      "optional": true
-    },
     "fstream": {
       "version": "1.0.11",
       "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz",
       "integrity": "sha1-hKGnodar0m7VaEE0lscxM+mQAY8=",
       "dev": true
     },
+    "grunt-exec": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/grunt-exec/-/grunt-exec-2.0.0.tgz",
+      "integrity": "sha1-pXWmILHaRBbCksAd9WTJKWuAqyM=",
+      "dev": true
+    },
     "grunt-known-options": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-1.1.0.tgz",
       "integrity": "sha1-bdiaORERfiFNKi785WWsRqBuRC0=",
       "dev": true
     },
-    "grunt-ts": {
-      "version": "5.5.1",
-      "resolved": "https://registry.npmjs.org/grunt-ts/-/grunt-ts-5.5.1.tgz",
-      "integrity": "sha1-lXIBxrQhx3cilATwcILY5pnRIZk=",
-      "dev": true,
-      "dependencies": {
-        "lodash": {
-          "version": "2.4.1",
-          "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.1.tgz",
-          "integrity": "sha1-W3cjA03aTSYuWkb7LFjXzCL3FCA=",
-          "dev": true
-        },
-        "rimraf": {
-          "version": "2.2.6",
-          "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.6.tgz",
-          "integrity": "sha1-xZWXVpsU2VatKcrMQr3d9fDqT0w=",
-          "dev": true
-        },
-        "typescript": {
-          "version": "1.8.9",
-          "resolved": "https://registry.npmjs.org/typescript/-/typescript-1.8.9.tgz",
-          "integrity": "sha1-s7OnQFn9McvT7K2V1iRlk55+1fo=",
-          "dev": true
-        },
-        "underscore.string": {
-          "version": "2.3.3",
-          "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz",
-          "integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=",
-          "dev": true
-        }
-      }
-    },
     "grunt-tslint": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmjs.org/grunt-tslint/-/grunt-tslint-3.3.0.tgz",
-      "integrity": "sha1-1IYDHFQS2IQsixJuyBRh2qmJg6M=",
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/grunt-tslint/-/grunt-tslint-5.0.1.tgz",
+      "integrity": "sha1-dDK9G9VuijolAACI1cYf3MNC8MI=",
       "dev": true
     },
     "gzip-size": {
       "integrity": "sha1-8OgK4DmkvWVLXygfyT8EqRSn/M4=",
       "dev": true
     },
+    "js-tokens": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz",
+      "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=",
+      "dev": true
+    },
     "js-yaml": {
       "version": "3.5.5",
       "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.5.5.tgz",
       "integrity": "sha1-5P805slf37WuzAjeZZb0NgWn20U=",
       "dev": true
     },
-    "ncp": {
-      "version": "0.5.1",
-      "resolved": "https://registry.npmjs.org/ncp/-/ncp-0.5.1.tgz",
-      "integrity": "sha1-dDmFMW49tFkoG1hxaehFc1oFQ58=",
-      "dev": true
-    },
     "negotiator": {
       "version": "0.6.1",
       "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
       "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=",
       "dev": true
     },
+    "path-parse": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz",
+      "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=",
+      "dev": true
+    },
     "path-type": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
       "integrity": "sha1-n6+jfShr5dksuuve4DDcm19AZ0c=",
       "dev": true
     },
-    "readdirp": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-1.4.0.tgz",
-      "integrity": "sha1-xd5vyz3sgFI8HHARPxoZDYr4LIk=",
-      "dev": true,
-      "dependencies": {
-        "isarray": {
-          "version": "0.0.1",
-          "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
-          "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
-          "dev": true
-        },
-        "lru-cache": {
-          "version": "2.7.3",
-          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz",
-          "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=",
-          "dev": true
-        },
-        "minimatch": {
-          "version": "0.2.14",
-          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz",
-          "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=",
-          "dev": true
-        },
-        "readable-stream": {
-          "version": "1.0.34",
-          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
-          "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
-          "dev": true
-        },
-        "string_decoder": {
-          "version": "0.10.31",
-          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
-          "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
-          "dev": true
-        }
-      }
-    },
     "realize-package-specifier": {
       "version": "3.0.3",
       "resolved": "https://registry.npmjs.org/realize-package-specifier/-/realize-package-specifier-3.0.3.tgz",
         }
       }
     },
-    "sax": {
-      "version": "1.2.2",
-      "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.2.tgz",
-      "integrity": "sha1-/YYxojvHgmvvXYcb24c3jJVkeCg=",
-      "dev": true
-    },
     "scss-tokenizer": {
       "version": "0.2.3",
       "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz",
       "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=",
       "dev": true
     },
+    "tslib": {
+      "version": "1.7.1",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.7.1.tgz",
+      "integrity": "sha1-vIAEFkaRkjp5/oN4u+s9ogF1OOw=",
+      "dev": true
+    },
     "tslint": {
-      "version": "3.15.1",
-      "resolved": "https://registry.npmjs.org/tslint/-/tslint-3.15.1.tgz",
-      "integrity": "sha1-2hZcqT2P3CwIa1EWXuG6y0jJjqU=",
+      "version": "5.4.2",
+      "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.4.2.tgz",
+      "integrity": "sha1-YJtmQMwEJPSjlamt9ow3VWPFScc=",
       "dev": true,
       "dependencies": {
-        "underscore.string": {
-          "version": "3.3.4",
-          "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.4.tgz",
-          "integrity": "sha1-LCo/n4PmR2L9xF5s6sZRQoZCE9s=",
+        "diff": {
+          "version": "3.2.0",
+          "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz",
+          "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=",
+          "dev": true
+        },
+        "glob": {
+          "version": "7.1.2",
+          "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
+          "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
+          "dev": true
+        },
+        "resolve": {
+          "version": "1.3.3",
+          "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.3.3.tgz",
+          "integrity": "sha1-ZVkHw0aahoDcLeOidaj91paR8OU=",
           "dev": true
         }
       }
     },
+    "tsutils": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.3.0.tgz",
+      "integrity": "sha1-luZh18I2PzGtyJkqxnu+e3/BdeU=",
+      "dev": true
+    },
     "tunnel-agent": {
       "version": "0.6.0",
       "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
       "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=",
       "dev": true
     },
-    "underscore": {
-      "version": "1.5.1",
-      "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.5.1.tgz",
-      "integrity": "sha1-0r3oF9F2/63olKtxRY5oKhS4bck=",
-      "dev": true
-    },
     "underscore.string": {
       "version": "3.2.3",
       "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.2.3.tgz",
       "integrity": "sha1-OS2LotDxw00e4tYw8V0O+2jhBIo=",
       "dev": true
     },
-    "xml2js": {
-      "version": "0.4.17",
-      "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.17.tgz",
-      "integrity": "sha1-F76T6q4/O3eTWceVtBlwWogX6Gg=",
-      "dev": true
-    },
-    "xmlbuilder": {
-      "version": "4.2.1",
-      "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-4.2.1.tgz",
-      "integrity": "sha1-qlijBBoGb5DqoWwvU4n/GfP0YaU=",
-      "dev": true,
-      "dependencies": {
-        "lodash": {
-          "version": "4.17.4",
-          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
-          "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=",
-          "dev": true
-        }
-      }
-    },
     "xmlhttprequest": {
       "version": "1.8.0",
       "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz",
index 6c70fe9..3b7cd97 100644 (file)
@@ -10,6 +10,8 @@
   "devDependencies": {
     "@claviska/jquery-minicolors": "^2.2.6",
     "@types/bootstrap": "*",
+    "@types/ckeditor": "0.0.38",
+    "@types/imagesloaded": "^4.1.0",
     "@types/jasmine": "^2.5.35",
     "@types/jquery": "*",
     "@types/jqueryui": "*",
     "grunt-contrib-copy": "^1.0.0",
     "grunt-contrib-uglify": "2.0.0",
     "grunt-contrib-watch": "~1.0.0",
+    "grunt-exec": "^2.0.0",
     "grunt-npm-install": "^0.3.1",
     "grunt-npmcopy": "^0.1.0",
     "grunt-postcss": "^0.8.0",
     "grunt-sass": "^2.0.0",
     "grunt-stylelint": "^0.7.0",
-    "grunt-ts": "^5.5.1",
-    "grunt-tslint": "^3.2.1",
+    "grunt-tslint": "^5.0.1",
     "imagesloaded": "^4.1.1",
     "jasmine-core": "~2.6.0",
     "jquery": "^3.2.1",
@@ -65,8 +67,8 @@
     "stylefmt": "^5.3.0",
     "taboverride": "^4.0.3",
     "tagsort": "1.4.0",
-    "tslint": "^3.15.1",
-    "typescript": "^2.2.0"
+    "tslint": "^5.4.2",
+    "typescript": "^2.3.4"
   },
   "scripts": {
     "build-css": "./node_modules/.bin/grunt css",
index 70da760..e8953c2 100644 (file)
         "module": "amd",
         "sourceMap": false,
         "removeComments": false,
+        "alwaysStrict": true,
+        "downlevelIteration": true,
+        "experimentalDecorators": true,
+        "noImplicitAny": true,
+        "noImplicitThis": true,
+        "noImplicitReturns": true,
         "pretty": true,
         "baseUrl": ".",
         "rootDir": "../",
         "paths": {
             "TYPO3/CMS/About/*": [
-                "../typo3/sysext/about/Resources/Public/JavaScript/"
+                "../typo3/sysext/about/Resources/Public/JavaScript/*"
             ],
             "TYPO3/CMS/Backend/*": [
-                "../typo3/sysext/backend/Resources/Public/JavaScript/"
-            ],
-            "TYPO3/CMS/Belog/*": [
-                "../typo3/sysext/belog/Resources/Public/JavaScript/"
+                "../typo3/sysext/backend/Resources/Public/JavaScript/*"
             ],
             "TYPO3/CMS/Beuser/*": [
-                "../typo3/sysext/beuser/Resources/Public/JavaScript/"
-            ],
-            "TYPO3/CMS/ContextHelp/*": [
-                "../typo3/sysext/context_help/Resources/Public/JavaScript/"
+                "../typo3/sysext/beuser/Resources/Public/JavaScript/*"
             ],
             "TYPO3/CMS/Core/*": [
-                "../typo3/sysext/core/Resources/Public/JavaScript/"
-            ],
-            "TYPO3/CMS/Cshmanuel/*": [
-                "../typo3/sysext/cshmanuel/Resources/Public/JavaScript/"
+                "../typo3/sysext/core/Resources/Public/JavaScript/*"
             ],
             "TYPO3/CMS/Documentation/*": [
-                "../typo3/sysext/documentation/Resources/Public/JavaScript/"
-            ],
-            "TYPO3/CMS/Extbase/*": [
-                "../typo3/sysext/extbase/Resources/Public/JavaScript/"
+                "../typo3/sysext/documentation/Resources/Public/JavaScript/*"
             ],
             "TYPO3/CMS/Extensionmanager/*": [
-                "../typo3/sysext/extensionmanager/Resources/Public/JavaScript/"
-            ],
-            "TYPO3/CMS/Feedit/*": [
-                "../typo3/sysext/feedit/Resources/Public/JavaScript/"
-            ],
-            "TYPO3/CMS/Felogin/*": [
-                "../typo3/sysext/felogin/Resources/Public/JavaScript/"
+                "../typo3/sysext/extensionmanager/Resources/Public/JavaScript/*"
             ],
             "TYPO3/CMS/Filelist/*": [
-                "../typo3/sysext/filelist/Resources/Public/JavaScript/"
-            ],
-            "TYPO3/CMS/Filemetadata/*": [
-                "../typo3/sysext/filemetadata/Resources/Public/JavaScript/"
-            ],
-            "TYPO3/CMS/Fluid/*": [
-                "../typo3/sysext/fluid/Resources/Public/JavaScript/"
-            ],
-            "TYPO3/CMS/FluidStyledContent/*": [
-                "../typo3/sysext/fluid_styled_content/Resources/Public/JavaScript/"
+                "../typo3/sysext/filelist/Resources/Public/JavaScript/*"
             ],
             "TYPO3/CMS/Form/*": [
-                "../typo3/sysext/form/Resources/Public/JavaScript/"
+                "../typo3/sysext/form/Resources/Public/JavaScript/*"
             ],
             "TYPO3/CMS/Frontend/*": [
-                "../typo3/sysext/frontend/Resources/Public/JavaScript/"
-            ],
-            "TYPO3/CMS/Func/*": [
-                "../typo3/sysext/func/Resources/Public/JavaScript/"
+                "../typo3/sysext/frontend/Resources/Public/JavaScript/*"
             ],
             "TYPO3/CMS/Impexp/*": [
-                "../typo3/sysext/impexp/Resources/Public/JavaScript/"
-            ],
-            "TYPO3/CMS/IndexedSearch/*": [
-                "../typo3/sysext/indexed_search/Resources/Public/JavaScript/"
-            ],
-            "TYPO3/CMS/Info/*": [
-                "../typo3/sysext/info/Resources/Public/JavaScript/"
-            ],
-            "TYPO3/CMS/InfoPagetsconfig/*": [
-                "../typo3/sysext/info_pagetsconfig/Resources/Public/JavaScript/"
+                "../typo3/sysext/impexp/Resources/Public/JavaScript/*"
             ],
             "TYPO3/CMS/Install/*": [
-                "../typo3/sysext/install/Resources/Public/JavaScript/"
+                "../typo3/sysext/install/Resources/Public/JavaScript/*"
             ],
             "TYPO3/CMS/Lang/*": [
-                "../typo3/sysext/lang/Resources/Public/JavaScript/"
+                "../typo3/sysext/lang/Resources/Public/JavaScript/*"
             ],
             "TYPO3/CMS/Linkvalidator/*": [
-                "../typo3/sysext/linkvalidator/Resources/Public/JavaScript/"
+                "../typo3/sysext/linkvalidator/Resources/Public/JavaScript/*"
             ],
             "TYPO3/CMS/Lowlevel/*": [
-                "../typo3/sysext/lowlevel/Resources/Public/JavaScript/"
+                "../typo3/sysext/lowlevel/Resources/Public/JavaScript/*"
             ],
             "TYPO3/CMS/Opendocs/*": [
-                "../typo3/sysext/opendocs/Resources/Public/JavaScript/"
+                "../typo3/sysext/opendocs/Resources/Public/JavaScript/*"
             ],
             "TYPO3/CMS/Recordlist/*": [
-                "../typo3/sysext/recordlist/Resources/Public/JavaScript/"
+                "../typo3/sysext/recordlist/Resources/Public/JavaScript/*"
             ],
             "TYPO3/CMS/Recycler/*": [
-                "../typo3/sysext/recycler/Resources/Public/JavaScript/"
-            ],
-            "TYPO3/CMS/Reports/*": [
-                "../typo3/sysext/reports/Resources/Public/JavaScript/"
+                "../typo3/sysext/recycler/Resources/Public/JavaScript/*"
             ],
             "TYPO3/CMS/Rsaauth/*": [
-                "../typo3/sysext/rsaauth/Resources/Public/JavaScript/"
-            ],
-            "TYPO3/CMS/Rtehtmlarea/*": [
-                "../typo3/sysext/rtehtmlarea/Resources/Public/JavaScript/"
+                "../typo3/sysext/rsaauth/Resources/Public/JavaScript/*"
             ],
-            "TYPO3/CMS/Saltedpasswords/*": [
-                "../typo3/sysext/saltedpassword/Resources/Public/JavaScript/"
+            "TYPO3/CMS/RteCkeditor/*": [
+                "../typo3/sysext/rte_ckeditor/Resources/Public/JavaScript/*"
             ],
             "TYPO3/CMS/Scheduler/*": [
-                "../typo3/sysext/scheduler/Resources/Public/JavaScript/"
-            ],
-            "TYPO3/CMS/Setup/*": [
-                "../typo3/sysext/setup/Resources/Public/JavaScript/"
-            ],
-            "TYPO3/CMS/Sv/*": [
-                "../typo3/sysext/sv/Resources/Public/JavaScript/"
+                "../typo3/sysext/scheduler/Resources/Public/JavaScript/*"
             ],
             "TYPO3/CMS/SysAction/*": [
-                "../typo3/sysext/sys_action/Resources/Public/JavaScript/"
-            ],
-            "TYPO3/CMS/SysNote/*": [
-                "../typo3/sysext/sys:note/Resources/Public/JavaScript/"
+                "../typo3/sysext/sys_action/Resources/Public/JavaScript/*"
             ],
             "TYPO3/CMS/T3editor/*": [
-                "../typo3/sysext/t3editor/Resources/Public/JavaScript/"
+                "../typo3/sysext/t3editor/Resources/Public/JavaScript/*"
             ],
             "TYPO3/CMS/Taskcenter/*": [
-                "../typo3/sysext/taskcenter/Resources/Public/JavaScript/"
+                "../typo3/sysext/taskcenter/Resources/Public/JavaScript/*"
             ],
             "TYPO3/CMS/Tstemplate/*": [
-                "../typo3/sysext/tetemplate/Resources/Public/JavaScript/"
-            ],
-            "TYPO3/CMS/Version/*": [
-                "../typo3/sysext/version/Resources/Public/JavaScript/"
+                "../typo3/sysext/tstemplate/Resources/Public/JavaScript/*"
             ],
             "TYPO3/CMS/Viewpage/*": [
-                "../typo3/sysext/viewpage/Resources/Public/JavaScript/"
+                "../typo3/sysext/viewpage/Resources/Public/JavaScript/*"
             ],
             "TYPO3/CMS/WizardCrpages/*": [
-                "../typo3/sysext/wizard_crpages/Resources/Public/JavaScript/"
-            ],
-            "TYPO3/CMS/WizardSortpages/*": [
-                "../typo3/sysext/wizard_sortpages/Resources/Public/JavaScript/"
+                "../typo3/sysext/wizard_crpages/Resources/Public/JavaScript/*"
             ],
             "TYPO3/CMS/Workspaces/*": [
-                "../typo3/sysext/workspaces/Resources/Public/JavaScript/"
+                "../typo3/sysext/workspaces/Resources/Public/JavaScript/*"
             ]
         },
         "outDir": "./JavaScript/",
             "types"
         ]
     },
-    "filesGlob": [
+    "include": [
         "../typo3/sysext/*/Resources/Private/TypeScript/**/*.ts"
-    ],
-    "files": [
-        "../typo3/sysext/backend/Resources/Private/TypeScript/ColorPicker.ts",
-        "../typo3/sysext/backend/Resources/Private/TypeScript/FormEngineReview.ts",
-        "../typo3/sysext/backend/Resources/Private/TypeScript/ImageManipulation.ts",
-        "../typo3/sysext/backend/Resources/Private/TypeScript/Popover.ts",
-        "../typo3/sysext/backend/Resources/Private/TypeScript/RenameFile.ts"
     ]
 }
\ No newline at end of file
index 362d261..aa19ca5 100644 (file)
@@ -2,10 +2,11 @@
        "// extends": "@see https://github.com/palantir/tslint/blob/master/src/configs/recommended.ts",
        "extends": "tslint:recommended",
        "rules": {
-               "interface-name": false,
-               "no-console": false,
+               "interface-name": [false],
+               "no-console": [false],
+               "no-inferrable-types": [true],
                "no-namespace": [false, "allow-declarations"],
-               "quotemark": [true, "single", "avoid-escape"],
-               "typedef": [true, "call-signature", "arrow-call-signature", "arrow-parameter", "property-declaration", "variable-declaration", "parameter", "member-variable-declaration"]
+               "no-trailing-comma": [false],
+               "quotemark": [true, "single", "avoid-escape"]
        }
 }
index e95a92a..87d5e16 100644 (file)
@@ -1,2 +1,68 @@
+/* tslint:disable:max-classes-per-file */
+
+/**
+ * Currently a mixture between namespace and global object
+ * Add types as you use them
+ */
+declare namespace TYPO3 {
+  export let Popover: any;
+  export const lang: any;
+  export const settings: any;
+  export namespace CMS {
+    export namespace Backend {
+      export class FormEngineValidation {
+        public readonly errorClass: string;
+      }
+      export class FormEngine {
+        public readonly Validation: FormEngineValidation;
+      }
+      export class Modal {
+        public readonly sizes: {[key: string]: string};
+        public readonly styles: {[key: string]: string};
+        public advanced(configuration: object): any;
+        public confirm(title: string, content: any, severity: number, buttons: any[], additionalCssClasses?: string[]): JQuery; // tslint:disable-line:max-line-length
+        public dismiss(): void;
+      }
+      export class Severity {
+        public readonly notice: number;
+        public readonly info: number;
+        public readonly ok: number;
+        public readonly warning: number;
+        public readonly: number;
+      }
+    }
+  }
+}
+
+/**
+ * Current AMD/RequireJS modules are returning *instances* of ad-hoc *classes*, make that known to TypeScript
+ */
+
+declare module 'TYPO3/CMS/Backend/FormEngineValidation' {
+  export = new TYPO3.CMS.Backend.FormEngineValidation();
+}
+
+declare module 'TYPO3/CMS/Backend/FormEngine' {
+  export = new TYPO3.CMS.Backend.FormEngine();
+}
+
+declare module 'TYPO3/CMS/Backend/Modal' {
+  export = new TYPO3.CMS.Backend.Modal();
+}
+
+declare module 'TYPO3/CMS/Backend/Severity' {
+  export = new TYPO3.CMS.Backend.Severity();
+}
+
 // Type definition for global namespace object
-declare var TYPO3: any;
+interface Window {
+  TYPO3: any;
+}
+
+/**
+ * Needed type declarations for provided libs
+ */
+declare module 'TYPO3/CMS/Core/Contrib/imagesloaded.pkgd.min' {
+  import * as imagesloaded from 'imagesloaded';
+  export = imagesloaded;
+}
index efe5d1b..afc9d2d 100644 (file)
@@ -11,8 +11,8 @@
  * The TYPO3 project - inspiring people to share!
  */
 
-/// <amd-dependency path="TYPO3/CMS/Core/Contrib/jquery.minicolors">
 import $ = require('jquery');
+import 'TYPO3/CMS/Core/Contrib/jquery.minicolors';
 
 /**
  * Module: TYPO3/CMS/Backend/ColorPicker
@@ -36,18 +36,17 @@ class ColorPicker {
    * Initialize the color picker for the given selector
    */
   public initialize(): void {
-    (<any> $(this.selector)).minicolors({
+    ($(this.selector) as any).minicolors({
       format: 'hex',
       position: 'bottom left',
       theme: 'bootstrap',
     });
-    (<any> $(document)).on('change', '.t3js-colorpicker-value-trigger', function(): void {
-      (<any> $(this))
-        .closest('.t3js-formengine-field-item')
-        .find('.t3js-color-picker')
-        .val(this.value)
-        .trigger('paste');
-      (<any> $(this)).val('');
+    $(document).on('change', '.t3js-colorpicker-value-trigger', function(this: HTMLFormElement): void {
+      $(this).closest('.t3js-formengine-field-item')
+             .find('.t3js-color-picker')
+             .val(this.value)
+             .trigger('paste');
+      $(this).val('');
     });
   }
 }
index b20651c..6bee75f 100644 (file)
  * The TYPO3 project - inspiring people to share!
  */
 
-/// <amd-dependency path="bootstrap">
-
-// todo: once FormEngine is a native TypeScript class, we can use require() instead
-// and drop amd-dependency and declare
-/// <amd-dependency path="TYPO3/CMS/Backend/FormEngine" name="FormEngine">
-declare let FormEngine: any;
-declare let TYPO3: any;
-
+import 'bootstrap';
+import FormEngine = require('TYPO3/CMS/Backend/FormEngine');
 import $ = require('jquery');
 
 /**
@@ -27,141 +21,141 @@ import $ = require('jquery');
  * @exports TYPO3/CMS/Backend/FormEngineReview
  */
 class FormEngineReview {
-    /**
-     * Fetches all fields that have a failed validation
-     *
-     * @return {$}
-     */
-    public static findInvalidField(): any {
-        return $(document).find('.tab-content .' + FormEngine.Validation.errorClass);
-    }
+  /**
+   * Fetches all fields that have a failed validation
+   *
+   * @return {$}
+   */
+  public static findInvalidField(): any {
+    return $(document).find('.tab-content .' + FormEngine.Validation.errorClass);
+  }
+
+  /**
+   * Renders an invisible button to toggle the review panel into the least possible toolbar
+   *
+   * @param {Object} context
+   */
+  public static attachButtonToModuleHeader(context: any): void {
+    const $leastButtonBar: any = $('.t3js-module-docheader-bar-buttons').children().last().find('[role="toolbar"]');
+    const $button: any = $('<a />', {
+      class: 'btn btn-danger btn-sm hidden ' + context.toggleButtonClass,
+      href: '#',
+      title: TYPO3.lang['buttons.reviewFailedValidationFields'],
+    }).append(
+      $('<span />', {class: 'fa fa-fw fa-info'}),
+    );
+
+    $button.popover({
+      container: 'body',
+      html: true,
+      placement: 'bottom',
+    });
+
+    $leastButtonBar.prepend($button);
+  }
+
+  /**
+   * Class for the toggle button
+   */
+  private toggleButtonClass: string;
+
+  /**
+   * Class for field list items
+   */
+  private fieldListItemClass: string;
+
+  /**
+   * Class of FormEngine labels
+   */
+  private labelSelector: string;
+
+  /**
+   * The constructor, set the class properties default values
+   */
+  constructor() {
+    this.toggleButtonClass = 't3js-toggle-review-panel';
+    this.fieldListItemClass = 't3js-field-item';
+    this.labelSelector = '.t3js-formengine-label';
+
+    this.initialize();
+  }
+
+  /**
+   * Initialize the events
+   */
+  public initialize(): void {
+    const me: any = this;
+    const $document: any = $(document);
+
+    $((): void => {
+      FormEngineReview.attachButtonToModuleHeader(me);
+    });
+    $document.on('click', '.' + this.fieldListItemClass, this.switchToField);
+    $document.on('t3-formengine-postfieldvalidation', this.checkForReviewableField);
+  }
+
+  /**
+   * Checks if fields have failed validation. In such case, the markup is rendered and the toggle button is unlocked.
+   */
+  public checkForReviewableField = (): void => {
+    const me: any = this;
+    const $invalidFields: any = FormEngineReview.findInvalidField();
+    const $toggleButton: any = $('.' + this.toggleButtonClass);
+
+    if ($invalidFields.length > 0) {
+      const $list: any = $('<div />', {class: 'list-group'});
+
+      $invalidFields.each(function(this: Element): void {
+        const $field: any = $(this);
+        const $input: any = $field.find('[data-formengine-validation-rules]');
+        let inputId: any = $input.attr('id');
+
+        if (typeof inputId === 'undefined') {
+          inputId = $input.parent().children('[id]').first().attr('id');
+        }
 
-    /**
-     * Renders an invisible button to toggle the review panel into the least possible toolbar
-     *
-     * @param {Object} context
-     */
-    public static attachButtonToModuleHeader(context: any): void {
-        let $leastButtonBar: any = $('.t3js-module-docheader-bar-buttons').children().last().find('[role="toolbar"]');
-        let $button: any = $('<a />', {
-            'class': 'btn btn-danger btn-sm hidden ' + context.toggleButtonClass,
-            href: '#',
-            title: TYPO3.lang['buttons.reviewFailedValidationFields'],
-        }).append(
-            $('<span />', {'class': 'fa fa-fw fa-info'})
+        $list.append(
+          $('<a />', {
+            'class': 'list-group-item ' + me.fieldListItemClass,
+            'data-field-id': inputId,
+            'href': '#',
+          }).text($field.find(me.labelSelector).text()),
         );
-
-        $button.popover({
-            container: 'body',
-            html: true,
-            placement: 'bottom',
-        });
-
-        $leastButtonBar.prepend($button);
+      });
+
+      $toggleButton.removeClass('hidden');
+
+      // Bootstrap has no official API to update the content of a popover w/o destroying it
+      const $popover: any = $toggleButton.data('bs.popover');
+      if ($popover) {
+        $popover.options.content = $list.wrapAll('<div>').parent().html();
+        $popover.setContent();
+        $popover.$tip.addClass($popover.options.placement);
+      }
+    } else {
+      $toggleButton.addClass('hidden').popover('hide');
     }
-
-    /**
-     * Class for the toggle button
-     */
-    private toggleButtonClass: string;
-
-    /**
-     * Class for field list items
-     */
-    private fieldListItemClass: string;
-
-    /**
-     * Class of FormEngine labels
-     */
-    private labelSelector: string;
-
-    /**
-     * The constructor, set the class properties default values
-     */
-    constructor() {
-        this.toggleButtonClass = 't3js-toggle-review-panel';
-        this.fieldListItemClass = 't3js-field-item';
-        this.labelSelector = '.t3js-formengine-label';
-
-        this.initialize();
-    }
-
-    /**
-     * Initialize the events
-     */
-    public initialize(): void {
-        let me: any = this;
-        let $document: any = $(document);
-
-        $(function(): void {
-            FormEngineReview.attachButtonToModuleHeader(me);
-        });
-        $document.on('click', '.' + this.fieldListItemClass, this.switchToField);
-        $document.on('t3-formengine-postfieldvalidation', this.checkForReviewableField);
-    }
-
-    /**
-     * Checks if fields have failed validation. In such case, the markup is rendered and the toggle button is unlocked.
-     */
-    public checkForReviewableField = (): void => {
-        let me: any = this;
-        let $invalidFields: any = FormEngineReview.findInvalidField();
-        let $toggleButton: any = $('.' + this.toggleButtonClass);
-
-        if ($invalidFields.length > 0) {
-            let $list: any = $('<div />', {'class': 'list-group'});
-
-            $invalidFields.each(function(): void {
-                let $field: any = $(this);
-                let $input: any = $field.find('[data-formengine-validation-rules]');
-                let inputId: any = $input.attr('id');
-
-                if (typeof inputId === 'undefined') {
-                    inputId = $input.parent().children('[id]').first().attr('id');
-                }
-
-                $list.append(
-                    $('<a />', {
-                        href: '#',
-                        'class': 'list-group-item ' + me.fieldListItemClass,
-                        'data-field-id': inputId,
-                    }).text($field.find(me.labelSelector).text())
-                );
-            });
-
-            $toggleButton.removeClass('hidden');
-
-            // Bootstrap has no official API to update the content of a popover w/o destroying it
-            let $popover: any = $toggleButton.data('bs.popover');
-            if ($popover) {
-              $popover.options.content = $list.wrapAll('<div>').parent().html();
-              $popover.setContent();
-              $popover.$tip.addClass($popover.options.placement);
-            }
-        } else {
-            $toggleButton.addClass('hidden').popover('hide');
-        }
-    };
-
-    /**
-     * Finds the field in the form and focuses it
-     *
-     * @param {Event} e
-     */
-    public switchToField = (e: Event): void => {
-        e.preventDefault();
-
-        let $listItem: any = $(e.currentTarget);
-        let referenceFieldId: string = $listItem.data('fieldId');
-        let $referenceField: any = $('#' + referenceFieldId);
-
-        // Iterate possibly nested tab panels
-        $referenceField.parents('[id][role="tabpanel"]').each(function(): void {
-            $('[aria-controls="' + $(this).attr('id') + '"]').tab('show');
-        });
-
-        $referenceField.focus();
-    };
+  }
+
+  /**
+   * Finds the field in the form and focuses it
+   *
+   * @param {Event} e
+   */
+  public switchToField = (e: Event): void => {
+    e.preventDefault();
+
+    const $listItem: any = $(e.currentTarget);
+    const referenceFieldId: string = $listItem.data('fieldId');
+    const $referenceField: any = $('#' + referenceFieldId);
+
+    // Iterate possibly nested tab panels
+    $referenceField.parents('[id][role="tabpanel"]').each(function(this: Element): void {
+      $('[aria-controls="' + $(this).attr('id') + '"]').tab('show');
+    });
+
+    $referenceField.focus();
+  }
 }
 
 // Create an instance and return it
index 8dea2d0..43528a8 100644 (file)
  * The TYPO3 project - inspiring people to share!
  */
 
-/// <amd-dependency path='TYPO3/CMS/Core/Contrib/imagesloaded.pkgd.min' name='ImagesLoaded'>
-/// <amd-dependency path='TYPO3/CMS/Backend/Modal' name='Modal'>
-
 import $ = require('jquery');
 import 'jquery-ui/draggable';
 import 'jquery-ui/resizable';
-declare const Modal: any;
-declare const ImagesLoaded: any;
+import Modal = require('TYPO3/CMS/Backend/Modal');
+import ImagesLoaded = require('TYPO3/CMS/Core/Contrib/imagesloaded.pkgd.min');
 
-declare global {
-  interface Window {
-    TYPO3: any;
-  }
-}
-
-type Area = {
+interface Area {
   x: number;
   y: number;
   height: number;
   width: number;
 }
 
-type Ratio = {
+interface Ratio {
   id: string;
   title: string;
   value: number;
 }
 
-type CropVariant = {
+interface CropVariant {
   title: string;
   id: string;
   selectedRatio: string;
   cropArea?: Area;
   focusArea?: Area;
   coverAreas?: Area[];
-  allowedAspectRatios: Ratio[];
+  allowedAspectRatios: {[key: string]: Ratio};
 }
 
-type Offset = {
+interface Offset {
   left: number;
   top: number;
-};
+}
 
 interface CropperEvent {
   x: number;
@@ -103,7 +94,7 @@ class ImageManipulation {
    * @public
    * @static
    */
-  public static wait(fn: Function, ms: number): void {
+  public static wait(fn: () => void, ms: number): void {
     window.setTimeout(fn, ms);
   }
 
@@ -125,7 +116,7 @@ class ImageManipulation {
    * @param {Object} cropVariants
    * @returns string
    */
-  private static serializeCropVariants(cropVariants: Object): string {
+  private static serializeCropVariants(cropVariants: object): string {
     const omitUnused: any = (key: any, value: any): any =>
       (
         key === 'id'
@@ -148,24 +139,24 @@ class ImageManipulation {
   private aspectRatioTrigger: JQuery;
   private cropperCanvas: JQuery;
   private cropInfo: JQuery;
-  private cropImageContainerSelector: string = '#t3js-crop-image-container';
+  private cropImageContainerSelector = '#t3js-crop-image-container';
   private imageOriginalSizeFactor: number;
-  private cropImageSelector: string = '#t3js-crop-image';
-  private coverAreaSelector: string = '.t3js-cropper-cover-area';
-  private cropInfoSelector: string = '.t3js-cropper-info-crop';
-  private focusAreaSelector: string = '#t3js-cropper-focus-area';
+  private cropImageSelector = '#t3js-crop-image';
+  private coverAreaSelector = '.t3js-cropper-cover-area';
+  private cropInfoSelector = '.t3js-cropper-info-crop';
+  private focusAreaSelector = '#t3js-cropper-focus-area';
   private focusArea: any;
   private cropBox: JQuery;
   private cropper: any;
   private currentCropVariant: CropVariant;
-  private data: Object;
+  private data: any;
   private defaultFocusArea: Area = {
     height: 1 / 3,
     width: 1 / 3,
     x: 0,
     y: 0,
   };
-  private defaultOpts: Object = {
+  private defaultOpts: object = {
     autoCrop: true,
     autoCropArea: '0.7',
     dragMode: 'crop',
@@ -174,7 +165,7 @@ class ImageManipulation {
     viewMode: 1,
     zoomable: false,
   };
-  private resizeTimeout: number = 450;
+  private resizeTimeout = 450;
 
   constructor() {
     // Silence is golden
@@ -197,7 +188,7 @@ class ImageManipulation {
    * @public
    */
   public initializeTrigger(): void {
-    const triggerHandler: Function = (e: JQueryEventObject): void => {
+    const triggerHandler = (e: JQueryEventObject): void => {
       e.preventDefault();
       this.trigger = $(e.currentTarget);
       this.show();
@@ -212,7 +203,7 @@ class ImageManipulation {
    */
   private initializeCropperModal(): void {
     const image: JQuery = this.currentModal.find(this.cropImageSelector);
-    ImagesLoaded(image, (): void => {
+    ImagesLoaded(image as any, (): void => {
       setTimeout((): void => {
         this.init();
       }, 100);
@@ -230,7 +221,7 @@ class ImageManipulation {
     const buttonDismissText: string = this.trigger.data('buttonDismissText');
     const buttonSaveText: string = this.trigger.data('buttonSaveText');
     const imageUri: string = this.trigger.data('url');
-    const initCropperModal: Function = this.initializeCropperModal.bind(this);
+    const initCropperModal: ()  => void = this.initializeCropperModal.bind(this);
 
     /**
      * Open modal with image to crop
@@ -242,7 +233,7 @@ class ImageManipulation {
         {
           btnClass: 'btn-default pull-left',
           dataAttributes: {
-              method: 'preview',
+            method: 'preview',
           },
           icon: 'actions-view',
           text: buttonPreviewText,
@@ -250,7 +241,7 @@ class ImageManipulation {
         {
           btnClass: 'btn-default',
           dataAttributes: {
-              method: 'dismiss',
+            method: 'dismiss',
           },
           icon: 'actions-close',
           text: buttonDismissText,
@@ -258,7 +249,7 @@ class ImageManipulation {
         {
           btnClass: 'btn-primary',
           dataAttributes: {
-              method: 'save',
+            method: 'save',
           },
           icon: 'actions-document-save',
           text: buttonSaveText,
@@ -266,7 +257,7 @@ class ImageManipulation {
       ],
       callback: (currentModal: JQuery): void => {
         currentModal.find('.t3js-modal-body')
-          .addClass('cropper');
+                    .addClass('cropper');
       },
       content: imageUri,
       size: Modal.sizes.full,
@@ -309,7 +300,7 @@ class ImageManipulation {
     this.resetButton = this.currentModal.find('[data-method=reset]');
     this.cropperCanvas = this.currentModal.find('#js-crop-canvas');
     this.aspectRatioTrigger = this.currentModal.find('[data-method=setAspectRatio]');
-    this.currentCropVariant = this.data[this.activeCropVariantTrigger.attr('data-crop-variant-id')];
+    this.currentCropVariant = (this as any).data[this.activeCropVariantTrigger.attr('data-crop-variant-id')];
 
     /**
      * Assign EventListener to cropVariantTriggers
@@ -329,7 +320,7 @@ class ImageManipulation {
       this.activeCropVariantTrigger.removeClass('is-active');
       $(e.currentTarget).addClass('is-active');
       this.activeCropVariantTrigger = $(e.currentTarget);
-      let cropVariant: CropVariant = this.data[this.activeCropVariantTrigger.attr('data-crop-variant-id')];
+      const cropVariant: CropVariant = this.data[this.activeCropVariantTrigger.attr('data-crop-variant-id')];
       const imageData: CropperImageData = this.cropper.cropper('getImageData');
       cropVariant.cropArea = this.convertRelativeToAbsoluteCropArea(cropVariant.cropArea, imageData);
       this.currentCropVariant = $.extend(true, {}, cropVariant);
@@ -406,7 +397,7 @@ class ImageManipulation {
      * The top.require is now inlined @see ImageManipulationElemen.php:143
      * TODO: Find a better solution for cross iframe communications
      */
-    this.cropper = (<any> top.TYPO3.jQuery(image)).cropper($.extend(this.defaultOpts, {
+    this.cropper = (top.TYPO3.jQuery(image) as any).cropper($.extend(this.defaultOpts, {
       built: this.cropBuiltHandler,
       crop: this.cropMoveHandler,
       cropend: this.cropEndHandler,
@@ -431,7 +422,7 @@ class ImageManipulation {
       const cropVariantId: string = $(elem).attr('data-crop-variant-id');
       const cropArea: Area = this.convertRelativeToAbsoluteCropArea(
         this.data[cropVariantId].cropArea,
-        imageData
+        imageData,
       );
       const variant: CropVariant = $.extend(true, {}, this.data[cropVariantId], {cropArea});
       this.updatePreviewThumbnail(variant, $(elem));
@@ -439,7 +430,7 @@ class ImageManipulation {
 
     this.currentCropVariant.cropArea = this.convertRelativeToAbsoluteCropArea(
       this.currentCropVariant.cropArea,
-      imageData
+      imageData,
     );
     // Can't use .t3js-* as selector because it is an extraneous selector
     this.cropBox = this.currentModal.find('.cropper-crop-box');
@@ -470,7 +461,7 @@ class ImageManipulation {
     }
 
     this.cropperCanvas.addClass('is-visible');
-  };
+  }
 
   /**
    * @method cropMoveHandler
@@ -489,7 +480,7 @@ class ImageManipulation {
     const naturalWidth: number = Math.round(this.currentCropVariant.cropArea.width * this.imageOriginalSizeFactor);
     const naturalHeight: number = Math.round(this.currentCropVariant.cropArea.height * this.imageOriginalSizeFactor);
     this.cropInfo.text(`${naturalWidth}×${naturalHeight} px`);
-  };
+  }
 
   /**
    * @method cropStartHandler
@@ -501,7 +492,7 @@ class ImageManipulation {
       this.focusArea.draggable('option', 'disabled', true);
       this.focusArea.resizable('option', 'disabled', true);
     }
-  };
+  }
 
   /**
    * @method cropEndHandler
@@ -513,7 +504,7 @@ class ImageManipulation {
       this.focusArea.draggable('option', 'disabled', false);
       this.focusArea.resizable('option', 'disabled', false);
     }
-  };
+  }
 
   /**
    * @method update
@@ -567,97 +558,98 @@ class ImageManipulation {
     this.focusArea = $('<div id="t3js-cropper-focus-area" class="cropper-focus-area"></div>');
     container.append(this.focusArea);
     this.focusArea
-      .draggable({
-        containment: container,
-        create: (): void => {
-          this.scaleAndMoveFocusArea(this.currentCropVariant.focusArea);
-        },
-        drag: (): void => {
-          const {left, top}: Offset = container.offset();
-          const {left: fLeft, top: fTop}: Offset = this.focusArea.offset();
-          const {focusArea, coverAreas}: {focusArea?: Area, coverAreas?: Area[]} = this.currentCropVariant;
-
-          focusArea.x = (fLeft - left) / container.width();
-          focusArea.y = (fTop - top) / container.height();
-          this.updatePreviewThumbnail(this.currentCropVariant, this.activeCropVariantTrigger);
-          if (this.checkFocusAndCoverAreasCollision(focusArea, coverAreas)) {
-            this.focusArea.addClass('has-nodrop');
-          } else {
-            this.focusArea.removeClass('has-nodrop');
-          }
-        },
-        revert: (): boolean => {
-          const revertDelay: number = 250;
-          const {left, top}: Offset = container.offset();
-          const {left: fLeft, top: fTop}: Offset = this.focusArea.offset();
-          const {focusArea, coverAreas}: {focusArea?: Area, coverAreas?: Area[]} = this.currentCropVariant;
-
-          if (this.checkFocusAndCoverAreasCollision(focusArea, coverAreas)) {
-            this.focusArea.removeClass('has-nodrop');
-            ImageManipulation.wait((): void => {
-              focusArea.x = (fLeft - left) / container.width();
-              focusArea.y = (fTop - top) / container.height();
-              this.updateCropVariantData(this.currentCropVariant);
-            }, revertDelay);
-            return true;
-          }
-        },
-        revertDuration: 200,
-        stop: (): void => {
-          const {left, top}: Offset = container.offset();
-          const {left: fLeft, top: fTop}: Offset = this.focusArea.offset();
-          const {focusArea}: {focusArea?: Area} = this.currentCropVariant;
-
-          focusArea.x = (fLeft - left) / container.width();
-          focusArea.y = (fTop - top) / container.height();
-
-          this.scaleAndMoveFocusArea(focusArea);
-        },
-      })
-      .resizable({
-        containment: container,
-        handles: 'all',
-        resize: (): void => {
-          const {left, top}: Offset = container.offset();
-          const {left: fLeft, top: fTop}: Offset = this.focusArea.offset();
-          const {focusArea, coverAreas}: {focusArea?: Area, coverAreas?: Area[]} = this.currentCropVariant;
-
-          focusArea.height = this.focusArea.height() / container.height();
-          focusArea.width = this.focusArea.width() / container.width();
-          focusArea.x = (fLeft - left) / container.width();
-          focusArea.y = (fTop - top) / container.height();
-          this.updatePreviewThumbnail(this.currentCropVariant, this.activeCropVariantTrigger);
-
-          if (this.checkFocusAndCoverAreasCollision(focusArea, coverAreas)) {
-            this.focusArea.addClass('has-nodrop');
-          } else {
-            this.focusArea.removeClass('has-nodrop');
-          }
+        .draggable({
+          containment: container,
+          create: (): void => {
+            this.scaleAndMoveFocusArea(this.currentCropVariant.focusArea);
+          },
+          drag: (): void => {
+            const {left, top}: Offset = container.offset();
+            const {left: fLeft, top: fTop}: Offset = this.focusArea.offset();
+            const {focusArea, coverAreas}: {focusArea?: Area, coverAreas?: Area[]} = this.currentCropVariant;
+
+            focusArea.x = (fLeft - left) / container.width();
+            focusArea.y = (fTop - top) / container.height();
+            this.updatePreviewThumbnail(this.currentCropVariant, this.activeCropVariantTrigger);
+            if (this.checkFocusAndCoverAreasCollision(focusArea, coverAreas)) {
+              this.focusArea.addClass('has-nodrop');
+            } else {
+              this.focusArea.removeClass('has-nodrop');
+            }
+          },
+          revert: (): boolean => {
+            const revertDelay = 250;
+            const {left, top}: Offset = container.offset();
+            const {left: fLeft, top: fTop}: Offset = this.focusArea.offset();
+            const {focusArea, coverAreas}: {focusArea?: Area, coverAreas?: Area[]} = this.currentCropVariant;
 
-        },
-        stop: (event: any, ui: any): void => {
-          const revertDelay: number = 250;
-          const {left, top}: Offset = container.offset();
-          const {left: fLeft, top: fTop}: Offset = this.focusArea.offset();
-          const {focusArea, coverAreas}: {focusArea?: Area, coverAreas?: Area[]} = this.currentCropVariant;
+            if (this.checkFocusAndCoverAreasCollision(focusArea, coverAreas)) {
+              this.focusArea.removeClass('has-nodrop');
+              ImageManipulation.wait((): void => {
+                focusArea.x = (fLeft - left) / container.width();
+                focusArea.y = (fTop - top) / container.height();
+                this.updateCropVariantData(this.currentCropVariant);
+              }, revertDelay);
+              return true;
+            }
+            return false;
+          },
+          revertDuration: 200,
+          stop: (): void => {
+            const {left, top}: Offset = container.offset();
+            const {left: fLeft, top: fTop}: Offset = this.focusArea.offset();
+            const {focusArea}: {focusArea?: Area} = this.currentCropVariant;
 
-          if (this.checkFocusAndCoverAreasCollision(focusArea, coverAreas)) {
-            ui.element.animate($.extend(ui.originalPosition, ui.originalSize), revertDelay, (): void => {
+            focusArea.x = (fLeft - left) / container.width();
+            focusArea.y = (fTop - top) / container.height();
 
-              focusArea.height = this.focusArea.height() / container.height();
-              focusArea.height = this.focusArea.height() / container.height();
-              focusArea.width = this.focusArea.width() / container.width();
-              focusArea.x = (fLeft - left) / container.width();
-              focusArea.y = (fTop - top) / container.height();
+            this.scaleAndMoveFocusArea(focusArea);
+          },
+        })
+        .resizable({
+          containment: container,
+          handles: 'all',
+          resize: (): void => {
+            const {left, top}: Offset = container.offset();
+            const {left: fLeft, top: fTop}: Offset = this.focusArea.offset();
+            const {focusArea, coverAreas}: {focusArea?: Area, coverAreas?: Area[]} = this.currentCropVariant;
+
+            focusArea.height = this.focusArea.height() / container.height();
+            focusArea.width = this.focusArea.width() / container.width();
+            focusArea.x = (fLeft - left) / container.width();
+            focusArea.y = (fTop - top) / container.height();
+            this.updatePreviewThumbnail(this.currentCropVariant, this.activeCropVariantTrigger);
+
+            if (this.checkFocusAndCoverAreasCollision(focusArea, coverAreas)) {
+              this.focusArea.addClass('has-nodrop');
+            } else {
+              this.focusArea.removeClass('has-nodrop');
+            }
 
+          },
+          stop: (event: any, ui: any): void => {
+            const revertDelay = 250;
+            const {left, top}: Offset = container.offset();
+            const {left: fLeft, top: fTop}: Offset = this.focusArea.offset();
+            const {focusArea, coverAreas}: {focusArea?: Area, coverAreas?: Area[]} = this.currentCropVariant;
+
+            if (this.checkFocusAndCoverAreasCollision(focusArea, coverAreas)) {
+              ui.element.animate($.extend(ui.originalPosition, ui.originalSize), revertDelay, (): void => {
+
+                focusArea.height = this.focusArea.height() / container.height();
+                focusArea.height = this.focusArea.height() / container.height();
+                focusArea.width = this.focusArea.width() / container.width();
+                focusArea.x = (fLeft - left) / container.width();
+                focusArea.y = (fTop - top) / container.height();
+
+                this.scaleAndMoveFocusArea(focusArea);
+                this.focusArea.removeClass('has-nodrop');
+              });
+            } else {
               this.scaleAndMoveFocusArea(focusArea);
-              this.focusArea.removeClass('has-nodrop');
-            });
-          } else {
-            this.scaleAndMoveFocusArea(focusArea);
-          }
-        },
-      });
+            }
+          },
+        });
   }
 
   /**
@@ -668,7 +660,7 @@ class ImageManipulation {
    */
   private initCoverAreas(container: JQuery, coverAreas: Area[]): void {
     coverAreas.forEach((coverArea: Area): void => {
-      let coverAreaCanvas: JQuery = $('<div class="cropper-cover-area t3js-cropper-cover-area"></div>');
+      const coverAreaCanvas: JQuery = $('<div class="cropper-cover-area t3js-cropper-cover-area"></div>');
       container.append(coverAreaCanvas);
       coverAreaCanvas.css({
         height: ImageManipulation.toCssPercent(coverArea.height),
@@ -808,12 +800,10 @@ class ImageManipulation {
     return coverAreas
       .some((coverArea: Area): boolean => {
         // noinspection OverlyComplexBooleanExpressionJS
-        if (focusArea.x < coverArea.x + coverArea.width &&
-          focusArea.x + focusArea.width > coverArea.x &&
-          focusArea.y < coverArea.y + coverArea.height &&
-          focusArea.height + focusArea.y > coverArea.y) {
-          return true;
-        }
+        return (focusArea.x < coverArea.x + coverArea.width &&
+           focusArea.x + focusArea.width > coverArea.x &&
+            focusArea.y < coverArea.y + coverArea.height &&
+           focusArea.height + focusArea.y > coverArea.y);
       });
   }
 
@@ -856,9 +846,9 @@ class ImageManipulation {
    * @desc Updates the preview images in the editing section with the respective crop variants
    * @param {Object} data - The internal crop variants state
    */
-  private setPreviewImages(data: Object): void {
-    let $image: any = this.cropper;
-    let imageData: CropperImageData = $image.cropper('getImageData');
+  private setPreviewImages(data: {[key: string]: CropVariant}): void {
+    const $image: any = this.cropper;
+    const imageData: CropperImageData = $image.cropper('getImageData');
 
     // Iterate over the crop variants and set up their respective preview
     Object.keys(data).forEach((cropVariantId: string) => {
@@ -866,11 +856,11 @@ class ImageManipulation {
       const cropData: Area = this.convertRelativeToAbsoluteCropArea(cropVariant.cropArea, imageData);
 
       const $preview: JQuery = this.trigger
-        .closest('.form-group')
-        .find(`.t3js-image-manipulation-preview[data-crop-variant-id="${cropVariantId}"]`);
+                                   .closest('.form-group')
+                                   .find(`.t3js-image-manipulation-preview[data-crop-variant-id="${cropVariantId}"]`);
       const $previewSelectedRatio: JQuery = this.trigger
-        .closest('.form-group')
-        .find(`.t3js-image-manipulation-selected-ratio[data-crop-variant-id="${cropVariantId}"]`);
+                                                .closest('.form-group')
+                                                .find(`.t3js-image-manipulation-selected-ratio[data-crop-variant-id="${cropVariantId}"]`); // tslint:disable-line:max-line-length
 
       if ($preview.length === 0) {
         return;
@@ -880,8 +870,8 @@ class ImageManipulation {
       let previewHeight: number = $preview.data('preview-height');
 
       // Adjust aspect ratio of preview width/height
-      let aspectRatio: number = cropData.width / cropData.height;
-      let tmpHeight: number = previewWidth / aspectRatio;
+      const aspectRatio: number = cropData.width / cropData.height;
+      const tmpHeight: number = previewWidth / aspectRatio;
       if (tmpHeight > previewHeight) {
         previewWidth = previewHeight * aspectRatio;
       } else {
@@ -895,9 +885,7 @@ class ImageManipulation {
 
       const ratio: number = previewWidth / cropData.width;
       const $viewBox: JQuery = $('<div />').html('<img src="' + $image.attr('src') + '">');
-      const $ratioTitleText: JQuery = this.currentModal.find(
-        `.t3-js-ratio-title[data-ratio-id="${cropVariant.id}${cropVariant.selectedRatio}"]`
-      );
+      const $ratioTitleText: JQuery = this.currentModal.find(`.t3-js-ratio-title[data-ratio-id="${cropVariant.id}${cropVariant.selectedRatio}"]`); // tslint:disable-line:max-line-length
       $previewSelectedRatio.text($ratioTitleText.text());
       $viewBox.addClass('cropper-preview-container');
       $preview.empty().append($viewBox);
@@ -910,7 +898,7 @@ class ImageManipulation {
         width: imageData.naturalWidth * ratio,
       });
     });
-  };
+  }
 
   /**
    * @method openPreview
@@ -918,7 +906,7 @@ class ImageManipulation {
    * @param {object} data - The whole data object containing all the cropVariants
    * @private
    */
-  private openPreview(data: Object): void {
+  private openPreview(data: object): void {
     const cropVariants: string = ImageManipulation.serializeCropVariants(data);
     let previewUrl: string = this.trigger.attr('data-preview-url');
     previewUrl = previewUrl + '&cropVariants=' + encodeURIComponent(cropVariants);
@@ -931,7 +919,7 @@ class ImageManipulation {
    * @param {object} data - The whole data object containing all the cropVariants
    * @private
    */
-  private save(data: Object): void {
+  private save(data: {[key: string]: CropVariant}): void {
     const cropVariants: string = ImageManipulation.serializeCropVariants(data);
     const hiddenField: JQuery = $(`#${this.trigger.attr('data-field')}`);
     this.trigger.attr('data-crop-variants', JSON.stringify(data));
@@ -960,7 +948,7 @@ class ImageManipulation {
    * @param {Function} fn - The function to call on resize completion
    * @private
    */
-  private resizeEnd(fn: Function): void {
+  private resizeEnd(fn: () => void): void {
     let timer: number;
     $(window).on('resize', (): void => {
       clearTimeout(timer);
index 0c5fe54..b2f11b5 100644 (file)
@@ -11,7 +11,7 @@
  * The TYPO3 project - inspiring people to share!
  */
 
-/// <amd-dependency path="bootstrap">
+import 'bootstrap';
 import $ = require('jquery');
 
 /**
@@ -56,11 +56,11 @@ class Popover {
    */
   public setOptions($element: JQuery, options?: PopoverOptions): void {
     options = options || {};
-    let title: string|Function = options.title || $element.data('title') || '';
-    let content: string|Function = options.content || $element.data('content') || '';
+    const title: string|(() => void) = options.title || $element.data('title') || '';
+    const content: string|(() => void) = options.content || $element.data('content') || '';
     $element
-      .attr('data-original-title', (<string> title))
-      .attr('data-content', (<string> content))
+      .attr('data-original-title', (title as string))
+      .attr('data-content', (content as string))
       .attr('data-placement', 'auto')
       .popover(options);
   }
@@ -119,10 +119,9 @@ class Popover {
 }
 
 // Create an instance, initialize and return it
-let popover: Popover = new Popover();
+const popover: Popover = new Popover();
 popover.initialize();
 
 // @deprecated since TYPO3 v9, will be removed in TYPO3 v10 prevent global object usage
-declare var TYPO3: any;
 TYPO3.Popover = popover;
 export = popover;
index 7661835..ac9bb01 100644 (file)
  * The TYPO3 project - inspiring people to share!
  */
 
-/// <amd-dependency path='TYPO3/CMS/Backend/Modal' name='Modal'>
-/// <amd-dependency path='TYPO3/CMS/Backend/Severity' name='Severity'>
-
 import $ = require('jquery');
-declare const Modal: any;
-declare const Severity: any;
-declare const TYPO3: any;
+import Modal = require('TYPO3/CMS/Backend/Modal');
+import Severity = require('TYPO3/CMS/Backend/Severity');
 
 /**
  * Module: TYPO3/CMS/Backend/RenameFile
@@ -31,7 +27,7 @@ class RenameFile {
   }
 
   public initialize(): void {
-    (<any> $('.t3js-submit-file-rename')).on('click', this.checkForDuplicate);
+    $('.t3js-submit-file-rename').on('click', this.checkForDuplicate);
   }
 
   private checkForDuplicate(e: any): void {
@@ -48,16 +44,16 @@ class RenameFile {
         fileName: fileNameField.val(),
         fileTarget: form.find('input[name="file[rename][0][destination]"]').val(),
       },
-      success: function (response: any): void {
+      success: (response: any): void => {
         const fileExists: boolean = response !== false;
         const originalFileName: string = fileNameField.data('original');
         const newFileName: string = fileNameField.val();
 
         if (fileExists && originalFileName !== newFileName) {
           const description: string = TYPO3.lang['file_rename.exists.description']
-            .replace('{0}', originalFileName).replace('{1}', newFileName);
+                                           .replace('{0}', originalFileName).replace('{1}', newFileName);
 
-          const modal: boolean = Modal.confirm(
+          const modal: JQuery = Modal.confirm(
             TYPO3.lang['file_rename.exists.title'],
             description,
             Severity.warning,
@@ -80,7 +76,7 @@ class RenameFile {
               },
             ]);
 
-          (<any> modal).on('button.clicked', function (event: any): void {
+          modal.on('button.clicked', (event: any): void => {
             conflictModeField.val(event.target.name);
             form.submit();
             Modal.dismiss();
@@ -91,7 +87,7 @@ class RenameFile {
       },
       url: ajaxUrl,
     });
-  };
+  }
 }
 
 export = new RenameFile();
index 88a3a1a..d676d05 100644 (file)
@@ -34,8 +34,7 @@ define(["require", "exports", "jquery", "TYPO3/CMS/Core/Contrib/jquery.minicolor
                 theme: 'bootstrap',
             });
             $(document).on('change', '.t3js-colorpicker-value-trigger', function () {
-                $(this)
-                    .closest('.t3js-formengine-field-item')
+                $(this).closest('.t3js-formengine-field-item')
                     .find('.t3js-color-picker')
                     .val(this.value)
                     .trigger('paste');
index aebaa64..c15754d 100644 (file)
@@ -31,7 +31,7 @@ define(["require", "exports", "TYPO3/CMS/Backend/FormEngine", "jquery", "bootstr
                 var $invalidFields = FormEngineReview.findInvalidField();
                 var $toggleButton = $('.' + _this.toggleButtonClass);
                 if ($invalidFields.length > 0) {
-                    var $list_1 = $('<div />', { 'class': 'list-group' });
+                    var $list_1 = $('<div />', { class: 'list-group' });
                     $invalidFields.each(function () {
                         var $field = $(this);
                         var $input = $field.find('[data-formengine-validation-rules]');
@@ -40,9 +40,9 @@ define(["require", "exports", "TYPO3/CMS/Backend/FormEngine", "jquery", "bootstr
                             inputId = $input.parent().children('[id]').first().attr('id');
                         }
                         $list_1.append($('<a />', {
-                            href: '#',
                             'class': 'list-group-item ' + me.fieldListItemClass,
                             'data-field-id': inputId,
+                            'href': '#',
                         }).text($field.find(me.labelSelector).text()));
                     });
                     $toggleButton.removeClass('hidden');
@@ -95,10 +95,10 @@ define(["require", "exports", "TYPO3/CMS/Backend/FormEngine", "jquery", "bootstr
         FormEngineReview.attachButtonToModuleHeader = function (context) {
             var $leastButtonBar = $('.t3js-module-docheader-bar-buttons').children().last().find('[role="toolbar"]');
             var $button = $('<a />', {
-                'class': 'btn btn-danger btn-sm hidden ' + context.toggleButtonClass,
+                class: 'btn btn-danger btn-sm hidden ' + context.toggleButtonClass,
                 href: '#',
                 title: TYPO3.lang['buttons.reviewFailedValidationFields'],
-            }).append($('<span />', { 'class': 'fa fa-fw fa-info' }));
+            }).append($('<span />', { class: 'fa fa-fw fa-info' }));
             $button.popover({
                 container: 'body',
                 html: true,
index 0cad2a6..1a1a399 100644 (file)
@@ -10,7 +10,7 @@
  *
  * The TYPO3 project - inspiring people to share!
  */
-define(["require", "exports", "TYPO3/CMS/Core/Contrib/imagesloaded.pkgd.min", "TYPO3/CMS/Backend/Modal", "jquery", "jquery-ui/draggable", "jquery-ui/resizable"], function (require, exports, ImagesLoaded, Modal, $) {
+define(["require", "exports", "jquery", "TYPO3/CMS/Backend/Modal", "TYPO3/CMS/Core/Contrib/imagesloaded.pkgd.min", "jquery-ui/draggable", "jquery-ui/resizable"], function (require, exports, $, Modal, ImagesLoaded) {
     "use strict";
     /**
      * Module: TYPO3/CMS/Backend/ImageManipulation
@@ -479,6 +479,7 @@ define(["require", "exports", "TYPO3/CMS/Core/Contrib/imagesloaded.pkgd.min", "T
                         }, revertDelay);
                         return true;
                     }
+                    return false;
                 },
                 revertDuration: 200,
                 stop: function () {
@@ -667,12 +668,10 @@ define(["require", "exports", "TYPO3/CMS/Core/Contrib/imagesloaded.pkgd.min", "T
             return coverAreas
                 .some(function (coverArea) {
                 // noinspection OverlyComplexBooleanExpressionJS
-                if (focusArea.x < coverArea.x + coverArea.width &&
+                return (focusArea.x < coverArea.x + coverArea.width &&
                     focusArea.x + focusArea.width > coverArea.x &&
                     focusArea.y < coverArea.y + coverArea.height &&
-                    focusArea.height + focusArea.y > coverArea.y) {
-                    return true;
-                }
+                    focusArea.height + focusArea.y > coverArea.y);
             });
         };
         /**
@@ -725,7 +724,7 @@ define(["require", "exports", "TYPO3/CMS/Core/Contrib/imagesloaded.pkgd.min", "T
                     .find(".t3js-image-manipulation-preview[data-crop-variant-id=\"" + cropVariantId + "\"]");
                 var $previewSelectedRatio = _this.trigger
                     .closest('.form-group')
-                    .find(".t3js-image-manipulation-selected-ratio[data-crop-variant-id=\"" + cropVariantId + "\"]");
+                    .find(".t3js-image-manipulation-selected-ratio[data-crop-variant-id=\"" + cropVariantId + "\"]"); // tslint:disable-line:max-line-length
                 if ($preview.length === 0) {
                     return;
                 }
@@ -747,7 +746,7 @@ define(["require", "exports", "TYPO3/CMS/Core/Contrib/imagesloaded.pkgd.min", "T
                 }
                 var ratio = previewWidth / cropData.width;
                 var $viewBox = $('<div />').html('<img src="' + $image.attr('src') + '">');
-                var $ratioTitleText = _this.currentModal.find(".t3-js-ratio-title[data-ratio-id=\"" + cropVariant.id + cropVariant.selectedRatio + "\"]");
+                var $ratioTitleText = _this.currentModal.find(".t3-js-ratio-title[data-ratio-id=\"" + cropVariant.id + cropVariant.selectedRatio + "\"]"); // tslint:disable-line:max-line-length
                 $previewSelectedRatio.text($ratioTitleText.text());
                 $viewBox.addClass('cropper-preview-container');
                 $preview.empty().append($viewBox);
@@ -760,7 +759,6 @@ define(["require", "exports", "TYPO3/CMS/Core/Contrib/imagesloaded.pkgd.min", "T
                 });
             });
         };
-        ;
         /**
          * @method openPreview
          * @desc Opens a preview view with the crop variants
index 9274b45..4e809df 100644 (file)
@@ -112,6 +112,7 @@ define(["require", "exports", "jquery", "bootstrap"], function (require, exports
     // Create an instance, initialize and return it
     var popover = new Popover();
     popover.initialize();
+    // @deprecated since TYPO3 v9, will be removed in TYPO3 v10 prevent global object usage
     TYPO3.Popover = popover;
     return popover;
 });
index add74a0..59b38b9 100644 (file)
@@ -10,7 +10,7 @@
  *
  * The TYPO3 project - inspiring people to share!
  */
-define(["require", "exports", "TYPO3/CMS/Backend/Modal", "TYPO3/CMS/Backend/Severity", "jquery"], function (require, exports, Modal, Severity, $) {
+define(["require", "exports", "jquery", "TYPO3/CMS/Backend/Modal", "TYPO3/CMS/Backend/Severity"], function (require, exports, $, Modal, Severity) {
     "use strict";
     /**
      * Module: TYPO3/CMS/Backend/RenameFile
@@ -74,7 +74,6 @@ define(["require", "exports", "TYPO3/CMS/Backend/Modal", "TYPO3/CMS/Backend/Seve
                 url: ajaxUrl,
             });
         };
-        ;
         return RenameFile;
     }());
     return new RenameFile();