diff --git a/scm-core/src/main/java/sonia/scm/plugin/WebResourceLoader.java b/scm-core/src/main/java/sonia/scm/plugin/WebResourceLoader.java index 94b31ac844..61466c0e2c 100644 --- a/scm-core/src/main/java/sonia/scm/plugin/WebResourceLoader.java +++ b/scm-core/src/main/java/sonia/scm/plugin/WebResourceLoader.java @@ -53,9 +53,11 @@ public interface WebResourceLoader * Returns a {@link URL} for the given path. The method will return null if no * resources could be found for the given path. * + * Note: The path is a web path and uses "/" as path separator + * * @param path resource path * * @return url object for the given path or null */ - public URL getResource(String path); + URL getResource(String path); } diff --git a/scm-plugins/scm-git-plugin/package.json b/scm-plugins/scm-git-plugin/package.json index 7fc8484d75..93ec098597 100644 --- a/scm-plugins/scm-git-plugin/package.json +++ b/scm-plugins/scm-git-plugin/package.json @@ -9,6 +9,6 @@ "@scm-manager/ui-extensions": "^0.0.7" }, "devDependencies": { - "@scm-manager/ui-bundler": "^0.0.13" + "@scm-manager/ui-bundler": "^0.0.15" } } diff --git a/scm-plugins/scm-git-plugin/yarn.lock b/scm-plugins/scm-git-plugin/yarn.lock index 56d3e0ffe2..702e28711f 100644 --- a/scm-plugins/scm-git-plugin/yarn.lock +++ b/scm-plugins/scm-git-plugin/yarn.lock @@ -707,9 +707,9 @@ version "0.0.2" resolved "https://registry.yarnpkg.com/@scm-manager/eslint-config/-/eslint-config-0.0.2.tgz#94cc8c3fb4f51f870b235893dc134fc6c423ae85" -"@scm-manager/ui-bundler@^0.0.13": - version "0.0.13" - resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.13.tgz#020e6c8ee870fccb6c451490cb18972ebfb0d2c4" +"@scm-manager/ui-bundler@^0.0.15": + version "0.0.15" + resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.15.tgz#8ed4a557d5ae38d6b99493b29608fd6a4c9cd917" dependencies: "@babel/core" "^7.0.0" "@babel/plugin-proposal-class-properties" "^7.0.0" @@ -737,9 +737,10 @@ flow-bin "^0.79.1" gulp "^3.9.1" gulp-sourcemaps "^2.6.4" - gulp-util "^3.0.8" + gulp-uglify "^3.0.1" jest "^23.5.0" jest-junit "^5.1.0" + mustache "^2.3.2" node-mkdirs "^0.0.1" pom-parser "^1.1.1" prettier "^1.14.2" @@ -1867,7 +1868,7 @@ combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5, combined- dependencies: delayed-stream "~1.0.0" -commander@^2.11.0, commander@^2.17.1, commander@^2.2.0, commander@^2.9.0: +commander@^2.11.0, commander@^2.17.1, commander@^2.2.0, commander@^2.9.0, commander@~2.17.1: version "2.17.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" @@ -3285,7 +3286,20 @@ gulp-sourcemaps@^2.6.4: strip-bom-string "1.X" through2 "2.X" -gulp-util@^3.0.0, gulp-util@^3.0.8: +gulp-uglify@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/gulp-uglify/-/gulp-uglify-3.0.1.tgz#8d3eee466521bea6b10fd75dff72adf8b7ea2d97" + dependencies: + gulplog "^1.0.0" + has-gulplog "^0.1.0" + lodash "^4.13.1" + make-error-cause "^1.1.1" + safe-buffer "^5.1.2" + through2 "^2.0.0" + uglify-js "^3.0.5" + vinyl-sourcemaps-apply "^0.2.0" + +gulp-util@^3.0.0: version "3.0.8" resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" dependencies: @@ -4733,6 +4747,16 @@ lru-queue@0.1: dependencies: es5-ext "~0.10.2" +make-error-cause@^1.1.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/make-error-cause/-/make-error-cause-1.2.2.tgz#df0388fcd0b37816dff0a5fb8108939777dcbc9d" + dependencies: + make-error "^1.2.0" + +make-error@^1.2.0: + version "1.3.5" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8" + make-iterator@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6" @@ -4955,6 +4979,10 @@ multipipe@^0.1.2: dependencies: duplexer2 "0.0.2" +mustache@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.2.tgz#a6d4d9c3f91d13359ab889a812954f9230a3d0c5" + mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" @@ -6402,7 +6430,7 @@ source-map@^0.4.4: dependencies: amdefine ">=0.0.4" -source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1, source-map@~0.5.3: +source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1, source-map@~0.5.3: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -6857,6 +6885,13 @@ uglify-js@^2.6: optionalDependencies: uglify-to-browserify "~1.0.0" +uglify-js@^3.0.5: + version "3.4.9" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3" + dependencies: + commander "~2.17.1" + source-map "~0.6.1" + uglify-to-browserify@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" @@ -7033,6 +7068,12 @@ vinyl-source-stream@^2.0.0: through2 "^2.0.3" vinyl "^2.1.0" +vinyl-sourcemaps-apply@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz#ab6549d61d172c2b1b87be5c508d239c8ef87705" + dependencies: + source-map "^0.5.1" + vinyl@^0.4.0: version "0.4.6" resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847" diff --git a/scm-plugins/scm-hg-plugin/package.json b/scm-plugins/scm-hg-plugin/package.json index e6de568588..c5907d38bc 100644 --- a/scm-plugins/scm-hg-plugin/package.json +++ b/scm-plugins/scm-hg-plugin/package.json @@ -9,6 +9,6 @@ "@scm-manager/ui-extensions": "^0.0.7" }, "devDependencies": { - "@scm-manager/ui-bundler": "^0.0.13" + "@scm-manager/ui-bundler": "^0.0.15" } } diff --git a/scm-plugins/scm-hg-plugin/src/main/js/HgAvatar.js b/scm-plugins/scm-hg-plugin/src/main/js/HgAvatar.js index 27bc10808e..b2348b54cc 100644 --- a/scm-plugins/scm-hg-plugin/src/main/js/HgAvatar.js +++ b/scm-plugins/scm-hg-plugin/src/main/js/HgAvatar.js @@ -8,7 +8,7 @@ type Props = { class HgAvatar extends React.Component { render() { - return Mercurial Logo; + return Mercurial Logo; } } diff --git a/scm-plugins/scm-hg-plugin/yarn.lock b/scm-plugins/scm-hg-plugin/yarn.lock index 251b5241a2..8822bd5e57 100644 --- a/scm-plugins/scm-hg-plugin/yarn.lock +++ b/scm-plugins/scm-hg-plugin/yarn.lock @@ -641,9 +641,9 @@ version "0.0.2" resolved "https://registry.yarnpkg.com/@scm-manager/eslint-config/-/eslint-config-0.0.2.tgz#94cc8c3fb4f51f870b235893dc134fc6c423ae85" -"@scm-manager/ui-bundler@^0.0.13": - version "0.0.13" - resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.13.tgz#020e6c8ee870fccb6c451490cb18972ebfb0d2c4" +"@scm-manager/ui-bundler@^0.0.15": + version "0.0.15" + resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.15.tgz#8ed4a557d5ae38d6b99493b29608fd6a4c9cd917" dependencies: "@babel/core" "^7.0.0" "@babel/plugin-proposal-class-properties" "^7.0.0" @@ -671,9 +671,10 @@ flow-bin "^0.79.1" gulp "^3.9.1" gulp-sourcemaps "^2.6.4" - gulp-util "^3.0.8" + gulp-uglify "^3.0.1" jest "^23.5.0" jest-junit "^5.1.0" + mustache "^2.3.2" node-mkdirs "^0.0.1" pom-parser "^1.1.1" prettier "^1.14.2" @@ -1801,7 +1802,7 @@ combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5, combined- dependencies: delayed-stream "~1.0.0" -commander@^2.11.0, commander@^2.17.1, commander@^2.2.0, commander@^2.9.0: +commander@^2.11.0, commander@^2.17.1, commander@^2.2.0, commander@^2.9.0, commander@~2.17.1: version "2.17.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" @@ -3217,7 +3218,20 @@ gulp-sourcemaps@^2.6.4: strip-bom-string "1.X" through2 "2.X" -gulp-util@^3.0.0, gulp-util@^3.0.8: +gulp-uglify@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/gulp-uglify/-/gulp-uglify-3.0.1.tgz#8d3eee466521bea6b10fd75dff72adf8b7ea2d97" + dependencies: + gulplog "^1.0.0" + has-gulplog "^0.1.0" + lodash "^4.13.1" + make-error-cause "^1.1.1" + safe-buffer "^5.1.2" + through2 "^2.0.0" + uglify-js "^3.0.5" + vinyl-sourcemaps-apply "^0.2.0" + +gulp-util@^3.0.0: version "3.0.8" resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" dependencies: @@ -4636,6 +4650,16 @@ lru-queue@0.1: dependencies: es5-ext "~0.10.2" +make-error-cause@^1.1.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/make-error-cause/-/make-error-cause-1.2.2.tgz#df0388fcd0b37816dff0a5fb8108939777dcbc9d" + dependencies: + make-error "^1.2.0" + +make-error@^1.2.0: + version "1.3.5" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8" + make-iterator@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6" @@ -4868,6 +4892,10 @@ multipipe@^0.1.2: dependencies: duplexer2 "0.0.2" +mustache@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.2.tgz#a6d4d9c3f91d13359ab889a812954f9230a3d0c5" + mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" @@ -6283,7 +6311,7 @@ source-map@^0.4.4: dependencies: amdefine ">=0.0.4" -source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1, source-map@~0.5.3: +source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1, source-map@~0.5.3: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -6739,6 +6767,13 @@ uglify-js@^2.6: optionalDependencies: uglify-to-browserify "~1.0.0" +uglify-js@^3.0.5: + version "3.4.9" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3" + dependencies: + commander "~2.17.1" + source-map "~0.6.1" + uglify-to-browserify@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" @@ -6915,6 +6950,12 @@ vinyl-source-stream@^2.0.0: through2 "^2.0.3" vinyl "^2.1.0" +vinyl-sourcemaps-apply@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz#ab6549d61d172c2b1b87be5c508d239c8ef87705" + dependencies: + source-map "^0.5.1" + vinyl@^0.4.0: version "0.4.6" resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847" diff --git a/scm-plugins/scm-svn-plugin/package.json b/scm-plugins/scm-svn-plugin/package.json index 98f0394833..118108c882 100644 --- a/scm-plugins/scm-svn-plugin/package.json +++ b/scm-plugins/scm-svn-plugin/package.json @@ -9,6 +9,6 @@ "@scm-manager/ui-extensions": "^0.0.7" }, "devDependencies": { - "@scm-manager/ui-bundler": "^0.0.13" + "@scm-manager/ui-bundler": "^0.0.15" } } diff --git a/scm-plugins/scm-svn-plugin/src/main/js/SvnAvatar.js b/scm-plugins/scm-svn-plugin/src/main/js/SvnAvatar.js index 06fc2454db..9996cbbfe0 100644 --- a/scm-plugins/scm-svn-plugin/src/main/js/SvnAvatar.js +++ b/scm-plugins/scm-svn-plugin/src/main/js/SvnAvatar.js @@ -8,7 +8,7 @@ type Props = { class SvnAvatar extends React.Component { render() { - return Subversion Logo; + return Subversion Logo; } } diff --git a/scm-plugins/scm-svn-plugin/yarn.lock b/scm-plugins/scm-svn-plugin/yarn.lock index 251b5241a2..8822bd5e57 100644 --- a/scm-plugins/scm-svn-plugin/yarn.lock +++ b/scm-plugins/scm-svn-plugin/yarn.lock @@ -641,9 +641,9 @@ version "0.0.2" resolved "https://registry.yarnpkg.com/@scm-manager/eslint-config/-/eslint-config-0.0.2.tgz#94cc8c3fb4f51f870b235893dc134fc6c423ae85" -"@scm-manager/ui-bundler@^0.0.13": - version "0.0.13" - resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.13.tgz#020e6c8ee870fccb6c451490cb18972ebfb0d2c4" +"@scm-manager/ui-bundler@^0.0.15": + version "0.0.15" + resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.15.tgz#8ed4a557d5ae38d6b99493b29608fd6a4c9cd917" dependencies: "@babel/core" "^7.0.0" "@babel/plugin-proposal-class-properties" "^7.0.0" @@ -671,9 +671,10 @@ flow-bin "^0.79.1" gulp "^3.9.1" gulp-sourcemaps "^2.6.4" - gulp-util "^3.0.8" + gulp-uglify "^3.0.1" jest "^23.5.0" jest-junit "^5.1.0" + mustache "^2.3.2" node-mkdirs "^0.0.1" pom-parser "^1.1.1" prettier "^1.14.2" @@ -1801,7 +1802,7 @@ combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5, combined- dependencies: delayed-stream "~1.0.0" -commander@^2.11.0, commander@^2.17.1, commander@^2.2.0, commander@^2.9.0: +commander@^2.11.0, commander@^2.17.1, commander@^2.2.0, commander@^2.9.0, commander@~2.17.1: version "2.17.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" @@ -3217,7 +3218,20 @@ gulp-sourcemaps@^2.6.4: strip-bom-string "1.X" through2 "2.X" -gulp-util@^3.0.0, gulp-util@^3.0.8: +gulp-uglify@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/gulp-uglify/-/gulp-uglify-3.0.1.tgz#8d3eee466521bea6b10fd75dff72adf8b7ea2d97" + dependencies: + gulplog "^1.0.0" + has-gulplog "^0.1.0" + lodash "^4.13.1" + make-error-cause "^1.1.1" + safe-buffer "^5.1.2" + through2 "^2.0.0" + uglify-js "^3.0.5" + vinyl-sourcemaps-apply "^0.2.0" + +gulp-util@^3.0.0: version "3.0.8" resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" dependencies: @@ -4636,6 +4650,16 @@ lru-queue@0.1: dependencies: es5-ext "~0.10.2" +make-error-cause@^1.1.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/make-error-cause/-/make-error-cause-1.2.2.tgz#df0388fcd0b37816dff0a5fb8108939777dcbc9d" + dependencies: + make-error "^1.2.0" + +make-error@^1.2.0: + version "1.3.5" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8" + make-iterator@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6" @@ -4868,6 +4892,10 @@ multipipe@^0.1.2: dependencies: duplexer2 "0.0.2" +mustache@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.2.tgz#a6d4d9c3f91d13359ab889a812954f9230a3d0c5" + mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" @@ -6283,7 +6311,7 @@ source-map@^0.4.4: dependencies: amdefine ">=0.0.4" -source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1, source-map@~0.5.3: +source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1, source-map@~0.5.3: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -6739,6 +6767,13 @@ uglify-js@^2.6: optionalDependencies: uglify-to-browserify "~1.0.0" +uglify-js@^3.0.5: + version "3.4.9" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3" + dependencies: + commander "~2.17.1" + source-map "~0.6.1" + uglify-to-browserify@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" @@ -6915,6 +6950,12 @@ vinyl-source-stream@^2.0.0: through2 "^2.0.3" vinyl "^2.1.0" +vinyl-sourcemaps-apply@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz#ab6549d61d172c2b1b87be5c508d239c8ef87705" + dependencies: + source-map "^0.5.1" + vinyl@^0.4.0: version "0.4.6" resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847" diff --git a/scm-ui-components/packages/ui-components/package.json b/scm-ui-components/packages/ui-components/package.json index 1b8eeb517e..e515002728 100644 --- a/scm-ui-components/packages/ui-components/package.json +++ b/scm-ui-components/packages/ui-components/package.json @@ -12,7 +12,7 @@ "eslint-fix": "eslint src --fix" }, "devDependencies": { - "@scm-manager/ui-bundler": "^0.0.13", + "@scm-manager/ui-bundler": "^0.0.15", "create-index": "^2.3.0", "enzyme": "^3.5.0", "enzyme-adapter-react-16": "^1.3.1", diff --git a/scm-ui-components/packages/ui-components/yarn.lock b/scm-ui-components/packages/ui-components/yarn.lock index e0d20269fd..bab2b75068 100644 --- a/scm-ui-components/packages/ui-components/yarn.lock +++ b/scm-ui-components/packages/ui-components/yarn.lock @@ -728,9 +728,9 @@ version "0.0.2" resolved "https://registry.yarnpkg.com/@scm-manager/eslint-config/-/eslint-config-0.0.2.tgz#94cc8c3fb4f51f870b235893dc134fc6c423ae85" -"@scm-manager/ui-bundler@^0.0.13": - version "0.0.13" - resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.13.tgz#020e6c8ee870fccb6c451490cb18972ebfb0d2c4" +"@scm-manager/ui-bundler@^0.0.15": + version "0.0.15" + resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.15.tgz#8ed4a557d5ae38d6b99493b29608fd6a4c9cd917" dependencies: "@babel/core" "^7.0.0" "@babel/plugin-proposal-class-properties" "^7.0.0" @@ -758,9 +758,10 @@ flow-bin "^0.79.1" gulp "^3.9.1" gulp-sourcemaps "^2.6.4" - gulp-util "^3.0.8" + gulp-uglify "^3.0.1" jest "^23.5.0" jest-junit "^5.1.0" + mustache "^2.3.2" node-mkdirs "^0.0.1" pom-parser "^1.1.1" prettier "^1.14.2" @@ -1983,7 +1984,7 @@ combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5, combined- dependencies: delayed-stream "~1.0.0" -commander@^2.11.0, commander@^2.17.1, commander@^2.2.0, commander@^2.9.0: +commander@^2.11.0, commander@^2.17.1, commander@^2.2.0, commander@^2.9.0, commander@~2.17.1: version "2.17.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" @@ -3605,7 +3606,20 @@ gulp-sourcemaps@^2.6.4: strip-bom-string "1.X" through2 "2.X" -gulp-util@^3.0.0, gulp-util@^3.0.8: +gulp-uglify@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/gulp-uglify/-/gulp-uglify-3.0.1.tgz#8d3eee466521bea6b10fd75dff72adf8b7ea2d97" + dependencies: + gulplog "^1.0.0" + has-gulplog "^0.1.0" + lodash "^4.13.1" + make-error-cause "^1.1.1" + safe-buffer "^5.1.2" + through2 "^2.0.0" + uglify-js "^3.0.5" + vinyl-sourcemaps-apply "^0.2.0" + +gulp-util@^3.0.0: version "3.0.8" resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" dependencies: @@ -5264,6 +5278,16 @@ lru-queue@0.1: dependencies: es5-ext "~0.10.2" +make-error-cause@^1.1.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/make-error-cause/-/make-error-cause-1.2.2.tgz#df0388fcd0b37816dff0a5fb8108939777dcbc9d" + dependencies: + make-error "^1.2.0" + +make-error@^1.2.0: + version "1.3.5" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8" + make-iterator@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6" @@ -5506,6 +5530,10 @@ multipipe@^0.1.2: dependencies: duplexer2 "0.0.2" +mustache@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.2.tgz#a6d4d9c3f91d13359ab889a812954f9230a3d0c5" + mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" @@ -7143,7 +7171,7 @@ source-map@^0.4.4: dependencies: amdefine ">=0.0.4" -source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1, source-map@~0.5.3: +source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1, source-map@~0.5.3: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -7627,6 +7655,13 @@ uglify-js@^2.6: optionalDependencies: uglify-to-browserify "~1.0.0" +uglify-js@^3.0.5: + version "3.4.9" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3" + dependencies: + commander "~2.17.1" + source-map "~0.6.1" + uglify-to-browserify@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" @@ -7839,6 +7874,12 @@ vinyl-source-stream@^2.0.0: through2 "^2.0.3" vinyl "^2.1.0" +vinyl-sourcemaps-apply@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz#ab6549d61d172c2b1b87be5c508d239c8ef87705" + dependencies: + source-map "^0.5.1" + vinyl@^0.4.0: version "0.4.6" resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847" diff --git a/scm-ui-components/packages/ui-types/package.json b/scm-ui-components/packages/ui-types/package.json index e9db94b9a6..9c06fc7740 100644 --- a/scm-ui-components/packages/ui-types/package.json +++ b/scm-ui-components/packages/ui-types/package.json @@ -14,7 +14,7 @@ "check": "flow check" }, "devDependencies": { - "@scm-manager/ui-bundler": "^0.0.13" + "@scm-manager/ui-bundler": "^0.0.15" }, "browserify": { "transform": [ diff --git a/scm-ui-components/packages/ui-types/yarn.lock b/scm-ui-components/packages/ui-types/yarn.lock index 6c18546f36..24213220d9 100644 --- a/scm-ui-components/packages/ui-types/yarn.lock +++ b/scm-ui-components/packages/ui-types/yarn.lock @@ -707,9 +707,9 @@ version "0.0.2" resolved "https://registry.yarnpkg.com/@scm-manager/eslint-config/-/eslint-config-0.0.2.tgz#94cc8c3fb4f51f870b235893dc134fc6c423ae85" -"@scm-manager/ui-bundler@^0.0.13": - version "0.0.13" - resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.13.tgz#020e6c8ee870fccb6c451490cb18972ebfb0d2c4" +"@scm-manager/ui-bundler@^0.0.15": + version "0.0.15" + resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.15.tgz#8ed4a557d5ae38d6b99493b29608fd6a4c9cd917" dependencies: "@babel/core" "^7.0.0" "@babel/plugin-proposal-class-properties" "^7.0.0" @@ -737,9 +737,10 @@ flow-bin "^0.79.1" gulp "^3.9.1" gulp-sourcemaps "^2.6.4" - gulp-util "^3.0.8" + gulp-uglify "^3.0.1" jest "^23.5.0" jest-junit "^5.1.0" + mustache "^2.3.2" node-mkdirs "^0.0.1" pom-parser "^1.1.1" prettier "^1.14.2" @@ -1856,7 +1857,7 @@ combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5, combined- dependencies: delayed-stream "~1.0.0" -commander@^2.11.0, commander@^2.17.1, commander@^2.2.0, commander@^2.9.0: +commander@^2.11.0, commander@^2.17.1, commander@^2.2.0, commander@^2.9.0, commander@~2.17.1: version "2.17.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" @@ -3252,7 +3253,20 @@ gulp-sourcemaps@^2.6.4: strip-bom-string "1.X" through2 "2.X" -gulp-util@^3.0.0, gulp-util@^3.0.8: +gulp-uglify@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/gulp-uglify/-/gulp-uglify-3.0.1.tgz#8d3eee466521bea6b10fd75dff72adf8b7ea2d97" + dependencies: + gulplog "^1.0.0" + has-gulplog "^0.1.0" + lodash "^4.13.1" + make-error-cause "^1.1.1" + safe-buffer "^5.1.2" + through2 "^2.0.0" + uglify-js "^3.0.5" + vinyl-sourcemaps-apply "^0.2.0" + +gulp-util@^3.0.0: version "3.0.8" resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" dependencies: @@ -4693,6 +4707,16 @@ lru-queue@0.1: dependencies: es5-ext "~0.10.2" +make-error-cause@^1.1.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/make-error-cause/-/make-error-cause-1.2.2.tgz#df0388fcd0b37816dff0a5fb8108939777dcbc9d" + dependencies: + make-error "^1.2.0" + +make-error@^1.2.0: + version "1.3.5" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8" + make-iterator@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6" @@ -4915,6 +4939,10 @@ multipipe@^0.1.2: dependencies: duplexer2 "0.0.2" +mustache@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.2.tgz#a6d4d9c3f91d13359ab889a812954f9230a3d0c5" + mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" @@ -6327,7 +6355,7 @@ source-map@^0.4.4: dependencies: amdefine ">=0.0.4" -source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1, source-map@~0.5.3: +source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1, source-map@~0.5.3: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -6778,6 +6806,13 @@ uglify-js@^2.6: optionalDependencies: uglify-to-browserify "~1.0.0" +uglify-js@^3.0.5: + version "3.4.9" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3" + dependencies: + commander "~2.17.1" + source-map "~0.6.1" + uglify-to-browserify@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" @@ -6954,6 +6989,12 @@ vinyl-source-stream@^2.0.0: through2 "^2.0.3" vinyl "^2.1.0" +vinyl-sourcemaps-apply@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz#ab6549d61d172c2b1b87be5c508d239c8ef87705" + dependencies: + source-map "^0.5.1" + vinyl@^0.4.0: version "0.4.6" resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847" diff --git a/scm-ui/package.json b/scm-ui/package.json index a531cb4bd9..50ae39cd29 100644 --- a/scm-ui/package.json +++ b/scm-ui/package.json @@ -28,13 +28,13 @@ "redux-thunk": "^2.3.0" }, "scripts": { - "webfonts": "copyfiles -f node_modules/@fortawesome/fontawesome-free/webfonts/* target/styles/webfonts", - "build-css": "node-sass-chokidar --include-path ./styles --include-path ./node_modules styles/ -o target/styles", - "watch-css": "npm run build-css && node-sass-chokidar --include-path ./styles --include-path ./node_modules styles/ -o target/styles --watch --recursive", - "start-js": "ui-bundler serve --vendor vendor.bundle.js", + "webfonts": "copyfiles -f node_modules/@fortawesome/fontawesome-free/webfonts/* target/scm-ui/styles/webfonts", + "build-css": "node-sass-chokidar --include-path ./styles --include-path ./node_modules styles/ -o target/scm-ui/styles", + "watch-css": "npm run build-css && node-sass-chokidar --include-path ./styles --include-path ./node_modules styles/ -o target/scm-ui/styles --watch --recursive", + "start-js": "ui-bundler serve --target target/scm-ui --vendor vendor.bundle.js", "start": "npm-run-all -p webfonts watch-css start-js", - "build-js": "ui-bundler bundle target/scm-ui.bundle.js", - "build-vendor": "ui-bundler vendor target/vendor.bundle.js", + "build-js": "ui-bundler bundle --mode=production target/scm-ui/scm-ui.bundle.js", + "build-vendor": "ui-bundler vendor --mode=production target/scm-ui/vendor.bundle.js", "build": "npm-run-all -s webfonts build-css build-vendor build-js", "test": "ui-bundler test", "test-ci": "ui-bundler test --ci", @@ -42,7 +42,7 @@ "pre-commit": "jest && flow && eslint src" }, "devDependencies": { - "@scm-manager/ui-bundler": "^0.0.13", + "@scm-manager/ui-bundler": "^0.0.15", "copyfiles": "^2.0.0", "enzyme": "^3.3.0", "enzyme-adapter-react-16": "^1.1.1", diff --git a/scm-ui/pom.xml b/scm-ui/pom.xml index abe87e697f..5e3ca2b6f5 100644 --- a/scm-ui/pom.xml +++ b/scm-ui/pom.xml @@ -10,9 +10,9 @@ 2.0.0-SNAPSHOT - sonia.scm.clients + sonia.scm scm-ui - pom + war 2.0.0-SNAPSHOT scm-ui @@ -26,6 +26,7 @@ + scm-ui @@ -93,6 +94,20 @@ + + org.apache.maven.plugins + maven-war-plugin + 3.1.0 + + false + + + public + + + + + diff --git a/scm-ui/public/index.html b/scm-ui/public/index.mustache similarity index 56% rename from scm-ui/public/index.html rename to scm-ui/public/index.mustache index 23dc1b9782..802be2ca97 100644 --- a/scm-ui/public/index.html +++ b/scm-ui/public/index.mustache @@ -8,20 +8,11 @@ manifest.json provides metadata used when your web app is added to the homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/ --> - - - - - - + + SCM-Manager @@ -41,9 +32,9 @@ To create a production bundle, use `npm run build` or `yarn build`. --> - - + + diff --git a/scm-ui/yarn.lock b/scm-ui/yarn.lock index 078a841ea2..26bfec8070 100644 --- a/scm-ui/yarn.lock +++ b/scm-ui/yarn.lock @@ -732,9 +732,9 @@ version "0.0.2" resolved "https://registry.yarnpkg.com/@scm-manager/eslint-config/-/eslint-config-0.0.2.tgz#94cc8c3fb4f51f870b235893dc134fc6c423ae85" -"@scm-manager/ui-bundler@^0.0.13": - version "0.0.13" - resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.13.tgz#020e6c8ee870fccb6c451490cb18972ebfb0d2c4" +"@scm-manager/ui-bundler@^0.0.15": + version "0.0.15" + resolved "https://registry.yarnpkg.com/@scm-manager/ui-bundler/-/ui-bundler-0.0.15.tgz#8ed4a557d5ae38d6b99493b29608fd6a4c9cd917" dependencies: "@babel/core" "^7.0.0" "@babel/plugin-proposal-class-properties" "^7.0.0" @@ -762,9 +762,10 @@ flow-bin "^0.79.1" gulp "^3.9.1" gulp-sourcemaps "^2.6.4" - gulp-util "^3.0.8" + gulp-uglify "^3.0.1" jest "^23.5.0" jest-junit "^5.1.0" + mustache "^2.3.2" node-mkdirs "^0.0.1" pom-parser "^1.1.1" prettier "^1.14.2" @@ -2042,7 +2043,7 @@ combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5, combined- dependencies: delayed-stream "~1.0.0" -commander@^2.11.0, commander@^2.17.1, commander@^2.2.0, commander@^2.9.0: +commander@^2.11.0, commander@^2.17.1, commander@^2.2.0, commander@^2.9.0, commander@~2.17.1: version "2.17.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" @@ -3743,7 +3744,20 @@ gulp-sourcemaps@^2.6.4: strip-bom-string "1.X" through2 "2.X" -gulp-util@^3.0.0, gulp-util@^3.0.8: +gulp-uglify@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/gulp-uglify/-/gulp-uglify-3.0.1.tgz#8d3eee466521bea6b10fd75dff72adf8b7ea2d97" + dependencies: + gulplog "^1.0.0" + has-gulplog "^0.1.0" + lodash "^4.13.1" + make-error-cause "^1.1.1" + safe-buffer "^5.1.2" + through2 "^2.0.0" + uglify-js "^3.0.5" + vinyl-sourcemaps-apply "^0.2.0" + +gulp-util@^3.0.0: version "3.0.8" resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" dependencies: @@ -5474,6 +5488,16 @@ lru-queue@0.1: dependencies: es5-ext "~0.10.2" +make-error-cause@^1.1.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/make-error-cause/-/make-error-cause-1.2.2.tgz#df0388fcd0b37816dff0a5fb8108939777dcbc9d" + dependencies: + make-error "^1.2.0" + +make-error@^1.2.0: + version "1.3.5" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8" + make-iterator@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6" @@ -5743,6 +5767,10 @@ multipipe@^0.1.2: dependencies: duplexer2 "0.0.2" +mustache@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.2.tgz#a6d4d9c3f91d13359ab889a812954f9230a3d0c5" + mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" @@ -7586,7 +7614,7 @@ source-map@^0.4.2, source-map@^0.4.4: dependencies: amdefine ">=0.0.4" -source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1, source-map@~0.5.3: +source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1, source-map@~0.5.3: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -8120,6 +8148,13 @@ uglify-js@^2.6: optionalDependencies: uglify-to-browserify "~1.0.0" +uglify-js@^3.0.5: + version "3.4.9" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.9.tgz#af02f180c1207d76432e473ed24a28f4a782bae3" + dependencies: + commander "~2.17.1" + source-map "~0.6.1" + uglify-to-browserify@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" @@ -8336,6 +8371,12 @@ vinyl-source-stream@^2.0.0: through2 "^2.0.3" vinyl "^2.1.0" +vinyl-sourcemaps-apply@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz#ab6549d61d172c2b1b87be5c508d239c8ef87705" + dependencies: + source-map "^0.5.1" + vinyl@^0.4.0: version "0.4.6" resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847" diff --git a/scm-webapp/pom.xml b/scm-webapp/pom.xml index fb5cc57e44..761a28730c 100644 --- a/scm-webapp/pom.xml +++ b/scm-webapp/pom.xml @@ -237,6 +237,12 @@ ${mustache.version} + + com.github.sdorra + web-resources + 1.0.2 + + com.github.sdorra spotter-core @@ -248,6 +254,7 @@ tika-core 1.18 + @@ -515,7 +522,7 @@ sonia.scm.ui.proxy - http://localhost:3000 + ${livereload.proxy} @@ -546,7 +553,42 @@ - + + + livereload + + + + livereload + + + + + http://localhost:3000 + + + + + ui-overlay + + + + !livereload + + + + + + + sonia.scm + scm-ui + 2.0.0-SNAPSHOT + war + + + + + release diff --git a/scm-webapp/src/main/java/sonia/scm/ForwardingPushStateDispatcher.java b/scm-webapp/src/main/java/sonia/scm/ForwardingPushStateDispatcher.java deleted file mode 100644 index 0b80f158f3..0000000000 --- a/scm-webapp/src/main/java/sonia/scm/ForwardingPushStateDispatcher.java +++ /dev/null @@ -1,24 +0,0 @@ -package sonia.scm; - -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -/** - * This dispatcher forwards every request to the index.html of the application. - * - * @since 2.0.0 - */ -public class ForwardingPushStateDispatcher implements PushStateDispatcher { - @Override - public void dispatch(HttpServletRequest request, HttpServletResponse response, String uri) throws IOException { - RequestDispatcher dispatcher = request.getRequestDispatcher("/index.html"); - try { - dispatcher.forward(request, response); - } catch (ServletException e) { - throw new IOException("failed to forward request", e); - } - } -} diff --git a/scm-webapp/src/main/java/sonia/scm/PushStateDispatcherProvider.java b/scm-webapp/src/main/java/sonia/scm/PushStateDispatcherProvider.java index 653f7b4bdc..f0d2807497 100644 --- a/scm-webapp/src/main/java/sonia/scm/PushStateDispatcherProvider.java +++ b/scm-webapp/src/main/java/sonia/scm/PushStateDispatcherProvider.java @@ -3,12 +3,13 @@ package sonia.scm; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Strings; +import javax.inject.Inject; import javax.inject.Provider; /** * Injection Provider for the {@link PushStateDispatcher}. The provider will return a {@link ProxyPushStateDispatcher} * if the system property {@code PushStateDispatcherProvider#PROPERTY_TARGET} is set to a proxy target url, otherwise - * a {@link ForwardingPushStateDispatcher} is used. + * a {@link TemplatingPushStateDispatcher} is used. * * @since 2.0.0 */ @@ -17,11 +18,18 @@ public class PushStateDispatcherProvider implements Provider templatingPushStateDispatcherProvider; + + @Inject + public PushStateDispatcherProvider(Provider templatingPushStateDispatcherProvider) { + this.templatingPushStateDispatcherProvider = templatingPushStateDispatcherProvider; + } + @Override public PushStateDispatcher get() { String target = System.getProperty(PROPERTY_TARGET); if (Strings.isNullOrEmpty(target)) { - return new ForwardingPushStateDispatcher(); + return templatingPushStateDispatcherProvider.get(); } return new ProxyPushStateDispatcher(target); } diff --git a/scm-webapp/src/main/java/sonia/scm/TemplatingPushStateDispatcher.java b/scm-webapp/src/main/java/sonia/scm/TemplatingPushStateDispatcher.java new file mode 100644 index 0000000000..6652975c4a --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/TemplatingPushStateDispatcher.java @@ -0,0 +1,61 @@ +package sonia.scm; + +import com.google.common.annotations.VisibleForTesting; +import sonia.scm.template.Template; +import sonia.scm.template.TemplateEngine; +import sonia.scm.template.TemplateEngineFactory; + +import javax.inject.Inject; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.Writer; + +/** + * This dispatcher renders the /index.mustache template, which is merged in from the scm-ui package. + * + * @since 2.0.0 + */ +public class TemplatingPushStateDispatcher implements PushStateDispatcher { + + @VisibleForTesting + static final String TEMPLATE = "/index.mustache"; + + private final TemplateEngine templateEngine; + + @Inject + public TemplatingPushStateDispatcher(TemplateEngineFactory templateEngineFactory) { + this(templateEngineFactory.getDefaultEngine()); + } + + @VisibleForTesting + TemplatingPushStateDispatcher(TemplateEngine templateEngine) { + this.templateEngine = templateEngine; + } + + @Override + public void dispatch(HttpServletRequest request, HttpServletResponse response, String uri) throws IOException { + response.setContentType("text/html"); + response.setCharacterEncoding("UTF-8"); + + Template template = templateEngine.getTemplate(TEMPLATE); + try (Writer writer = response.getWriter()) { + template.execute(writer, new IndexHtmlModel(request)); + } + } + + @VisibleForTesting + static class IndexHtmlModel { + + private final HttpServletRequest request; + + private IndexHtmlModel(HttpServletRequest request) { + this.request = request; + } + + public String getContextPath() { + return request.getContextPath(); + } + + } +} diff --git a/scm-webapp/src/main/java/sonia/scm/WebResourceServlet.java b/scm-webapp/src/main/java/sonia/scm/WebResourceServlet.java index 764e4f18d2..98117851db 100644 --- a/scm-webapp/src/main/java/sonia/scm/WebResourceServlet.java +++ b/scm-webapp/src/main/java/sonia/scm/WebResourceServlet.java @@ -1,7 +1,7 @@ package sonia.scm; +import com.github.sdorra.webresources.WebResourceSender; import com.google.common.annotations.VisibleForTesting; -import com.google.common.io.Resources; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import sonia.scm.filter.WebElement; @@ -15,7 +15,6 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; -import java.io.OutputStream; import java.net.URL; /** @@ -27,6 +26,7 @@ import java.net.URL; @WebElement(value = WebResourceServlet.PATTERN, regex = true) public class WebResourceServlet extends HttpServlet { + /** * exclude api requests and the old frontend servlets. * @@ -37,6 +37,11 @@ public class WebResourceServlet extends HttpServlet { private static final Logger LOG = LoggerFactory.getLogger(WebResourceServlet.class); + private final WebResourceSender sender = WebResourceSender.create() + .withGZIP() + .withGZIPMinLength(512) + .withBufferSize(16384); + private final UberWebResourceLoader webResourceLoader; private final PushStateDispatcher pushStateDispatcher; @@ -53,7 +58,7 @@ public class WebResourceServlet extends HttpServlet { LOG.trace("try to load {}", uri); URL url = webResourceLoader.getResource(uri); if (url != null) { - serveResource(response, url); + serveResource(request, response, url); } else { dispatch(request, response, uri); } @@ -72,10 +77,9 @@ public class WebResourceServlet extends HttpServlet { return HttpUtil.getStrippedURI(request); } - private void serveResource(HttpServletResponse response, URL url) { - // TODO lastModifiedDate, if-... ??? - try (OutputStream output = response.getOutputStream()) { - Resources.copy(url, output); + private void serveResource(HttpServletRequest request, HttpServletResponse response, URL url) { + try { + sender.resource(url).send(request, response); } catch (IOException ex) { LOG.warn("failed to serve resource: {}", url); response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); diff --git a/scm-webapp/src/main/java/sonia/scm/plugin/PathWebResourceLoader.java b/scm-webapp/src/main/java/sonia/scm/plugin/PathWebResourceLoader.java index 230cfa6c7a..4b9e502c4d 100644 --- a/scm-webapp/src/main/java/sonia/scm/plugin/PathWebResourceLoader.java +++ b/scm-webapp/src/main/java/sonia/scm/plugin/PathWebResourceLoader.java @@ -31,18 +31,11 @@ package sonia.scm.plugin; -//~--- non-JDK imports -------------------------------------------------------- - import org.slf4j.Logger; import org.slf4j.LoggerFactory; -//~--- JDK imports ------------------------------------------------------------ - -import java.io.File; - import java.net.MalformedURLException; import java.net.URL; - import java.nio.file.Files; import java.nio.file.Path; @@ -55,47 +48,27 @@ import java.nio.file.Path; public class PathWebResourceLoader implements WebResourceLoader { - /** Field description */ - private static final String DEFAULT_SEPARATOR = "/"; + private static final String SEPARATOR = "/"; /** * the logger for PathWebResourceLoader */ - private static final Logger logger = + private static final Logger LOG = LoggerFactory.getLogger(PathWebResourceLoader.class); - //~--- constructors --------------------------------------------------------- - - /** - * Constructs ... - * - * - * @param directory - */ public PathWebResourceLoader(Path directory) { this.directory = directory; } - //~--- get methods ---------------------------------------------------------- - - /** - * Method description - * - * - * @param path - * - * @return - */ @Override - public URL getResource(String path) - { + public URL getResource(String path) { URL resource = null; Path file = directory.resolve(filePath(path)); if (Files.exists(file) && ! Files.isDirectory(file)) { - logger.trace("found path {} at {}", path, file); + LOG.trace("found path {} at {}", path, file); try { @@ -103,56 +76,20 @@ public class PathWebResourceLoader implements WebResourceLoader } catch (MalformedURLException ex) { - logger.error("could not transform path to url", ex); + LOG.error("could not transform path to url", ex); } + } else { + LOG.trace("could not find file {}", file); } return resource; } - //~--- methods -------------------------------------------------------------- - - /** - * Method description - * - * - * @param path - * - * @return - */ - private String filePath(String path) - { - - // TODO handle illegal path parts, such as .. - String filePath = filePath(DEFAULT_SEPARATOR, path); - - if (!DEFAULT_SEPARATOR.equals(File.separator)) - { - filePath = filePath(File.separator, path); + private String filePath(String path) { + if (path.startsWith(SEPARATOR)) { + return path.substring(1); } - - return filePath; - } - - /** - * Method description - * - * - * @param separator - * @param path - * - * @return - */ - private String filePath(String separator, String path) - { - String filePath = path; - - if (filePath.startsWith(separator)) - { - filePath = filePath.substring(separator.length()); - } - - return filePath; + return path; } //~--- fields --------------------------------------------------------------- diff --git a/scm-webapp/src/main/webapp/index.html b/scm-webapp/src/main/webapp/index.html deleted file mode 100644 index e149a39434..0000000000 --- a/scm-webapp/src/main/webapp/index.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - Title - - - - - diff --git a/scm-webapp/src/test/java/sonia/scm/ForwardingPushStateDispatcherTest.java b/scm-webapp/src/test/java/sonia/scm/ForwardingPushStateDispatcherTest.java deleted file mode 100644 index e96464ee98..0000000000 --- a/scm-webapp/src/test/java/sonia/scm/ForwardingPushStateDispatcherTest.java +++ /dev/null @@ -1,51 +0,0 @@ -package sonia.scm; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; - -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import java.io.IOException; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -@RunWith(MockitoJUnitRunner.class) -public class ForwardingPushStateDispatcherTest { - - @Mock - private HttpServletRequest request; - - @Mock - private RequestDispatcher requestDispatcher; - - @Mock - private HttpServletResponse response; - - private ForwardingPushStateDispatcher dispatcher = new ForwardingPushStateDispatcher(); - - @Test - public void testDispatch() throws ServletException, IOException { - when(request.getRequestDispatcher("/index.html")).thenReturn(requestDispatcher); - - dispatcher.dispatch(request, response, "/something"); - - verify(requestDispatcher).forward(request, response); - } - - @Test(expected = IOException.class) - public void testWrapServletException() throws ServletException, IOException { - when(request.getRequestDispatcher("/index.html")).thenReturn(requestDispatcher); - doThrow(ServletException.class).when(requestDispatcher).forward(request, response); - - dispatcher.dispatch(request, response, "/something"); - } - -} diff --git a/scm-webapp/src/test/java/sonia/scm/PushStateDispatcherProviderTest.java b/scm-webapp/src/test/java/sonia/scm/PushStateDispatcherProviderTest.java index 31e5f7c6dc..4316d9bc06 100644 --- a/scm-webapp/src/test/java/sonia/scm/PushStateDispatcherProviderTest.java +++ b/scm-webapp/src/test/java/sonia/scm/PushStateDispatcherProviderTest.java @@ -1,14 +1,23 @@ package sonia.scm; +import com.google.inject.util.Providers; import org.assertj.core.api.Assertions; import org.junit.After; import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import sonia.scm.template.TemplateEngine; -import static org.junit.Assert.*; - +@RunWith(MockitoJUnitRunner.class) public class PushStateDispatcherProviderTest { - private PushStateDispatcherProvider provider = new PushStateDispatcherProvider(); + @Mock + private TemplateEngine templateEngine; + + private PushStateDispatcherProvider provider = new PushStateDispatcherProvider( + Providers.of(new TemplatingPushStateDispatcher(templateEngine)) + ); @Test public void testGetProxyPushStateWithPropertySet() { @@ -20,7 +29,7 @@ public class PushStateDispatcherProviderTest { @Test public void testGetProxyPushStateWithoutProperty() { PushStateDispatcher dispatcher = provider.get(); - Assertions.assertThat(dispatcher).isInstanceOf(ForwardingPushStateDispatcher.class); + Assertions.assertThat(dispatcher).isInstanceOf(TemplatingPushStateDispatcher.class); } @After diff --git a/scm-webapp/src/test/java/sonia/scm/TemplatingPushStateDispatcherTest.java b/scm-webapp/src/test/java/sonia/scm/TemplatingPushStateDispatcherTest.java new file mode 100644 index 0000000000..126ba9ac0f --- /dev/null +++ b/scm-webapp/src/test/java/sonia/scm/TemplatingPushStateDispatcherTest.java @@ -0,0 +1,66 @@ +package sonia.scm; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import sonia.scm.template.Template; +import sonia.scm.template.TemplateEngine; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.Writer; + +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class TemplatingPushStateDispatcherTest { + + @Mock + private HttpServletRequest request; + + @Mock + private HttpServletResponse response; + + @Mock + private TemplateEngine templateEngine; + + @Mock + private Template template; + + private TemplatingPushStateDispatcher dispatcher; + + @Before + public void setUpMocks() { + dispatcher = new TemplatingPushStateDispatcher(templateEngine); + } + + @Test + public void testDispatch() throws IOException { + when(request.getContextPath()).thenReturn("/scm"); + when(templateEngine.getTemplate(TemplatingPushStateDispatcher.TEMPLATE)).thenReturn(template); + + when(response.getWriter()).thenReturn(new PrintWriter(new StringWriter())); + + dispatcher.dispatch(request, response, "/someurl"); + + verify(response).setContentType("text/html"); + verify(response).setCharacterEncoding("UTF-8"); + + ArgumentCaptor captor = ArgumentCaptor.forClass(Object.class); + + verify(template).execute(any(Writer.class), captor.capture()); + + TemplatingPushStateDispatcher.IndexHtmlModel model = (TemplatingPushStateDispatcher.IndexHtmlModel) captor.getValue(); + assertEquals("/scm", model.getContextPath()); + } + +} diff --git a/scm-webapp/src/test/java/sonia/scm/WebResourceServletTest.java b/scm-webapp/src/test/java/sonia/scm/WebResourceServletTest.java index fa39239d5d..b3864d894f 100644 --- a/scm-webapp/src/test/java/sonia/scm/WebResourceServletTest.java +++ b/scm-webapp/src/test/java/sonia/scm/WebResourceServletTest.java @@ -22,7 +22,7 @@ import java.io.IOException; import static org.junit.Assert.*; import static org.mockito.Mockito.*; -@RunWith(MockitoJUnitRunner.class) +@RunWith(MockitoJUnitRunner.Silent.class) public class WebResourceServletTest { @Rule