diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b3eb214d3..3cd57e1ffc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Unreleased +## [2.8.0] - 2020-10-27 ### Added - Generation of email addresses for users, where none is configured ([#1370](https://github.com/scm-manager/scm-manager/pull/1370)) - Automatic user converter for external users ([#1380](https://github.com/scm-manager/scm-manager/pull/1380)) @@ -19,6 +19,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Handling of snapshot plugin dependencies ([#1384](https://github.com/scm-manager/scm-manager/pull/1384)) +- SyntaxHighlighting for GoLang ([#1386](https://github.com/scm-manager/scm-manager/pull/1386)) +- Privilege escalation for api keys ([#1388](https://github.com/scm-manager/scm-manager/pull/1388)) ## [2.6.3] - 2020-10-16 ### Fixed diff --git a/lerna.json b/lerna.json index 2eb3066367..1316097faf 100644 --- a/lerna.json +++ b/lerna.json @@ -5,5 +5,5 @@ ], "npmClient": "yarn", "useWorkspaces": true, - "version": "2.8.0-SNAPSHOT" + "version": "2.9.0-SNAPSHOT" } diff --git a/pom.xml b/pom.xml index 4b50003136..2e3c7d8840 100644 --- a/pom.xml +++ b/pom.xml @@ -32,7 +32,7 @@ sonia.scm scm pom - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT The easiest way to share your Git, Mercurial and Subversion repositories. @@ -925,7 +925,7 @@ 1.6.2 - 9.4.31.v20200723 + 9.4.33.v20201020 9.4.30.v20200611 diff --git a/scm-annotation-processor/pom.xml b/scm-annotation-processor/pom.xml index 28702106db..72f5af3a0d 100644 --- a/scm-annotation-processor/pom.xml +++ b/scm-annotation-processor/pom.xml @@ -31,12 +31,12 @@ sonia.scm scm - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT sonia.scm scm-annotation-processor - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT scm-annotation-processor @@ -46,7 +46,7 @@ sonia.scm scm-annotations - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT diff --git a/scm-annotations/pom.xml b/scm-annotations/pom.xml index f48c2dfb58..3bca913681 100644 --- a/scm-annotations/pom.xml +++ b/scm-annotations/pom.xml @@ -31,11 +31,11 @@ sonia.scm scm - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT scm-annotations - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT scm-annotations diff --git a/scm-core/pom.xml b/scm-core/pom.xml index e6b41a4e6c..5359eec268 100644 --- a/scm-core/pom.xml +++ b/scm-core/pom.xml @@ -31,11 +31,11 @@ scm sonia.scm - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT scm-core - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT scm-core @@ -54,7 +54,7 @@ sonia.scm scm-annotations - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT @@ -227,7 +227,7 @@ sonia.scm scm-annotation-processor - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT provided diff --git a/scm-dao-xml/pom.xml b/scm-dao-xml/pom.xml index 25231dc4e7..f336d60aa8 100644 --- a/scm-dao-xml/pom.xml +++ b/scm-dao-xml/pom.xml @@ -31,11 +31,11 @@ sonia.scm scm - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT scm-dao-xml - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT scm-dao-xml @@ -50,7 +50,7 @@ sonia.scm scm-core - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT @@ -58,7 +58,7 @@ sonia.scm scm-test - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT test diff --git a/scm-it/pom.xml b/scm-it/pom.xml index ff9a7d87f8..95f2146cc2 100644 --- a/scm-it/pom.xml +++ b/scm-it/pom.xml @@ -31,40 +31,40 @@ sonia.scm scm - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT sonia.scm scm-it war - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT scm-it sonia.scm scm-core - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT sonia.scm scm-test - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT sonia.scm.plugins scm-git-plugin - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT test sonia.scm.plugins scm-git-plugin - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT tests test @@ -72,14 +72,14 @@ sonia.scm.plugins scm-hg-plugin - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT test sonia.scm.plugins scm-hg-plugin - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT tests test @@ -87,14 +87,14 @@ sonia.scm.plugins scm-svn-plugin - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT test sonia.scm.plugins scm-svn-plugin - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT tests test diff --git a/scm-packaging/deb/pom.xml b/scm-packaging/deb/pom.xml index 6f0657736f..a4f19d14be 100644 --- a/scm-packaging/deb/pom.xml +++ b/scm-packaging/deb/pom.xml @@ -32,12 +32,12 @@ sonia.scm.packaging scm-packaging - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT deb deb - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT Packaging for Debian/Ubuntu deb @@ -46,7 +46,7 @@ sonia.scm scm-server - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT diff --git a/scm-packaging/docker/pom.xml b/scm-packaging/docker/pom.xml index 941a5c1516..9806dbd97d 100644 --- a/scm-packaging/docker/pom.xml +++ b/scm-packaging/docker/pom.xml @@ -32,12 +32,12 @@ sonia.scm.packaging scm-packaging - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT docker pom - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT diff --git a/scm-packaging/helm/pom.xml b/scm-packaging/helm/pom.xml index 5ad0cf6fd3..e0791dd467 100644 --- a/scm-packaging/helm/pom.xml +++ b/scm-packaging/helm/pom.xml @@ -32,12 +32,12 @@ sonia.scm.packaging scm-packaging - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT helm helm - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT 3.2.1 diff --git a/scm-packaging/pom.xml b/scm-packaging/pom.xml index 300f088af6..60a2ce343d 100644 --- a/scm-packaging/pom.xml +++ b/scm-packaging/pom.xml @@ -31,13 +31,13 @@ sonia.scm scm - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT sonia.scm.packaging scm-packaging pom - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT packages.scm-manager.org diff --git a/scm-packaging/release-yaml/pom.xml b/scm-packaging/release-yaml/pom.xml index 27c2731b87..618dd838cb 100644 --- a/scm-packaging/release-yaml/pom.xml +++ b/scm-packaging/release-yaml/pom.xml @@ -32,12 +32,12 @@ sonia.scm.packaging scm-packaging - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT release-yaml pom - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT diff --git a/scm-packaging/rpm/pom.xml b/scm-packaging/rpm/pom.xml index fee0719a8d..cefc92ce57 100644 --- a/scm-packaging/rpm/pom.xml +++ b/scm-packaging/rpm/pom.xml @@ -32,12 +32,12 @@ sonia.scm.packaging scm-packaging - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT rpm rpm - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT Packaging for RedHat/Centos/Fedora rpm @@ -52,7 +52,7 @@ sonia.scm scm-server - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT diff --git a/scm-packaging/unix/pom.xml b/scm-packaging/unix/pom.xml index 5cd9e36a97..72149ef11b 100644 --- a/scm-packaging/unix/pom.xml +++ b/scm-packaging/unix/pom.xml @@ -31,12 +31,12 @@ sonia.scm.packaging scm-packaging - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT unix pom - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT diff --git a/scm-packaging/windows/pom.xml b/scm-packaging/windows/pom.xml index 593c17a151..4c2a25d2ff 100644 --- a/scm-packaging/windows/pom.xml +++ b/scm-packaging/windows/pom.xml @@ -32,12 +32,12 @@ sonia.scm.packaging scm-packaging - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT windows pom - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT diff --git a/scm-plugins/pom.xml b/scm-plugins/pom.xml index 24e002fc17..693a21730b 100644 --- a/scm-plugins/pom.xml +++ b/scm-plugins/pom.xml @@ -31,13 +31,13 @@ sonia.scm scm - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT sonia.scm.plugins scm-plugins pom - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT scm-plugins @@ -60,7 +60,7 @@ sonia.scm scm-core - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT provided @@ -69,7 +69,7 @@ sonia.scm scm-annotation-processor - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT provided @@ -99,7 +99,7 @@ sonia.scm scm-test - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT test diff --git a/scm-plugins/scm-git-plugin/package.json b/scm-plugins/scm-git-plugin/package.json index 1e61547668..b859e3b05b 100644 --- a/scm-plugins/scm-git-plugin/package.json +++ b/scm-plugins/scm-git-plugin/package.json @@ -1,7 +1,7 @@ { "name": "@scm-manager/scm-git-plugin", "private": true, - "version": "2.8.0-SNAPSHOT", + "version": "2.9.0-SNAPSHOT", "license": "MIT", "main": "./src/main/js/index.ts", "scripts": { @@ -20,6 +20,6 @@ }, "prettier": "@scm-manager/prettier-config", "dependencies": { - "@scm-manager/ui-plugins": "^2.8.0-SNAPSHOT" + "@scm-manager/ui-plugins": "^2.9.0-SNAPSHOT" } } diff --git a/scm-plugins/scm-git-plugin/pom.xml b/scm-plugins/scm-git-plugin/pom.xml index d1d18f1329..3f01b0017a 100644 --- a/scm-plugins/scm-git-plugin/pom.xml +++ b/scm-plugins/scm-git-plugin/pom.xml @@ -31,7 +31,7 @@ scm-plugins sonia.scm.plugins - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT scm-git-plugin diff --git a/scm-plugins/scm-hg-plugin/package.json b/scm-plugins/scm-hg-plugin/package.json index 6683453f24..6bd7d66b9b 100644 --- a/scm-plugins/scm-hg-plugin/package.json +++ b/scm-plugins/scm-hg-plugin/package.json @@ -1,7 +1,7 @@ { "name": "@scm-manager/scm-hg-plugin", "private": true, - "version": "2.8.0-SNAPSHOT", + "version": "2.9.0-SNAPSHOT", "license": "MIT", "main": "./src/main/js/index.ts", "scripts": { @@ -19,6 +19,6 @@ }, "prettier": "@scm-manager/prettier-config", "dependencies": { - "@scm-manager/ui-plugins": "^2.8.0-SNAPSHOT" + "@scm-manager/ui-plugins": "^2.9.0-SNAPSHOT" } } diff --git a/scm-plugins/scm-hg-plugin/pom.xml b/scm-plugins/scm-hg-plugin/pom.xml index 0a03731bd3..02609314e3 100644 --- a/scm-plugins/scm-hg-plugin/pom.xml +++ b/scm-plugins/scm-hg-plugin/pom.xml @@ -31,7 +31,7 @@ sonia.scm.plugins scm-plugins - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT scm-hg-plugin diff --git a/scm-plugins/scm-integration-test-plugin/pom.xml b/scm-plugins/scm-integration-test-plugin/pom.xml index 755348c9d7..e1953740df 100644 --- a/scm-plugins/scm-integration-test-plugin/pom.xml +++ b/scm-plugins/scm-integration-test-plugin/pom.xml @@ -29,12 +29,12 @@ sonia.scm.plugins scm-plugins - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT scm-integration-test-plugin Add functions for integration tests. This is not intended for production systems. - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT smp diff --git a/scm-plugins/scm-legacy-plugin/package.json b/scm-plugins/scm-legacy-plugin/package.json index 510cdae1a6..fbc5cde7b4 100644 --- a/scm-plugins/scm-legacy-plugin/package.json +++ b/scm-plugins/scm-legacy-plugin/package.json @@ -1,7 +1,7 @@ { "name": "@scm-manager/scm-legacy-plugin", "private": true, - "version": "2.8.0-SNAPSHOT", + "version": "2.9.0-SNAPSHOT", "license": "MIT", "main": "./src/main/js/index.tsx", "scripts": { @@ -19,6 +19,6 @@ }, "prettier": "@scm-manager/prettier-config", "dependencies": { - "@scm-manager/ui-plugins": "^2.8.0-SNAPSHOT" + "@scm-manager/ui-plugins": "^2.9.0-SNAPSHOT" } } diff --git a/scm-plugins/scm-legacy-plugin/pom.xml b/scm-plugins/scm-legacy-plugin/pom.xml index 51c7e718a0..f3a30d4867 100644 --- a/scm-plugins/scm-legacy-plugin/pom.xml +++ b/scm-plugins/scm-legacy-plugin/pom.xml @@ -29,12 +29,12 @@ sonia.scm.plugins scm-plugins - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT scm-legacy-plugin Support migrated repository urls and v1 passwords - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT smp diff --git a/scm-plugins/scm-svn-plugin/package.json b/scm-plugins/scm-svn-plugin/package.json index c0b0051b1e..e0df47c08a 100644 --- a/scm-plugins/scm-svn-plugin/package.json +++ b/scm-plugins/scm-svn-plugin/package.json @@ -1,7 +1,7 @@ { "name": "@scm-manager/scm-svn-plugin", "private": true, - "version": "2.8.0-SNAPSHOT", + "version": "2.9.0-SNAPSHOT", "license": "MIT", "main": "./src/main/js/index.ts", "scripts": { @@ -19,6 +19,6 @@ }, "prettier": "@scm-manager/prettier-config", "dependencies": { - "@scm-manager/ui-plugins": "^2.8.0-SNAPSHOT" + "@scm-manager/ui-plugins": "^2.9.0-SNAPSHOT" } } diff --git a/scm-plugins/scm-svn-plugin/pom.xml b/scm-plugins/scm-svn-plugin/pom.xml index 26c16a221c..e78a8221bb 100644 --- a/scm-plugins/scm-svn-plugin/pom.xml +++ b/scm-plugins/scm-svn-plugin/pom.xml @@ -31,7 +31,7 @@ scm-plugins sonia.scm.plugins - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT scm-svn-plugin diff --git a/scm-server/pom.xml b/scm-server/pom.xml index 5a10a9c098..f70bedd767 100644 --- a/scm-server/pom.xml +++ b/scm-server/pom.xml @@ -31,12 +31,12 @@ scm sonia.scm - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT sonia.scm scm-server - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT scm-server jar diff --git a/scm-test/pom.xml b/scm-test/pom.xml index 0544a10524..fd359d6783 100644 --- a/scm-test/pom.xml +++ b/scm-test/pom.xml @@ -31,12 +31,12 @@ scm sonia.scm - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT sonia.scm scm-test - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT scm-test @@ -50,7 +50,7 @@ sonia.scm scm-core - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT diff --git a/scm-ui/babel-preset/package.json b/scm-ui/babel-preset/package.json index 37a15f5131..1b416e5683 100644 --- a/scm-ui/babel-preset/package.json +++ b/scm-ui/babel-preset/package.json @@ -1,6 +1,6 @@ { "name": "@scm-manager/babel-preset", - "version": "2.8.0-SNAPSHOT", + "version": "2.9.0-SNAPSHOT", "license": "MIT", "description": "Babel configuration for scm-manager and its plugins", "main": "index.js", diff --git a/scm-ui/e2e-tests/package.json b/scm-ui/e2e-tests/package.json index bc1af44bbd..a4cd2f3998 100644 --- a/scm-ui/e2e-tests/package.json +++ b/scm-ui/e2e-tests/package.json @@ -1,6 +1,6 @@ { "name": "@scm-manager/e2e-tests", - "version": "2.8.0-SNAPSHOT", + "version": "2.9.0-SNAPSHOT", "description": "End to end Tests for SCM-Manager", "main": "index.js", "author": "Eduard Heimbuch ", diff --git a/scm-ui/eslint-config/package.json b/scm-ui/eslint-config/package.json index 17cec9c9ee..81a7e17dc3 100644 --- a/scm-ui/eslint-config/package.json +++ b/scm-ui/eslint-config/package.json @@ -1,6 +1,6 @@ { "name": "@scm-manager/eslint-config", - "version": "2.8.0-SNAPSHOT", + "version": "2.9.0-SNAPSHOT", "description": "ESLint configuration for scm-manager and its plugins", "main": "src/index.js", "author": "Sebastian Sdorra ", diff --git a/scm-ui/jest-preset/package.json b/scm-ui/jest-preset/package.json index 6f8c5d71fc..be5c45a900 100644 --- a/scm-ui/jest-preset/package.json +++ b/scm-ui/jest-preset/package.json @@ -1,6 +1,6 @@ { "name": "@scm-manager/jest-preset", - "version": "2.8.0-SNAPSHOT", + "version": "2.9.0-SNAPSHOT", "description": "Jest presets for SCM-Manager and its plugins", "main": "src/index.js", "author": "Sebastian Sdorra ", diff --git a/scm-ui/pom.xml b/scm-ui/pom.xml index fce99381c3..d3ebd1cb29 100644 --- a/scm-ui/pom.xml +++ b/scm-ui/pom.xml @@ -32,13 +32,13 @@ sonia.scm scm - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT sonia.scm scm-ui war - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT scm-ui diff --git a/scm-ui/prettier-config/package.json b/scm-ui/prettier-config/package.json index 27c6e63597..857610f200 100644 --- a/scm-ui/prettier-config/package.json +++ b/scm-ui/prettier-config/package.json @@ -1,6 +1,6 @@ { "name": "@scm-manager/prettier-config", - "version": "2.8.0-SNAPSHOT", + "version": "2.9.0-SNAPSHOT", "license": "MIT", "description": "Prettier configuration", "author": "Sebastian Sdorra ", diff --git a/scm-ui/tsconfig/package.json b/scm-ui/tsconfig/package.json index 7801717520..7a75e132ff 100644 --- a/scm-ui/tsconfig/package.json +++ b/scm-ui/tsconfig/package.json @@ -1,6 +1,6 @@ { "name": "@scm-manager/tsconfig", - "version": "2.8.0-SNAPSHOT", + "version": "2.9.0-SNAPSHOT", "license": "MIT", "description": "TypeScript configuration", "author": "Sebastian Sdorra ", diff --git a/scm-ui/ui-components/.storybook/webpack.config.js b/scm-ui/ui-components/.storybook/webpack.config.js index 9269500c2d..9b7c1b6d26 100644 --- a/scm-ui/ui-components/.storybook/webpack.config.js +++ b/scm-ui/ui-components/.storybook/webpack.config.js @@ -50,8 +50,16 @@ module.exports = { use: [ // Creates `style` nodes from JS strings "style-loader", - // Translates CSS into CommonJS - "css-loader", + { + loader: "css-loader", + options: { + // Run `postcss-loader` on each CSS `@import`, do not forget that `sass-loader` compile non CSS `@import`'s into a single file + // If you need run `sass-loader` and `postcss-loader` on each CSS `@import` please set it to `2` + importLoaders: 1, + // Automatically enable css modules for files satisfying `/\.module\.\w+$/i` RegExp. + modules: { auto: true } + } + }, // Compiles Sass to CSS "sass-loader" ] diff --git a/scm-ui/ui-components/package.json b/scm-ui/ui-components/package.json index c4c8eb61fe..d7ab4e15a0 100644 --- a/scm-ui/ui-components/package.json +++ b/scm-ui/ui-components/package.json @@ -1,6 +1,6 @@ { "name": "@scm-manager/ui-components", - "version": "2.8.0-SNAPSHOT", + "version": "2.9.0-SNAPSHOT", "description": "UI Components for SCM-Manager and its plugins", "main": "src/index.ts", "files": [ @@ -18,7 +18,7 @@ "update-storyshots": "jest --testPathPattern=\"storyshots.test.ts\" --collectCoverage=false -u" }, "devDependencies": { - "@scm-manager/ui-tests": "^2.8.0-SNAPSHOT", + "@scm-manager/ui-tests": "^2.9.0-SNAPSHOT", "@storybook/addon-actions": "^5.2.3", "@storybook/addon-storyshots": "^5.2.3", "@storybook/react": "^5.2.3", @@ -34,7 +34,7 @@ "@types/react-router-dom": "^5.1.0", "@types/react-select": "^2.0.19", "@types/react-syntax-highlighter": "^11.0.1", - "@types/refractor": "^2.8.0", + "@types/refractor": "^3.0.0", "@types/storybook__addon-storyshots": "^5.1.1", "@types/styled-components": "^5.1.0", "@types/to-camel-case": "^1.0.0", @@ -51,8 +51,8 @@ "worker-plugin": "^3.2.0" }, "dependencies": { - "@scm-manager/ui-extensions": "^2.8.0-SNAPSHOT", - "@scm-manager/ui-types": "^2.8.0-SNAPSHOT", + "@scm-manager/ui-extensions": "^2.9.0-SNAPSHOT", + "@scm-manager/ui-types": "^2.9.0-SNAPSHOT", "classnames": "^2.2.6", "date-fns": "^2.4.1", "gitdiff-parser": "^0.1.2", diff --git a/scm-ui/ui-components/scripts/build-syntax-highlighting-javascript.js b/scm-ui/ui-components/scripts/build-syntax-highlighting-javascript.js index ca1ac2ed69..4d816c3c20 100644 --- a/scm-ui/ui-components/scripts/build-syntax-highlighting-javascript.js +++ b/scm-ui/ui-components/scripts/build-syntax-highlighting-javascript.js @@ -121,4 +121,4 @@ function createJavascriptStyleSheet(directory, inputFile, outputFile) { }); } -createJavascriptStyleSheet(path.join("..", "src"), "syntax-highlighting.css", "syntax-highlighting.ts"); +createJavascriptStyleSheet(path.join("..", "src"), "syntax-highlighting.module.css", "syntax-highlighting.ts"); diff --git a/scm-ui/ui-components/src/SyntaxHighlighter.stories.tsx b/scm-ui/ui-components/src/SyntaxHighlighter.stories.tsx index 7f458e4784..63961ac564 100644 --- a/scm-ui/ui-components/src/SyntaxHighlighter.stories.tsx +++ b/scm-ui/ui-components/src/SyntaxHighlighter.stories.tsx @@ -30,6 +30,7 @@ import JavaHttpServer from "./__resources__/HttpServer.java"; import GoHttpServer from "./__resources__/HttpServer.go"; import JsHttpServer from "./__resources__/HttpServer.js"; import PyHttpServer from "./__resources__/HttpServer.py"; +import Markdown from "./__resources__/test-page.md"; const Spacing = styled.div` padding: 1em; @@ -43,7 +44,7 @@ storiesOf("SyntaxHighlighter", module) )) .add("Go", () => ( - + )) .add("Javascript", () => ( @@ -56,6 +57,11 @@ storiesOf("SyntaxHighlighter", module) )) + .add("Markdown", () => ( + + + + )) .add("Without line numbers", () => ( diff --git a/scm-ui/ui-components/src/SyntaxHighlighter.tsx b/scm-ui/ui-components/src/SyntaxHighlighter.tsx index 852335e161..b665041913 100644 --- a/scm-ui/ui-components/src/SyntaxHighlighter.tsx +++ b/scm-ui/ui-components/src/SyntaxHighlighter.tsx @@ -24,6 +24,7 @@ import React from "react"; import { PrismAsyncLight as ReactSyntaxHighlighter } from "react-syntax-highlighter"; +import { defaultLanguage, determineLanguage } from "./languages"; // eslint-disable-next-line no-restricted-imports import highlightingTheme from "./syntax-highlighting"; @@ -33,27 +34,20 @@ type Props = { showLineNumbers?: boolean; }; -const defaultLanguage = "text"; - class SyntaxHighlighter extends React.Component { static defaultProps: Partial = { language: defaultLanguage, showLineNumbers: true }; - getLanguage = () => { - const { language } = this.props; - if (language) { - return language; - } - return defaultLanguage; - }; - render() { - const { showLineNumbers } = this.props; - const language = this.getLanguage(); + const { showLineNumbers, language } = this.props; return ( - + {this.props.value} ); diff --git a/scm-ui/ui-components/src/__resources__/Diff.markdown.ts b/scm-ui/ui-components/src/__resources__/Diff.markdown.ts new file mode 100644 index 0000000000..25c5dc77b3 --- /dev/null +++ b/scm-ui/ui-components/src/__resources__/Diff.markdown.ts @@ -0,0 +1,118 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +export default { + files: [ + { + oldPath: "CHANGELOG.md", + newPath: "CHANGELOG.md", + oldEndingNewLine: true, + newEndingNewLine: true, + oldRevision: "de732d6da1cc0be8454f004c14b7666c69c91fb4", + newRevision: "148eb799f3a56909fe65b966e093a482ba542c81", + type: "modify", + language: "markdown", + hunks: [ + { + content: "@@ -5,7 +5,7 @@", + oldStart: 5, + newStart: 5, + oldLines: 7, + newLines: 7, + changes: [ + { + content: "The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),", + type: "normal", + oldLineNumber: 5, + newLineNumber: 5, + isNormal: true + }, + { + content: "and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).", + type: "normal", + oldLineNumber: 6, + newLineNumber: 6, + isNormal: true + }, + { + content: "", + type: "normal", + oldLineNumber: 7, + newLineNumber: 7, + isNormal: true + }, + { + content: "## Unreleased", + type: "delete", + lineNumber: 8, + isDelete: true + }, + { + content: "## [2.7.1] - 2020-10-14", + type: "insert", + lineNumber: 8, + isInsert: true + }, + { + content: "### Fixed", + type: "normal", + oldLineNumber: 9, + newLineNumber: 9, + isNormal: true + }, + { + content: + "- Null Pointer Exception on anonymous migration with deleted repositories ([#1371](https://github.com/scm-manager/scm-manager/pull/1371))", + type: "normal", + oldLineNumber: 10, + newLineNumber: 10, + isNormal: true + }, + { + content: + "- Null Pointer Exception on parsing SVN properties ([#1373](https://github.com/scm-manager/scm-manager/pull/1373))", + type: "normal", + oldLineNumber: 11, + newLineNumber: 11, + isNormal: true + } + ] + } + ], + _links: { + lines: { + href: + "http://localhost:8081/scm/api/v2/repositories/scmadmin/scm-manager/content/fbffdea2a566dc4ac54ea38d4aade5aaf541e7f2/CHANGELOG.md?start={start}&end={end}", + templated: true + } + } + } + ], + _links: { + self: { + href: + "http://localhost:8081/scm/api/v2/repositories/scmadmin/scm-manager/diff/fbffdea2a566dc4ac54ea38d4aade5aaf541e7f2/parsed" + } + } +}; diff --git a/scm-ui/ui-components/src/__snapshots__/storyshots.test.ts.snap b/scm-ui/ui-components/src/__snapshots__/storyshots.test.ts.snap index 2129da9f5e..7c552c9c62 100644 --- a/scm-ui/ui-components/src/__snapshots__/storyshots.test.ts.snap +++ b/scm-ui/ui-components/src/__snapshots__/storyshots.test.ts.snap @@ -553,6 +553,487 @@ exports[`Storyshots Annotate Default 1`] = ` `; +exports[`Storyshots Annotate Markdown 1`] = ` +
+
+
+      
+        
+
+
+ Arthur Dent +
+ +
+ +
+ +
+
+ 1 +
+ +
+ + + # + + + Title + + + + + + +
+
+
+
+
+ 2 +
+ +
+ + + + +
+
+
+
+
+ Tricia Marie McMillan +
+ +
+ +
+ +
+
+ 3 +
+ +
+ + This is a short Markdown text. + + +
+
+
+
+
+ 4 +
+ +
+ + + + +
+
+
+
+
+ Arthur Dent +
+ +
+ +
+ +
+
+ 5 +
+ +
+ + + With + + + ** + + + bold + + + ** + + + and + + + __ + + + italic + + + __ + + + words. + + + +
+
+
+
+
+ Ford Prefect +
+ +
+ +
+ +
+
+ 6 +
+ +
+ + + + +
+
+
+
+
+ Arthur Dent +
+ +
+ +
+ +
+
+ 7 +
+ +
+ + + + + + > + + + This should be a quote + + + +
+
+
+
+
+ 8 +
+ +
+ + + + +
+
+ + + + +
+
+
+
+`; + exports[`Storyshots Annotate With Avatars 1`] = `
@@ -4407,7 +4888,7 @@ exports[`Storyshots Diff Binaries 1`] = ` className="panel-block is-paddingless" >
@@ -5271,7 +5752,7 @@ exports[`Storyshots Diff CollapsingWithFunction 1`] = ` className="panel-block is-paddingless" >
@@ -6129,7 +6610,7 @@ exports[`Storyshots Diff CollapsingWithFunction 1`] = ` className="panel-block is-paddingless" >
@@ -6583,7 +7064,7 @@ exports[`Storyshots Diff CollapsingWithFunction 1`] = ` className="panel-block is-paddingless" >
@@ -7196,7 +7677,7 @@ exports[`Storyshots Diff Default 1`] = ` className="panel-block is-paddingless" >
@@ -7777,7 +8258,7 @@ exports[`Storyshots Diff Default 1`] = ` className="panel-block is-paddingless" >
@@ -8635,7 +9116,7 @@ exports[`Storyshots Diff Default 1`] = ` className="panel-block is-paddingless" >
@@ -9089,7 +9570,7 @@ exports[`Storyshots Diff Default 1`] = ` className="panel-block is-paddingless" >
@@ -9543,7 +10024,7 @@ exports[`Storyshots Diff Default 1`] = ` className="panel-block is-paddingless" >
@@ -10604,7 +11085,7 @@ exports[`Storyshots Diff Default 1`] = ` className="panel-block is-paddingless" >
@@ -11142,7 +11623,7 @@ exports[`Storyshots Diff Expandable 1`] = ` className="panel-block is-paddingless" >
@@ -11760,7 +12241,7 @@ exports[`Storyshots Diff Expandable 1`] = ` className="panel-block is-paddingless" >
@@ -12715,7 +13196,7 @@ exports[`Storyshots Diff Expandable 1`] = ` className="panel-block is-paddingless" >
@@ -13241,7 +13722,7 @@ exports[`Storyshots Diff Expandable 1`] = ` className="panel-block is-paddingless" >
@@ -13767,7 +14248,7 @@ exports[`Storyshots Diff Expandable 1`] = ` className="panel-block is-paddingless" >
@@ -14983,7 +15464,7 @@ exports[`Storyshots Diff Expandable 1`] = ` className="panel-block is-paddingless" >
@@ -15562,7 +16043,7 @@ exports[`Storyshots Diff File Annotation 1`] = ` src/main/java/com/cloudogu/scm/review/events/EventListener.java

@@ -16147,7 +16628,7 @@ exports[`Storyshots Diff File Annotation 1`] = ` src/main/js/ChangeNotification.tsx

@@ -17009,7 +17490,7 @@ exports[`Storyshots Diff File Annotation 1`] = ` src/main/resources/locales/de/plugins.json

@@ -17467,7 +17948,7 @@ exports[`Storyshots Diff File Annotation 1`] = ` src/main/resources/locales/en/plugins.json

@@ -17925,7 +18406,7 @@ exports[`Storyshots Diff File Annotation 1`] = ` src/test/java/com/cloudogu/scm/review/events/ClientTest.java

@@ -18990,7 +19471,7 @@ exports[`Storyshots Diff File Annotation 1`] = ` Main.java

@@ -19546,7 +20027,7 @@ exports[`Storyshots Diff File Controls 1`] = ` className="panel-block is-paddingless" >
@@ -20145,7 +20626,7 @@ exports[`Storyshots Diff File Controls 1`] = ` className="panel-block is-paddingless" >
@@ -21021,7 +21502,7 @@ exports[`Storyshots Diff File Controls 1`] = ` className="panel-block is-paddingless" >
@@ -21493,7 +21974,7 @@ exports[`Storyshots Diff File Controls 1`] = ` className="panel-block is-paddingless" >
@@ -21965,7 +22446,7 @@ exports[`Storyshots Diff File Controls 1`] = ` className="panel-block is-paddingless" >
@@ -23044,7 +23525,7 @@ exports[`Storyshots Diff File Controls 1`] = ` className="panel-block is-paddingless" >
@@ -23582,7 +24063,7 @@ exports[`Storyshots Diff Hunks 1`] = ` className="panel-block is-paddingless" >
@@ -24427,7 +24908,7 @@ exports[`Storyshots Diff Line Annotation 1`] = ` className="panel-block is-paddingless" >
@@ -25020,7 +25501,7 @@ exports[`Storyshots Diff Line Annotation 1`] = ` className="panel-block is-paddingless" >
@@ -25890,7 +26371,7 @@ exports[`Storyshots Diff Line Annotation 1`] = ` className="panel-block is-paddingless" >
@@ -26344,7 +26825,7 @@ exports[`Storyshots Diff Line Annotation 1`] = ` className="panel-block is-paddingless" >
@@ -26798,7 +27279,7 @@ exports[`Storyshots Diff Line Annotation 1`] = ` className="panel-block is-paddingless" >
@@ -27859,7 +28340,7 @@ exports[`Storyshots Diff Line Annotation 1`] = ` className="panel-block is-paddingless" >
@@ -28409,7 +28890,7 @@ exports[`Storyshots Diff OnClick 1`] = ` className="panel-block is-paddingless" >
@@ -29030,7 +29511,7 @@ exports[`Storyshots Diff OnClick 1`] = ` className="panel-block is-paddingless" >
@@ -29950,7 +30431,7 @@ exports[`Storyshots Diff OnClick 1`] = ` className="panel-block is-paddingless" >
@@ -30434,7 +30915,7 @@ exports[`Storyshots Diff OnClick 1`] = ` className="panel-block is-paddingless" >
@@ -30918,7 +31399,7 @@ exports[`Storyshots Diff OnClick 1`] = ` className="panel-block is-paddingless" >
@@ -32055,7 +32536,7 @@ exports[`Storyshots Diff OnClick 1`] = ` className="panel-block is-paddingless" >
@@ -32629,7 +33110,7 @@ exports[`Storyshots Diff Side-By-Side 1`] = ` className="panel-block is-paddingless" >
@@ -33303,7 +33784,7 @@ exports[`Storyshots Diff Side-By-Side 1`] = ` className="panel-block is-paddingless" >
@@ -34251,7 +34732,7 @@ exports[`Storyshots Diff Side-By-Side 1`] = ` className="panel-block is-paddingless" >
@@ -34757,7 +35238,7 @@ exports[`Storyshots Diff Side-By-Side 1`] = ` className="panel-block is-paddingless" >
@@ -35263,7 +35744,7 @@ exports[`Storyshots Diff Side-By-Side 1`] = ` className="panel-block is-paddingless" >
@@ -36493,7 +36974,7 @@ exports[`Storyshots Diff Side-By-Side 1`] = ` className="panel-block is-paddingless" >
@@ -37021,6 +37502,369 @@ exports[`Storyshots Diff Side-By-Side 1`] = ` `; +exports[`Storyshots Diff SyntaxHighlighting (Markdown) 1`] = ` +
+
+
+
+
+
+ + + CHANGELOG.md + + + modify + +
+
+
+
+ + + + + +
+
+ + + + + +
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + diff.expandComplete + +
+
+ 5 + + 5 + + The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +
+ 6 + + 6 + + and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +
+ 7 + + 7 + + +
+ 8 + + + ## Unreleased +
+ + 8 + + ## [2.7.1] - 2020-10-14 +
+ 9 + + 9 + + ### Fixed +
+ 10 + + 10 + + - Null Pointer Exception on anonymous migration with deleted repositories ([#1371](https://github.com/scm-manager/scm-manager/pull/1371)) +
+ 11 + + 11 + + - Null Pointer Exception on parsing SVN properties ([#1373](https://github.com/scm-manager/scm-manager/pull/1373)) +
+
+ + + + diff.expandLastBottomByLines + + + + + + diff.expandLastBottomComplete + +
+
+
+ + + +`; + exports[`Storyshots Diff SyntaxHighlighting 1`] = `
@@ -37685,7 +38529,7 @@ exports[`Storyshots Diff SyntaxHighlighting 1`] = ` className="panel-block is-paddingless" >
@@ -38543,7 +39387,7 @@ exports[`Storyshots Diff SyntaxHighlighting 1`] = ` className="panel-block is-paddingless" >
@@ -38997,7 +39841,7 @@ exports[`Storyshots Diff SyntaxHighlighting 1`] = ` className="panel-block is-paddingless" >
@@ -39451,7 +40295,7 @@ exports[`Storyshots Diff SyntaxHighlighting 1`] = ` className="panel-block is-paddingless" >
@@ -40512,7 +41356,7 @@ exports[`Storyshots Diff SyntaxHighlighting 1`] = ` className="panel-block is-paddingless" >
@@ -41050,7 +41894,7 @@ exports[`Storyshots Diff WithLinkToFile 1`] = ` className="panel-block is-paddingless" >
@@ -41668,7 +42512,7 @@ exports[`Storyshots Diff WithLinkToFile 1`] = ` className="panel-block is-paddingless" >
@@ -42623,7 +43467,7 @@ exports[`Storyshots Diff WithLinkToFile 1`] = ` className="panel-block is-paddingless" >
@@ -43149,7 +43993,7 @@ exports[`Storyshots Diff WithLinkToFile 1`] = ` className="panel-block is-paddingless" >
@@ -43675,7 +44519,7 @@ exports[`Storyshots Diff WithLinkToFile 1`] = ` className="panel-block is-paddingless" >
@@ -44891,7 +45735,7 @@ exports[`Storyshots Diff WithLinkToFile 1`] = ` className="panel-block is-paddingless" >
@@ -54543,6 +55387,6388 @@ exports[`Storyshots SyntaxHighlighter Javascript 1`] = ` `; +exports[`Storyshots SyntaxHighlighter Markdown 1`] = ` +
+
+    
+      
+        1
+      
+      
+        #
+      
+      
+         <a name="top"></a>Markdown Test Page
+      
+      
+        
+
+      
+      
+        2
+      
+      
+
+      
+        3
+      
+      
+        
+      
+      
+        *
+      
+      
+         
+      
+      
+        [
+      
+      
+        Headings
+      
+      
+        ](#Headings)
+      
+      
+        
+
+      
+      
+        4
+      
+      
+        
+      
+      
+        *
+      
+      
+         
+      
+      
+        [
+      
+      
+        Paragraphs
+      
+      
+        ](#Paragraphs)
+      
+      
+        
+
+      
+      
+        5
+      
+      
+        
+      
+      
+        *
+      
+      
+         
+      
+      
+        [
+      
+      
+        Blockquotes
+      
+      
+        ](#Blockquotes)
+      
+      
+        
+
+      
+      
+        6
+      
+      
+        
+      
+      
+        *
+      
+      
+         
+      
+      
+        [
+      
+      
+        Lists
+      
+      
+        ](#Lists)
+      
+      
+        
+
+      
+      
+        7
+      
+      
+        
+      
+      
+        *
+      
+      
+         
+      
+      
+        [
+      
+      
+        Horizontal rule
+      
+      
+        ](#Horizontal)
+      
+      
+        
+
+      
+      
+        8
+      
+      
+        
+      
+      
+        *
+      
+      
+         
+      
+      
+        [
+      
+      
+        Table
+      
+      
+        ](#Table)
+      
+      
+        
+
+      
+      
+        9
+      
+      
+        
+      
+      
+        *
+      
+      
+         
+      
+      
+        [
+      
+      
+        Code
+      
+      
+        ](#Code)
+      
+      
+        
+
+      
+      
+        10
+      
+      
+        
+      
+      
+        *
+      
+      
+         
+      
+      
+        [
+      
+      
+        Inline elements
+      
+      
+        ](#Inline)
+      
+      
+        
+
+      
+      
+        11
+      
+      
+
+      
+        12
+      
+      
+        
+      
+      
+        ***
+      
+      
+        
+
+      
+      
+        13
+      
+      
+
+      
+        14
+      
+      
+        
+      
+      
+        #
+      
+      
+         <a name="Headings"></a>Headings
+      
+      
+        
+
+      
+      
+        15
+      
+      
+
+      
+        16
+      
+      
+        
+      
+      
+        #
+      
+      
+         Heading one
+      
+      
+        
+
+      
+      
+        17
+      
+      
+
+      
+        18
+      
+      Sint sit cillum pariatur eiusmod nulla pariatur ipsum. Sit laborum anim qui mollit tempor pariatur nisi minim dolor. Aliquip et adipisicing sit sit fugiat commodo id sunt. Nostrud enim ad commodo incididunt cupidatat in ullamco ullamco Lorem cupidatat velit enim et Lorem. Ut laborum cillum laboris fugiat culpa sint irure do reprehenderit culpa occaecat. Exercitation esse mollit tempor magna aliqua in occaecat aliquip veniam reprehenderit nisi dolor in laboris dolore velit.
+
+      
+        19
+      
+      
+
+      
+        20
+      
+      
+        
+      
+      
+        ##
+      
+      
+         Heading two
+      
+      
+        
+
+      
+      
+        21
+      
+      
+
+      
+        22
+      
+      Aute officia nulla deserunt do deserunt cillum velit magna. Officia veniam culpa anim minim dolore labore pariatur voluptate id ad est duis quis velit dolor pariatur enim. Incididunt enim excepteur do veniam consequat culpa do voluptate dolor fugiat ad adipisicing sit. Labore officia est adipisicing dolore proident eiusmod exercitation deserunt ullamco anim do occaecat velit. Elit dolor consectetur proident sunt aliquip est do tempor quis aliqua culpa aute. Duis in tempor exercitation pariatur et adipisicing mollit irure tempor ut enim esse commodo laboris proident. Do excepteur laborum anim esse aliquip eu sit id Lorem incididunt elit irure ea nulla dolor et. Nulla amet fugiat qui minim deserunt enim eu cupidatat aute officia do velit ea reprehenderit.
+
+      
+        23
+      
+      
+
+      
+        24
+      
+      
+        
+      
+      
+        ###
+      
+      
+         Heading three
+      
+      
+        
+
+      
+      
+        25
+      
+      
+
+      
+        26
+      
+      Voluptate cupidatat cillum elit quis ipsum eu voluptate fugiat consectetur enim. Quis ut voluptate culpa ex anim aute consectetur dolore proident voluptate exercitation eiusmod. Esse in do anim magna minim culpa sint. Adipisicing ipsum consectetur proident ullamco magna sit amet aliqua aute fugiat laborum exercitation duis et.
+
+      
+        27
+      
+      
+
+      
+        28
+      
+      
+        
+      
+      
+        ####
+      
+      
+         Heading four
+      
+      
+        
+
+      
+      
+        29
+      
+      
+
+      
+        30
+      
+      Commodo fugiat aliqua minim quis pariatur mollit id tempor. Non occaecat minim esse enim aliqua adipisicing nostrud duis consequat eu adipisicing qui. Minim aliquip sit excepteur ipsum consequat laborum pariatur excepteur. Veniam fugiat et amet ad elit anim laborum duis mollit occaecat et et ipsum et reprehenderit. Occaecat aliquip dolore adipisicing sint labore occaecat officia fugiat. Quis adipisicing exercitation exercitation eu amet est laboris sunt nostrud ipsum reprehenderit ullamco. Enim sint ut consectetur id anim aute voluptate exercitation mollit dolore magna magna est Lorem. Ut adipisicing adipisicing aliqua ullamco voluptate labore nisi tempor esse magna incididunt.
+
+      
+        31
+      
+      
+
+      
+        32
+      
+      
+        
+      
+      
+        #####
+      
+      
+         Heading five
+      
+      
+        
+
+      
+      
+        33
+      
+      
+
+      
+        34
+      
+      Veniam enim esse amet veniam deserunt laboris amet enim consequat. Minim nostrud deserunt cillum consectetur commodo eu enim nostrud ullamco occaecat excepteur. Aliquip et ut est commodo enim dolor amet sint excepteur. Amet ad laboris laborum deserunt sint sunt aliqua commodo ex duis deserunt enim est ex labore ut. Duis incididunt velit adipisicing non incididunt adipisicing adipisicing. Ad irure duis nisi tempor eu dolor fugiat magna et consequat tempor eu ex dolore. Mollit esse nisi qui culpa ut nisi ex proident culpa cupidatat cillum culpa occaecat anim. Ut officia sit ea nisi ea excepteur nostrud ipsum et nulla.
+
+      
+        35
+      
+      
+
+      
+        36
+      
+      
+        
+      
+      
+        ######
+      
+      
+         Heading six
+      
+      
+        
+
+      
+      
+        37
+      
+      
+
+      
+        38
+      
+      Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
+
+      
+        39
+      
+      
+
+      
+        40
+      
+      
+
+      
+        41
+      
+      [[Top]](#top)
+
+      
+        42
+      
+      
+
+      
+        43
+      
+      
+        
+      
+      
+        #
+      
+      
+         <a name="Paragraphs"></a>Paragraphs
+      
+      
+        
+
+      
+      
+        44
+      
+      
+
+      
+        45
+      
+      Incididunt ex adipisicing ea ullamco consectetur in voluptate proident fugiat tempor deserunt reprehenderit ullamco id dolore laborum. Do laboris laboris minim incididunt qui consectetur exercitation adipisicing dolore et magna consequat magna anim sunt. Officia fugiat Lorem sunt pariatur incididunt Lorem reprehenderit proident irure. Dolore ipsum aliqua mollit ad officia fugiat sit eu aliquip cupidatat ipsum duis laborum laborum fugiat esse. Voluptate anim ex dolore deserunt ea ex eiusmod irure. Occaecat excepteur aliqua exercitation aliquip dolor esse eu eu.
+
+      
+        46
+      
+      
+
+      
+        47
+      
+      Officia dolore laborum aute incididunt commodo nisi velit est est elit et dolore elit exercitation. Enim aliquip magna id ipsum aliquip consectetur ad nulla quis. Incididunt pariatur dolor consectetur cillum enim velit cupidatat laborum quis ex.
+
+      
+        48
+      
+      
+
+      
+        49
+      
+      Officia irure in non voluptate adipisicing sit amet tempor duis dolore deserunt enim ut. Reprehenderit incididunt in ad anim et deserunt deserunt Lorem laborum quis. Enim aute anim labore proident laboris voluptate elit excepteur in. Ex labore nulla velit officia ullamco Lorem Lorem id do. Dolore ullamco ipsum magna dolor pariatur voluptate ipsum id occaecat ipsum. Dolore tempor quis duis commodo quis quis enim.
+
+      
+        50
+      
+      
+
+      
+        51
+      
+      [[Top]](#top)
+
+      
+        52
+      
+      
+
+      
+        53
+      
+      
+        
+      
+      
+        #
+      
+      
+         <a name="Blockquotes"></a>Blockquotes
+      
+      
+        
+
+      
+      
+        54
+      
+      
+
+      
+        55
+      
+      Ad nisi laborum aute cupidatat magna deserunt eu id laboris id. Aliquip nulla cupidatat sint ex Lorem mollit laborum dolor amet est ut esse aute. Nostrud ex consequat id incididunt proident ipsum minim duis aliqua ut ex et ad quis. Laborum sint esse cillum anim nulla cillum consectetur aliqua sit. Nisi excepteur cillum labore amet excepteur commodo enim occaecat consequat ipsum proident exercitation duis id in.
+
+      
+        56
+      
+      
+
+      
+        57
+      
+      
+        
+      
+      
+        >
+      
+      
+         Ipsum et cupidatat mollit exercitation enim duis sunt irure aliqua reprehenderit mollit. Pariatur Lorem pariatur laboris do culpa do elit irure. Eiusmod amet nulla voluptate velit culpa et aliqua ad reprehenderit sit ut.
+
+      
+      
+        58
+      
+      
+
+      
+        59
+      
+      Labore ea magna Lorem consequat aliquip consectetur cillum duis dolore. Et veniam dolor qui incididunt minim amet laboris sit. Dolore ad esse commodo et dolore amet est velit ut nisi ea. Excepteur ea nulla commodo dolore anim dolore adipisicing eiusmod labore id enim esse quis mollit deserunt est. Minim ea culpa voluptate nostrud commodo proident in duis aliquip minim.
+
+      
+        60
+      
+      
+
+      
+        61
+      
+      
+        
+      
+      
+        >
+      
+      
+         Qui est sit et reprehenderit aute est esse enim aliqua id aliquip ea anim. Pariatur sint reprehenderit mollit velit voluptate enim consectetur sint enim. Quis exercitation proident elit non id qui culpa dolore esse aliquip consequat.
+
+      
+      
+        62
+      
+      
+
+      
+        63
+      
+      Ipsum excepteur cupidatat sunt minim ad eiusmod tempor sit.
+
+      
+        64
+      
+      
+
+      
+        65
+      
+      
+        
+      
+      
+        >
+      
+      
+         Deserunt excepteur adipisicing culpa pariatur cillum laboris ullamco nisi fugiat cillum officia. In cupidatat nulla aliquip tempor ad Lorem Lorem quis voluptate officia consectetur pariatur ex in est duis. Mollit id esse est elit exercitation voluptate nostrud nisi laborum magna dolore dolore tempor in est consectetur.
+
+      
+      
+        66
+      
+      
+
+      
+        67
+      
+      Adipisicing voluptate ipsum culpa voluptate id aute laboris labore esse fugiat veniam ullamco occaecat do ut. Tempor et esse reprehenderit veniam proident ipsum irure sit ullamco et labore ea excepteur nulla labore ut. Ex aute minim quis tempor in eu id id irure ea nostrud dolor esse.
+
+      
+        68
+      
+      
+
+      
+        69
+      
+      [[Top]](#top)
+
+      
+        70
+      
+      
+
+      
+        71
+      
+      
+        
+      
+      
+        #
+      
+      
+         <a name="Lists"></a>Lists
+      
+      
+        
+
+      
+      
+        72
+      
+      
+
+      
+        73
+      
+      
+        
+      
+      
+        ###
+      
+      
+         Ordered List
+      
+      
+        
+
+      
+      
+        74
+      
+      
+
+      
+        75
+      
+      
+        
+      
+      
+        1.
+      
+      
+         Longan
+
+      
+      
+        76
+      
+      
+        
+      
+      
+        2.
+      
+      
+         Lychee
+
+      
+      
+        77
+      
+      
+        
+      
+      
+        3.
+      
+      
+         Excepteur ad cupidatat do elit laborum amet cillum reprehenderit consequat quis.
+
+      
+      
+        78
+      
+          Deserunt officia esse aliquip consectetur duis ut labore laborum commodo aliquip aliquip velit pariatur dolore.
+
+      
+        79
+      
+      
+        
+      
+      
+        4.
+      
+      
+         Marionberry
+
+      
+      
+        80
+      
+      
+        
+      
+      
+        5.
+      
+      
+         Melon
+
+      
+      
+        81
+      
+      
+            
+      
+      
+        -
+      
+      
+         Cantaloupe
+
+      
+      
+        82
+      
+      
+            
+      
+      
+        -
+      
+      
+         Honeydew
+
+      
+      
+        83
+      
+      
+            
+      
+      
+        -
+      
+      
+         Watermelon
+
+      
+      
+        84
+      
+      
+        
+      
+      
+        6.
+      
+      
+         Miracle fruit
+
+      
+      
+        85
+      
+      
+        
+      
+      
+        7.
+      
+      
+         Mulberry
+
+      
+      
+        86
+      
+      
+
+      
+        87
+      
+      
+        
+      
+      
+        ###
+      
+      
+         Unordered List
+      
+      
+        
+
+      
+      
+        88
+      
+      
+
+      
+        89
+      
+      
+        
+      
+      
+        -
+      
+      
+         Olive
+
+      
+      
+        90
+      
+      
+        
+      
+      
+        -
+      
+      
+         Orange
+
+      
+      
+        91
+      
+      
+            
+      
+      
+        -
+      
+      
+         Blood orange
+
+      
+      
+        92
+      
+      
+            
+      
+      
+        -
+      
+      
+         Clementine
+
+      
+      
+        93
+      
+      
+        
+      
+      
+        -
+      
+      
+         Papaya
+
+      
+      
+        94
+      
+      
+        
+      
+      
+        -
+      
+      
+         Ut aute ipsum occaecat nisi culpa Lorem id occaecat cupidatat id id magna laboris ad duis. Fugiat cillum dolore veniam nostrud proident sint consectetur eiusmod irure adipisicing.
+
+      
+      
+        95
+      
+      
+        
+      
+      
+        -
+      
+      
+         Passionfruit
+
+      
+      
+        96
+      
+      
+
+      
+        97
+      
+      [[Top]](#top)
+
+      
+        98
+      
+      
+
+      
+        99
+      
+      
+        
+      
+      
+        #
+      
+      
+         <a name="Horizontal"></a>Horizontal rule
+      
+      
+        
+
+      
+      
+        100
+      
+      
+
+      
+        101
+      
+      In dolore velit aliquip labore mollit minim tempor veniam eu veniam ad in sint aliquip mollit mollit. Ex occaecat non deserunt elit laborum sunt tempor sint consequat culpa culpa qui sit. Irure ad commodo eu voluptate mollit cillum cupidatat veniam proident amet minim reprehenderit.
+
+      
+        102
+      
+      
+
+      
+        103
+      
+      
+        
+      
+      
+        ***
+      
+      
+        
+
+      
+      
+        104
+      
+      
+
+      
+        105
+      
+      In laboris eiusmod reprehenderit aliquip sit proident occaecat. Non sit labore anim elit veniam Lorem minim commodo eiusmod irure do minim nisi. Dolor amet cillum excepteur consequat sint non sint.
+
+      
+        106
+      
+      
+
+      
+        107
+      
+      [[Top]](#top)
+
+      
+        108
+      
+      
+
+      
+        109
+      
+      
+        
+      
+      
+        #
+      
+      
+         <a name="Table"></a>Table
+      
+      
+        
+
+      
+      
+        110
+      
+      
+
+      
+        111
+      
+      Duis sunt ut pariatur reprehenderit mollit mollit magna dolore in pariatur nulla commodo sit dolor ad fugiat. Laboris amet ea occaecat duis eu enim exercitation deserunt ea laborum occaecat reprehenderit. Et incididunt dolor commodo consequat mollit nisi proident non pariatur in et incididunt id. Eu ut et Lorem ea ex magna minim ipsum ipsum do.
+
+      
+        112
+      
+      
+
+      
+        113
+      
+      
+        
+      
+      
+        |
+      
+      
+         Table Heading 1 
+      
+      
+        |
+      
+      
+         Table Heading 2 
+      
+      
+        |
+      
+      
+         Center align    
+      
+      
+        |
+      
+      
+         Right align     
+      
+      
+        |
+      
+      
+         Table Heading 5 
+      
+      
+        |
+      
+      
+        
+
+      
+      
+        114
+      
+      
+        
+      
+      
+        |
+      
+      
+         
+      
+      
+        :--------------
+      
+      
+         
+      
+      
+        |
+      
+      
+         
+      
+      
+        :--------------
+      
+      
+         
+      
+      
+        |
+      
+      
+         
+      
+      
+        :-------------:
+      
+      
+         
+      
+      
+        |
+      
+      
+         
+      
+      
+        --------------:
+      
+      
+         
+      
+      
+        |
+      
+      
+         
+      
+      
+        :--------------
+      
+      
+         
+      
+      
+        |
+      
+      
+        
+
+      
+      
+        115
+      
+      
+        
+      
+      
+        |
+      
+      
+         Item 1          
+      
+      
+        |
+      
+      
+         Item 2          
+      
+      
+        |
+      
+      
+         Item 3          
+      
+      
+        |
+      
+      
+         Item 4          
+      
+      
+        |
+      
+      
+         Item 5          
+      
+      
+        |
+      
+      
+        
+
+      
+      
+        116
+      
+      
+        
+      
+      
+        |
+      
+      
+         Item 1          
+      
+      
+        |
+      
+      
+         Item 2          
+      
+      
+        |
+      
+      
+         Item 3          
+      
+      
+        |
+      
+      
+         Item 4          
+      
+      
+        |
+      
+      
+         Item 5          
+      
+      
+        |
+      
+      
+        
+
+      
+      
+        117
+      
+      
+        
+      
+      
+        |
+      
+      
+         Item 1          
+      
+      
+        |
+      
+      
+         Item 2          
+      
+      
+        |
+      
+      
+         Item 3          
+      
+      
+        |
+      
+      
+         Item 4          
+      
+      
+        |
+      
+      
+         Item 5          
+      
+      
+        |
+      
+      
+        
+
+      
+      
+        118
+      
+      
+        
+      
+      
+        |
+      
+      
+         Item 1          
+      
+      
+        |
+      
+      
+         Item 2          
+      
+      
+        |
+      
+      
+         Item 3          
+      
+      
+        |
+      
+      
+         Item 4          
+      
+      
+        |
+      
+      
+         Item 5          
+      
+      
+        |
+      
+      
+        
+
+      
+      
+        119
+      
+      
+        
+      
+      
+        |
+      
+      
+         Item 1          
+      
+      
+        |
+      
+      
+         Item 2          
+      
+      
+        |
+      
+      
+         Item 3          
+      
+      
+        |
+      
+      
+         Item 4          
+      
+      
+        |
+      
+      
+         Item 5          
+      
+      
+        |
+      
+      
+        
+
+      
+      
+        120
+      
+      
+        
+      
+      
+        
+
+      
+      
+        121
+      
+      Minim id consequat adipisicing cupidatat laborum culpa veniam non consectetur et duis pariatur reprehenderit eu ex consectetur. Sunt nisi qui eiusmod ut cillum laborum Lorem officia aliquip laboris ullamco nostrud laboris non irure laboris. Cillum dolore labore Lorem deserunt mollit voluptate esse incididunt ex dolor.
+
+      
+        122
+      
+      
+
+      
+        123
+      
+      [[Top]](#top)
+
+      
+        124
+      
+      
+
+      
+        125
+      
+      
+        
+      
+      
+        #
+      
+      
+         <a name="Code"></a>Code
+      
+      
+        
+
+      
+      
+        126
+      
+      
+
+      
+        127
+      
+      
+        
+      
+      
+        ##
+      
+      
+         Inline code
+      
+      
+        
+
+      
+      
+        128
+      
+      
+
+      
+        129
+      
+      
+        Ad amet irure est magna id mollit Lorem in do duis enim. Excepteur velit nisi magna ea pariatur pariatur ullamco fugiat deserunt sint non sint. Duis duis est 
+      
+      
+        \`code in text\`
+      
+      
+         velit velit aute culpa ex quis pariatur pariatur laborum aute pariatur duis tempor sunt ad. Irure magna voluptate dolore consectetur consectetur irure esse. Anim magna 
+      
+      
+        \`<strong>in culpa qui officia</strong>\`
+      
+      
+         dolor eiusmod esse amet aute cupidatat aliqua do id voluptate cupidatat reprehenderit amet labore deserunt.
+
+      
+      
+        130
+      
+      
+
+      
+        131
+      
+      
+        
+      
+      
+        ##
+      
+      
+         Highlighted
+      
+      
+        
+
+      
+      
+        132
+      
+      
+
+      
+        133
+      
+      Et fugiat ad nisi amet magna labore do cillum fugiat occaecat cillum Lorem proident. In sint dolor ullamco ad do adipisicing amet id excepteur Lorem aliquip sit irure veniam laborum duis cillum. Aliqua occaecat minim cillum deserunt magna sunt laboris do do irure ea nostrud consequat ut voluptate ex.
+
+      
+        134
+      
+      
+
+      
+        135
+      
+      
+        
+      
+      
+        \`\`\`
+      
+      
+        go
+      
+      
+        
+
+      
+      
+        136
+      
+      
+        
+      
+      
+        package
+      
+      
+         main
+
+      
+      
+        
+          137
+        
+        
+
+      
+      
+        138
+      
+      
+        
+      
+      
+        import
+      
+      
+         
+      
+      
+        (
+      
+      
+        
+
+      
+      
+        139
+      
+      
+            
+      
+      
+        "fmt"
+      
+      
+        
+
+      
+      
+        140
+      
+      
+            
+      
+      
+        "net/http"
+      
+      
+        
+
+      
+      
+        141
+      
+      
+        
+      
+      
+        )
+      
+      
+        
+
+      
+      
+        
+          142
+        
+        
+
+      
+      
+        143
+      
+      
+        
+      
+      
+        func
+      
+      
+         
+      
+      
+        handler
+      
+      
+        (
+      
+      
+        w http
+      
+      
+        .
+      
+      
+        ResponseWriter
+      
+      
+        ,
+      
+      
+         r 
+      
+      
+        *
+      
+      
+        http
+      
+      
+        .
+      
+      
+        Request
+      
+      
+        )
+      
+      
+         
+      
+      
+        {
+      
+      
+        
+
+      
+      
+        144
+      
+      
+            fmt
+      
+      
+        .
+      
+      
+        Fprintf
+      
+      
+        (
+      
+      
+        w
+      
+      
+        ,
+      
+      
+         
+      
+      
+        "Hi there, I love %s!"
+      
+      
+        ,
+      
+      
+         r
+      
+      
+        .
+      
+      
+        URL
+      
+      
+        .
+      
+      
+        Path
+      
+      
+        [
+      
+      
+        1
+      
+      
+        :
+      
+      
+        ]
+      
+      
+        )
+      
+      
+        
+
+      
+      
+        145
+      
+      
+        
+      
+      
+        }
+      
+      
+        
+
+      
+      
+        
+          146
+        
+        
+
+      
+      
+        147
+      
+      
+        
+      
+      
+        func
+      
+      
+         
+      
+      
+        main
+      
+      
+        (
+      
+      
+        )
+      
+      
+         
+      
+      
+        {
+      
+      
+        
+
+      
+      
+        148
+      
+      
+            http
+      
+      
+        .
+      
+      
+        HandleFunc
+      
+      
+        (
+      
+      
+        "/"
+      
+      
+        ,
+      
+      
+         handler
+      
+      
+        )
+      
+      
+        
+
+      
+      
+        149
+      
+      
+            http
+      
+      
+        .
+      
+      
+        ListenAndServe
+      
+      
+        (
+      
+      
+        ":8080"
+      
+      
+        ,
+      
+      
+         
+      
+      
+        nil
+      
+      
+        )
+      
+      
+        
+
+      
+      
+        150
+      
+      
+        
+      
+      
+        }
+      
+      
+        
+
+      
+      
+        151
+      
+      
+        
+      
+      
+        \`\`\`
+      
+      
+        
+
+      
+      
+        152
+      
+      
+
+      
+        153
+      
+      Ex amet id ex aliquip id do laborum excepteur exercitation elit sint commodo occaecat nostrud est. Nostrud pariatur esse veniam laborum non sint magna sit laboris minim in id. Aliqua pariatur pariatur excepteur adipisicing irure culpa consequat commodo et ex id ad.
+
+      
+        154
+      
+      
+
+      
+        155
+      
+      [[Top]](#top)
+
+      
+        156
+      
+      
+
+      
+        157
+      
+      
+        
+      
+      
+        #
+      
+      
+         <a name="Inline"></a>Inline elements
+      
+      
+        
+
+      
+      
+        158
+      
+      
+
+      
+        159
+      
+      
+        Sint ea anim ipsum ad commodo cupidatat do 
+      
+      
+        **
+      
+      
+        exercitation
+      
+      
+        **
+      
+      
+         incididunt et minim ad labore sunt. Minim deserunt labore laboris velit nulla incididunt ipsum nulla. Ullamco ad laborum ea qui et anim in laboris exercitation tempor sit officia laborum reprehenderit culpa velit quis. 
+      
+      
+        **
+      
+      
+        Consequat commodo
+      
+      
+        **
+      
+      
+         reprehenderit duis 
+      
+      
+        [
+      
+      
+        irure
+      
+      
+        ](#!)
+      
+      
+         esse esse exercitation minim enim Lorem dolore duis irure. Nisi Lorem reprehenderit ea amet excepteur dolor excepteur magna labore proident voluptate ipsum. Reprehenderit ex esse deserunt aliqua ea officia mollit Lorem nulla magna enim. Et ad ipsum labore enim ipsum 
+      
+      
+        **
+      
+      
+        cupidatat consequat
+      
+      
+        **
+      
+      
+        . Commodo non ea cupidatat magna deserunt dolore ipsum velit nulla elit veniam nulla eiusmod proident officia.
+
+      
+      
+        160
+      
+      
+
+      
+        161
+      
+      
+        
+      
+      
+        ![
+      
+      
+        Super wide
+      
+      
+        ](http://placekitten.com/1280/800)
+      
+      
+        
+
+      
+      
+        162
+      
+      
+
+      
+        163
+      
+      
+        
+      
+      
+        *
+      
+      
+        Proident sit veniam in est proident officia adipisicing
+      
+      
+        *
+      
+      
+         ea tempor cillum non cillum velit deserunt. Voluptate laborum incididunt sit consectetur Lorem irure incididunt voluptate nostrud. Commodo ut eiusmod tempor cupidatat esse enim minim ex anim consequat. Mollit sint culpa qui laboris quis consectetur ad sint esse. Amet anim anim minim ullamco et duis non irure. Sit tempor adipisicing ea laboris 
+      
+      
+        \`culpa ex duis sint\`
+      
+      
+         anim aute reprehenderit id eu ea. Aute 
+      
+      
+        [
+      
+      
+        excepteur proident
+      
+      
+        ](#!)
+      
+      
+         Lorem minim adipisicing nostrud mollit ad ut voluptate do nulla esse occaecat aliqua sint anim.
+
+      
+      
+        164
+      
+      
+
+      
+        165
+      
+      
+        
+      
+      
+        ![
+      
+      
+        Not so big
+      
+      
+        ](http://placekitten.com/480/400)
+      
+      
+        
+
+      
+      
+        166
+      
+      
+
+      
+        167
+      
+      
+        Incididunt in culpa cupidatat mollit cillum qui proident sit. In cillum aliquip incididunt voluptate magna amet cupidatat cillum pariatur sint aliqua est 
+      
+      
+        _
+      
+      
+        enim 
+      
+      
+        **
+      
+      
+        anim
+      
+      
+        **
+      
+      
+         voluptate
+      
+      
+        _
+      
+      
+        . Magna aliquip proident incididunt id duis pariatur eiusmod incididunt commodo culpa dolore sit. Culpa do nostrud elit ad exercitation anim pariatur non minim nisi 
+      
+      
+        **
+      
+      
+        adipisicing sunt 
+      
+      
+        _
+      
+      
+        officia
+      
+      
+        _
+      
+      
+        **
+      
+      
+        . Do deserunt magna mollit Lorem commodo ipsum do cupidatat mollit enim ut elit veniam ea voluptate.
+
+      
+      
+        168
+      
+      
+
+      
+        169
+      
+      
+        
+      
+      
+        [
+      
+      
+        ![Manny Pacquiao
+      
+      
+        ](https://img.youtube.com/vi/s6bCmZmy9aQ/0.jpg)
+      
+      
+        ](https://youtu.be/s6bCmZmy9aQ)
+
+      
+      
+        170
+      
+      
+
+      
+        171
+      
+      
+        Reprehenderit non eu quis in ad elit esse qui aute id 
+      
+      
+        [
+      
+      
+        incididunt
+      
+      
+        ](#!)
+      
+      
+         dolore cillum. Esse laboris consequat dolor anim exercitation tempor aliqua deserunt velit magna laboris. Culpa culpa minim duis amet mollit do quis amet commodo nulla irure.
+
+      
+      
+        172
+      
+      
+
+    
+  
+
+`; + exports[`Storyshots SyntaxHighlighter Python 1`] = `
{ + it("should return the language as it is", () => { + const java = determineLanguage("java"); + expect(java).toBe("java"); + }); + + it("should lower case the language", () => { + const java = determineLanguage("Java"); + expect(java).toBe("java"); + }); + + it("should return text if language is undefied", () => { + const lang = determineLanguage(); + expect(lang).toBe("text"); + }); + + it("should return text if language is an empty string", () => { + const lang = determineLanguage(""); + expect(lang).toBe("text"); + }); + + it("should use alias go for golang", () => { + const go = determineLanguage("golang"); + expect(go).toBe("go"); + }); +}); diff --git a/scm-ui/ui-components/src/languages.ts b/scm-ui/ui-components/src/languages.ts new file mode 100644 index 0000000000..f895d9d946 --- /dev/null +++ b/scm-ui/ui-components/src/languages.ts @@ -0,0 +1,41 @@ +/* + * MIT License + * + * Copyright (c) 2020-present Cloudogu GmbH and Contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +// this aliases are only to map from spotter detection to prismjs +const languageAliases: { [key: string]: string } = { + golang: "go" +}; + +export const defaultLanguage = "text"; + +export const determineLanguage = (language?: string) => { + if (!language) { + return defaultLanguage; + } + const lang = language.toLowerCase(); + if (languageAliases[lang]) { + return languageAliases[lang]; + } + return lang; +}; diff --git a/scm-ui/ui-components/src/repos/Diff.stories.tsx b/scm-ui/ui-components/src/repos/Diff.stories.tsx index be343c70ae..9649d97a84 100644 --- a/scm-ui/ui-components/src/repos/Diff.stories.tsx +++ b/scm-ui/ui-components/src/repos/Diff.stories.tsx @@ -29,6 +29,7 @@ import parser from "gitdiff-parser"; import simpleDiff from "../__resources__/Diff.simple"; import hunksDiff from "../__resources__/Diff.hunks"; import binaryDiff from "../__resources__/Diff.binary"; +import markdownDiff from "../__resources__/Diff.markdown"; import { DiffEventContext, File, FileControlFactory } from "./DiffTypes"; import Toast from "../toast/Toast"; import { getPath } from "./diffs"; @@ -151,6 +152,10 @@ storiesOf("Diff", module) }); return ; }) + .add("SyntaxHighlighting (Markdown)", () => { + // @ts-ignore + return ; + }) .add("CollapsingWithFunction", () => ( oldPath.endsWith(".java")} /> )) diff --git a/scm-ui/ui-components/src/repos/Tokenize.worker.ts b/scm-ui/ui-components/src/repos/Tokenize.worker.ts index fba9aec455..72f74b39b1 100644 --- a/scm-ui/ui-components/src/repos/Tokenize.worker.ts +++ b/scm-ui/ui-components/src/repos/Tokenize.worker.ts @@ -24,14 +24,28 @@ // @ts-ignore we have no types for react-diff-view import { tokenize } from "react-diff-view"; -import refractor from "./refractorAdapter"; +import createRefractor, { RefractorAdapter } from "./refractorAdapter"; // the WorkerGlobalScope is assigned to self // see https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/self declare const self: Worker; -self.addEventListener("message", ({ data: { id, payload } }) => { +type TokenizeMessage = { + id: string; + language: string; + hunks: any; + payload: any; +}; + +let refractor: RefractorAdapter; + +function initRefractor(theme: { [key: string]: string }) { + refractor = createRefractor(theme); +} + +function runTokenize({ id, payload }: TokenizeMessage) { const { hunks, language } = payload; + const options = { highlight: language !== "text", language: language, @@ -60,4 +74,12 @@ self.addEventListener("message", ({ data: { id, payload } }) => { if (options.highlight) { refractor.loadLanguage(language, createTokenizer(self)); } +} + +self.addEventListener("message", ({ data }) => { + if (data.theme) { + initRefractor(data.theme); + } else { + runTokenize(data); + } }); diff --git a/scm-ui/ui-components/src/repos/TokenizedDiffView.tsx b/scm-ui/ui-components/src/repos/TokenizedDiffView.tsx index dcd1d65616..82242af187 100644 --- a/scm-ui/ui-components/src/repos/TokenizedDiffView.tsx +++ b/scm-ui/ui-components/src/repos/TokenizedDiffView.tsx @@ -26,11 +26,10 @@ import styled from "styled-components"; // @ts-ignore we have no typings for react-diff-view import { Diff, useTokenizeWorker } from "react-diff-view"; import { File } from "./DiffTypes"; +import { determineLanguage } from "../languages"; -// styling for the diff tokens -// this must be aligned with th style, which is used in the SyntaxHighlighter component -// eslint-disable-next-line no-restricted-imports -import "../syntax-highlighting.css"; +// @ts-ignore no types for css modules +import theme from "../syntax-highlighting.module.css"; const DiffView = styled(Diff)` /* align line numbers */ @@ -59,26 +58,11 @@ const DiffView = styled(Diff)` &.unified .diff-widget-content .is-indented-line { padding-left: 6.5rem; } - - /* conflict between prism and bulma number class */ - .number { - align-items: inherit; - background-color: inherit; - border-radius: inherit; - display: initial; - font-size: inherit; - height: inherit; - justify-content: inherit; - margin-right: inherit; - margin-left: 0; - min-width: inherit; - padding: 0; - text-align: inherit; - } `; // WebWorker which creates tokens for syntax highlighting const tokenize = new Worker("./Tokenize.worker.ts", { name: "tokenizer", type: "module" }); +tokenize.postMessage({ theme }); type Props = { file: File; @@ -86,17 +70,10 @@ type Props = { className?: string; }; -const determineLanguage = (file: File) => { - if (file.language) { - return file.language.toLowerCase(); - } - return "text"; -}; - const TokenizedDiffView: FC = ({ file, viewType, className, children }) => { const { tokens } = useTokenizeWorker(tokenize, { hunks: file.hunks, - language: determineLanguage(file) + language: determineLanguage(file.language) }); return ( diff --git a/scm-ui/ui-components/src/repos/annotate/Annotate.stories.tsx b/scm-ui/ui-components/src/repos/annotate/Annotate.stories.tsx index 41345b2744..e69d4c62f0 100644 --- a/scm-ui/ui-components/src/repos/annotate/Annotate.stories.tsx +++ b/scm-ui/ui-components/src/repos/annotate/Annotate.stories.tsx @@ -67,7 +67,7 @@ const commitImplementMain = { }; const source: AnnotatedSource = { - language: "go", + language: "golang", lines: [ { lineNumber: 1, @@ -112,6 +112,52 @@ const source: AnnotatedSource = { ] }; +const markdownSource: AnnotatedSource = { + language: "markdown", + lines: [ + { + lineNumber: 1, + code: "# Title", + ...commitCreateNewApp + }, + { + lineNumber: 2, + code: "", + ...commitCreateNewApp + }, + { + lineNumber: 3, + code: "This is a short Markdown text.", + ...commitFixedMissingImport + }, + { + lineNumber: 4, + code: "", + ...commitFixedMissingImport + }, + { + lineNumber: 5, + code: "With **bold** and __italic__ words.", + ...commitCreateNewApp + }, + { + lineNumber: 6, + code: "", + ...commitImplementMain + }, + { + lineNumber: 7, + code: "> This should be a quote", + ...commitCreateNewApp + }, + { + lineNumber: 8, + code: "", + ...commitCreateNewApp + } + ] +}; + const Robohash: FC = ({ children }) => { const binder = new Binder("robohash"); binder.bind("avatar.factory", (person: Person) => `https://robohash.org/${person.mail}.png`); @@ -124,6 +170,9 @@ storiesOf("Annotate", module) .add("Default", () => ( )) + .add("Markdown", () => ( + + )) .add("With Avatars", () => ( diff --git a/scm-ui/ui-components/src/repos/annotate/Annotate.tsx b/scm-ui/ui-components/src/repos/annotate/Annotate.tsx index 9aeb36dd55..7ed489af25 100644 --- a/scm-ui/ui-components/src/repos/annotate/Annotate.tsx +++ b/scm-ui/ui-components/src/repos/annotate/Annotate.tsx @@ -35,6 +35,7 @@ import { DateInput } from "../../useDateFormatter"; import Popover from "./Popover"; import AnnotateLine from "./AnnotateLine"; import { Action } from "./actions"; +import { determineLanguage } from "../../languages"; type Props = { source: AnnotatedSource; @@ -147,7 +148,7 @@ const Annotate: FC = ({ source, repository, baseDate }) => { {popover} diff --git a/scm-ui/ui-components/src/repos/refractorAdapter.ts b/scm-ui/ui-components/src/repos/refractorAdapter.ts index 0bac53e4d2..6c2f93f1ec 100644 --- a/scm-ui/ui-components/src/repos/refractorAdapter.ts +++ b/scm-ui/ui-components/src/repos/refractorAdapter.ts @@ -24,29 +24,51 @@ import refractor from "refractor/core"; -const isLanguageRegistered = (lang: string) => { - const registeredLanguages = refractor.listLanguages(); - return registeredLanguages.includes(lang); +type RunHookEnv = { + classes: string[]; }; -const loadLanguage = (lang: string, callback: () => void) => { - if (isLanguageRegistered(lang)) { - callback(); - } else { - import( - /* webpackChunkName: "tokenizer-refractor-[request]" */ - `refractor/lang/${lang}` - ).then(loadedLanguage => { - refractor.register(loadedLanguage.default); +export type RefractorAdapter = typeof refractor & { + isLanguageRegistered: (lang: string) => boolean; + loadLanguage: (lang: string, callback: () => void) => void; +}; + +const createAdapter = (theme: { [key: string]: string }): RefractorAdapter => { + const isLanguageRegistered = (lang: string) => { + const registeredLanguages = refractor.listLanguages(); + return registeredLanguages.includes(lang); + }; + + const loadLanguage = (lang: string, callback: () => void) => { + if (isLanguageRegistered(lang)) { callback(); - }); - } + } else { + import( + /* webpackChunkName: "tokenizer-refractor-[request]" */ + `refractor/lang/${lang}` + ).then(loadedLanguage => { + refractor.register(loadedLanguage.default); + callback(); + }); + } + }; + + // @ts-ignore hooks are not in the type definition + const originalRunHook = refractor.hooks.run; + const runHook = (name: string, env: RunHookEnv) => { + originalRunHook.apply(name, env); + if (env.classes) { + env.classes = env.classes.map(className => theme[className] || className); + } + }; + // @ts-ignore hooks are not in the type definition + refractor.hooks.run = runHook; + + return { + isLanguageRegistered, + loadLanguage, + ...refractor + }; }; -const refractorAdapter = { - isLanguageRegistered, - loadLanguage, - ...refractor -}; - -export default refractorAdapter; +export default createAdapter; diff --git a/scm-ui/ui-components/src/syntax-highlighting.css b/scm-ui/ui-components/src/syntax-highlighting.module.css similarity index 94% rename from scm-ui/ui-components/src/syntax-highlighting.css rename to scm-ui/ui-components/src/syntax-highlighting.module.css index 71c052bdcf..4273b26931 100644 --- a/scm-ui/ui-components/src/syntax-highlighting.css +++ b/scm-ui/ui-components/src/syntax-highlighting.module.css @@ -22,140 +22,94 @@ * SOFTWARE. */ -/* Generated with http://k88hudson.github.io/syntax-highlighting-theme-generator/www */ +/** + * IMPORTANT: If this file is changed, please run scritps/build-syntax-highlighting-javascript afterwards + */ +/* Generated with http://k88hudson.github.io/syntax-highlighting-theme-generator/www */ /* http://k88hudson.github.io/react-markdocs */ /** - * @author k88hudson - * - * Based on prism.js default theme for JavaScript, CSS and HTML - * Based on dabblet (http://dabblet.com) - * @author Lea Verou - */ /********************************************************* - * General - */ pre[class*="language-"], code[class*="language-"] { - color: #363636; - font-size: 13px; - text-shadow: none; - font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; - direction: ltr; - text-align: left; - white-space: pre; - word-spacing: normal; - word-break: normal; - line-height: 1.5; - -moz-tab-size: 4; - -o-tab-size: 4; - tab-size: 4; - -webkit-hyphens: none; - -moz-hyphens: none; - -ms-hyphens: none; - hyphens: none; - } pre[class*="language-"]::selection, code[class*="language-"]::selection, -pre[class*="language-"]::mozselection, -code[class*="language-"]::mozselection { - +pre[class*="language-"]::-moz-selection, +code[class*="language-"]::-moz-selection { text-shadow: none; - background: #7fe3cd; - } @media print { pre[class*="language-"], code[class*="language-"] { - text-shadow: none; - } } pre[class*="language-"] { - padding: 1em; - margin: .5em 0; - overflow: auto; - background: #ffffff; - } :not(pre) > code[class*="language-"] { - padding: .1em .3em; - border-radius: .3em; - color: #ff3860; - background: #fbe7eb; - } /********************************************************* - * Tokens - */ .namespace { - opacity: .7; - } .token.comment, .token.prolog, .token.doctype, .token.cdata { - color: #9a9a9a; - } .token.punctuation { - color: #9a9a9a; - } .token.property, @@ -165,9 +119,7 @@ pre[class*="language-"] { .token.constant, .token.symbol, .token.deleted { - color: #2c99c7; - } .token.selector, @@ -176,9 +128,7 @@ pre[class*="language-"] { .token.char, .token.builtin, .token.inserted { - color: #005f9a; - } .token.operator, @@ -186,93 +136,62 @@ pre[class*="language-"] { .token.url, .language-css .token.string, .style .token.string { - color: #686868; } .token.atrule, .token.attr-value, .token.keyword { - color: #00a984; - } .token.function { - color: #ff3860; - } .token.regex, .token.important, .token.variable { - color: #a74eb2; - } .token.important, -.token.bold { - +.token.bold, +.token.title { font-weight: bold; - } .token.italic { - font-style: italic; - } .token.entity { - cursor: help; - } /********************************************************* - * Line highlighting - */ pre[data-line] { - position: relative; - } pre[class*="language-"] > code[class*="language-"] { - position: relative; - z-index: 1; - } .line-highlight { - position: absolute; - left: 0; - right: 0; - padding: inherit 0; - margin-top: 1em; - background: #f5f5f5; - box-shadow: inset 5px 0 0 #99d8f3; - z-index: 0; - pointer-events: none; - line-height: inherit; - white-space: pre; - } diff --git a/scm-ui/ui-components/src/syntax-highlighting.ts b/scm-ui/ui-components/src/syntax-highlighting.ts index 46c319d15e..7b6e928cfd 100644 --- a/scm-ui/ui-components/src/syntax-highlighting.ts +++ b/scm-ui/ui-components/src/syntax-highlighting.ts @@ -23,7 +23,7 @@ */ /* --- DO NOT EDIT --- */ -/* Auto-generated from syntax-highlighting.css */ +/* Auto-generated from syntax-highlighting.module.css */ export default { 'pre[class*="language-"]': { @@ -47,7 +47,7 @@ export default { padding: "1em", margin: ".5em 0", overflow: "auto", - background: "#ffffff", + background: "#ffffff" }, 'code[class*="language-"]': { color: "#363636", @@ -66,137 +66,140 @@ export default { WebkitHyphens: "none", MozHyphens: "none", msHyphens: "none", - hyphens: "none", + hyphens: "none" }, 'pre[class*="language-"]::selection': { textShadow: "none", - background: "#7fe3cd", + background: "#7fe3cd" }, 'code[class*="language-"]::selection': { textShadow: "none", - background: "#7fe3cd", + background: "#7fe3cd" }, - 'pre[class*="language-"]::mozselection': { + 'pre[class*="language-"]::-moz-selection': { textShadow: "none", - background: "#7fe3cd", + background: "#7fe3cd" }, - 'code[class*="language-"]::mozselection': { + 'code[class*="language-"]::-moz-selection': { textShadow: "none", - background: "#7fe3cd", + background: "#7fe3cd" }, ':not(pre) > code[class*="language-"]': { padding: ".1em .3em", borderRadius: ".3em", color: "#ff3860", - background: "#fbe7eb", + background: "#fbe7eb" }, ".namespace": { - Opacity: ".7", + Opacity: ".7" }, comment: { - color: "#9a9a9a", + color: "#9a9a9a" }, prolog: { - color: "#9a9a9a", + color: "#9a9a9a" }, doctype: { - color: "#9a9a9a", + color: "#9a9a9a" }, cdata: { - color: "#9a9a9a", + color: "#9a9a9a" }, punctuation: { - color: "#9a9a9a", + color: "#9a9a9a" }, property: { - color: "#2c99c7", + color: "#2c99c7" }, tag: { - color: "#2c99c7", + color: "#2c99c7" }, boolean: { - color: "#2c99c7", + color: "#2c99c7" }, number: { - color: "#2c99c7", + color: "#2c99c7" }, constant: { - color: "#2c99c7", + color: "#2c99c7" }, symbol: { - color: "#2c99c7", + color: "#2c99c7" }, deleted: { - color: "#2c99c7", + color: "#2c99c7" }, selector: { - color: "#005f9a", + color: "#005f9a" }, "attr-name": { - color: "#005f9a", + color: "#005f9a" }, string: { - color: "#005f9a", + color: "#005f9a" }, char: { - color: "#005f9a", + color: "#005f9a" }, builtin: { - color: "#005f9a", + color: "#005f9a" }, inserted: { - color: "#005f9a", + color: "#005f9a" }, operator: { - color: "#686868", + color: "#686868" }, entity: { color: "#686868", - cursor: "help", + cursor: "help" }, url: { - color: "#686868", + color: "#686868" }, ".language-css .token.string": { - color: "#686868", + color: "#686868" }, ".style .token.string": { - color: "#686868", + color: "#686868" }, atrule: { - color: "#00a984", + color: "#00a984" }, "attr-value": { - color: "#00a984", + color: "#00a984" }, keyword: { - color: "#00a984", + color: "#00a984" }, function: { - color: "#ff3860", + color: "#ff3860" }, regex: { - color: "#a74eb2", + color: "#a74eb2" }, important: { color: "#a74eb2", - fontWeight: "bold", + fontWeight: "bold" }, variable: { - color: "#a74eb2", + color: "#a74eb2" }, bold: { - fontWeight: "bold", + fontWeight: "bold" + }, + title: { + fontWeight: "bold" }, italic: { - fontStyle: "italic", + fontStyle: "italic" }, "pre[data-line]": { - position: "relative", + position: "relative" }, 'pre[class*="language-"] > code[class*="language-"]': { position: "relative", - zIndex: "1", + zIndex: "1" }, ".line-highlight": { position: "absolute", @@ -209,6 +212,6 @@ export default { zIndex: "0", pointerEvents: "none", lineHeight: "inherit", - whiteSpace: "pre", - }, + whiteSpace: "pre" + } }; diff --git a/scm-ui/ui-extensions/package.json b/scm-ui/ui-extensions/package.json index 049d153b07..6f40144ae5 100644 --- a/scm-ui/ui-extensions/package.json +++ b/scm-ui/ui-extensions/package.json @@ -1,6 +1,6 @@ { "name": "@scm-manager/ui-extensions", - "version": "2.8.0-SNAPSHOT", + "version": "2.9.0-SNAPSHOT", "main": "src/index.ts", "license": "MIT", "private": false, diff --git a/scm-ui/ui-plugins/package.json b/scm-ui/ui-plugins/package.json index 6bd7d2a93a..b3e99e0141 100644 --- a/scm-ui/ui-plugins/package.json +++ b/scm-ui/ui-plugins/package.json @@ -1,13 +1,13 @@ { "name": "@scm-manager/ui-plugins", - "version": "2.8.0-SNAPSHOT", + "version": "2.9.0-SNAPSHOT", "license": "MIT", "bin": { "ui-plugins": "./bin/ui-plugins.js" }, "dependencies": { - "@scm-manager/ui-components": "^2.8.0-SNAPSHOT", - "@scm-manager/ui-extensions": "^2.8.0-SNAPSHOT", + "@scm-manager/ui-components": "^2.9.0-SNAPSHOT", + "@scm-manager/ui-extensions": "^2.9.0-SNAPSHOT", "classnames": "^2.2.6", "query-string": "^5.0.1", "react": "^16.10.2", @@ -18,14 +18,14 @@ "styled-components": "^5.1.0" }, "devDependencies": { - "@scm-manager/babel-preset": "^2.8.0-SNAPSHOT", - "@scm-manager/eslint-config": "^2.8.0-SNAPSHOT", - "@scm-manager/jest-preset": "^2.8.0-SNAPSHOT", - "@scm-manager/prettier-config": "^2.8.0-SNAPSHOT", - "@scm-manager/tsconfig": "^2.8.0-SNAPSHOT", - "@scm-manager/ui-scripts": "^2.8.0-SNAPSHOT", - "@scm-manager/ui-tests": "^2.8.0-SNAPSHOT", - "@scm-manager/ui-types": "^2.8.0-SNAPSHOT", + "@scm-manager/babel-preset": "^2.9.0-SNAPSHOT", + "@scm-manager/eslint-config": "^2.9.0-SNAPSHOT", + "@scm-manager/jest-preset": "^2.9.0-SNAPSHOT", + "@scm-manager/prettier-config": "^2.9.0-SNAPSHOT", + "@scm-manager/tsconfig": "^2.9.0-SNAPSHOT", + "@scm-manager/ui-scripts": "^2.9.0-SNAPSHOT", + "@scm-manager/ui-tests": "^2.9.0-SNAPSHOT", + "@scm-manager/ui-types": "^2.9.0-SNAPSHOT", "@types/classnames": "^2.2.9", "@types/enzyme": "^3.10.3", "@types/fetch-mock": "^7.3.1", diff --git a/scm-ui/ui-polyfill/package.json b/scm-ui/ui-polyfill/package.json index bed6f43cb2..05ac12a57d 100644 --- a/scm-ui/ui-polyfill/package.json +++ b/scm-ui/ui-polyfill/package.json @@ -1,6 +1,6 @@ { "name": "@scm-manager/ui-polyfill", - "version": "2.8.0-SNAPSHOT", + "version": "2.9.0-SNAPSHOT", "description": "Polyfills for SCM-Manager UI", "main": "src/index.js", "author": "Sebastian Sdorra ", diff --git a/scm-ui/ui-scripts/package.json b/scm-ui/ui-scripts/package.json index bbd3caac00..d106b6da46 100644 --- a/scm-ui/ui-scripts/package.json +++ b/scm-ui/ui-scripts/package.json @@ -1,6 +1,6 @@ { "name": "@scm-manager/ui-scripts", - "version": "2.8.0-SNAPSHOT", + "version": "2.9.0-SNAPSHOT", "description": "Build scripts for SCM-Manager", "main": "src/index.js", "author": "Sebastian Sdorra ", diff --git a/scm-ui/ui-scripts/src/webpack.config.js b/scm-ui/ui-scripts/src/webpack.config.js index 0bc9f93fd7..bc20d91718 100644 --- a/scm-ui/ui-scripts/src/webpack.config.js +++ b/scm-ui/ui-scripts/src/webpack.config.js @@ -90,8 +90,16 @@ module.exports = [ use: [ // Creates `style` nodes from JS strings "style-loader", - // Translates CSS into CommonJS - "css-loader", + { + loader: "css-loader", + options: { + // Run `postcss-loader` on each CSS `@import`, do not forget that `sass-loader` compile non CSS `@import`'s into a single file + // If you need run `sass-loader` and `postcss-loader` on each CSS `@import` please set it to `2` + importLoaders: 1, + // Automatically enable css modules for files satisfying `/\.module\.\w+$/i` RegExp. + modules: { auto: true } + } + }, // Compiles Sass to CSS "sass-loader" ] diff --git a/scm-ui/ui-styles/package.json b/scm-ui/ui-styles/package.json index 0069cefc73..bb51dca134 100644 --- a/scm-ui/ui-styles/package.json +++ b/scm-ui/ui-styles/package.json @@ -1,6 +1,6 @@ { "name": "@scm-manager/ui-styles", - "version": "2.8.0-SNAPSHOT", + "version": "2.9.0-SNAPSHOT", "description": "Styles for SCM-Manager", "main": "src/scm.scss", "license": "MIT", diff --git a/scm-ui/ui-tests/package.json b/scm-ui/ui-tests/package.json index 0c8f3d3aae..246def1166 100644 --- a/scm-ui/ui-tests/package.json +++ b/scm-ui/ui-tests/package.json @@ -1,6 +1,6 @@ { "name": "@scm-manager/ui-tests", - "version": "2.8.0-SNAPSHOT", + "version": "2.9.0-SNAPSHOT", "description": "UI-Tests helpers", "author": "Sebastian Sdorra ", "license": "MIT", diff --git a/scm-ui/ui-types/package.json b/scm-ui/ui-types/package.json index 9ffb7f4251..267db9a4f1 100644 --- a/scm-ui/ui-types/package.json +++ b/scm-ui/ui-types/package.json @@ -1,6 +1,6 @@ { "name": "@scm-manager/ui-types", - "version": "2.8.0-SNAPSHOT", + "version": "2.9.0-SNAPSHOT", "description": "Flow types for SCM-Manager related Objects", "main": "src/index.ts", "files": [ diff --git a/scm-ui/ui-webapp/package.json b/scm-ui/ui-webapp/package.json index 1d5a332dc6..06f962abfa 100644 --- a/scm-ui/ui-webapp/package.json +++ b/scm-ui/ui-webapp/package.json @@ -1,10 +1,10 @@ { "name": "@scm-manager/ui-webapp", - "version": "2.8.0-SNAPSHOT", + "version": "2.9.0-SNAPSHOT", "private": true, "dependencies": { - "@scm-manager/ui-components": "^2.8.0-SNAPSHOT", - "@scm-manager/ui-extensions": "^2.8.0-SNAPSHOT", + "@scm-manager/ui-components": "^2.9.0-SNAPSHOT", + "@scm-manager/ui-extensions": "^2.9.0-SNAPSHOT", "classnames": "^2.2.5", "history": "^4.10.1", "i18next": "^19.6.0", @@ -29,7 +29,7 @@ "test": "jest" }, "devDependencies": { - "@scm-manager/ui-tests": "^2.8.0-SNAPSHOT", + "@scm-manager/ui-tests": "^2.9.0-SNAPSHOT", "@types/classnames": "^2.2.9", "@types/enzyme": "^3.10.3", "@types/fetch-mock": "^7.3.1", diff --git a/scm-webapp/pom.xml b/scm-webapp/pom.xml index f30c2cdb99..ce26d72a9d 100644 --- a/scm-webapp/pom.xml +++ b/scm-webapp/pom.xml @@ -32,13 +32,13 @@ sonia.scm scm - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT sonia.scm scm-webapp war - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT scm-webapp @@ -48,7 +48,7 @@ sonia.scm scm-annotation-processor - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT provided @@ -73,13 +73,13 @@ sonia.scm scm-core - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT sonia.scm scm-dao-xml - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT @@ -343,7 +343,7 @@ sonia.scm scm-test - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT test @@ -405,7 +405,7 @@ sonia.scm.plugins scm-git-plugin - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT tests test @@ -413,14 +413,14 @@ sonia.scm.plugins scm-git-plugin - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT test sonia.scm.plugins scm-hg-plugin - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT tests test @@ -428,14 +428,14 @@ sonia.scm.plugins scm-hg-plugin - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT test sonia.scm.plugins scm-svn-plugin - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT tests test @@ -443,7 +443,7 @@ sonia.scm.plugins scm-svn-plugin - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT test @@ -729,7 +729,7 @@ sonia.scm scm-ui - 2.8.0-SNAPSHOT + 2.9.0-SNAPSHOT war diff --git a/scm-webapp/src/main/java/sonia/scm/security/ApiKeyRealm.java b/scm-webapp/src/main/java/sonia/scm/security/ApiKeyRealm.java index a447388d97..859df41d3e 100644 --- a/scm-webapp/src/main/java/sonia/scm/security/ApiKeyRealm.java +++ b/scm-webapp/src/main/java/sonia/scm/security/ApiKeyRealm.java @@ -46,6 +46,8 @@ import static com.google.common.base.Preconditions.checkArgument; @Extension public class ApiKeyRealm extends AuthenticatingRealm { + public static final String NAME = "ApiTokenRealm"; + private static final Logger LOG = LoggerFactory.getLogger(ApiKeyRealm.class); private final ApiKeyService apiKeyService; @@ -55,7 +57,7 @@ public class ApiKeyRealm extends AuthenticatingRealm { @Inject public ApiKeyRealm(ApiKeyService apiKeyService, DAORealmHelperFactory helperFactory, RepositoryRoleManager repositoryRoleManager) { this.apiKeyService = apiKeyService; - this.helper = helperFactory.create("ApiTokenRealm"); + this.helper = helperFactory.create(NAME); this.repositoryRoleManager = repositoryRoleManager; setAuthenticationTokenClass(BearerToken.class); setCredentialsMatcher(new AllowAllCredentialsMatcher()); diff --git a/scm-webapp/src/main/java/sonia/scm/security/JwtAccessTokenBuilder.java b/scm-webapp/src/main/java/sonia/scm/security/JwtAccessTokenBuilder.java index ab5851538f..5221142fc0 100644 --- a/scm-webapp/src/main/java/sonia/scm/security/JwtAccessTokenBuilder.java +++ b/scm-webapp/src/main/java/sonia/scm/security/JwtAccessTokenBuilder.java @@ -21,7 +21,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - + package sonia.scm.security; import com.google.common.base.Preconditions; @@ -31,6 +31,7 @@ import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import org.apache.shiro.SecurityUtils; +import org.apache.shiro.authz.AuthorizationException; import org.apache.shiro.subject.Subject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -154,6 +155,9 @@ public final class JwtAccessTokenBuilder implements AccessTokenBuilder { @Override public JwtAccessToken build() { + if (SecurityUtils.getSubject().getPrincipals().getRealmNames().contains(ApiKeyRealm.NAME)) { + throw new AuthorizationException("Cannot create access token for api keys"); + } String id = keyGenerator.createKey(); String sub = getSubject(); diff --git a/scm-webapp/src/test/java/sonia/scm/security/JwtAccessTokenBuilderTest.java b/scm-webapp/src/test/java/sonia/scm/security/JwtAccessTokenBuilderTest.java index 9f41839640..4e25b8e869 100644 --- a/scm-webapp/src/test/java/sonia/scm/security/JwtAccessTokenBuilderTest.java +++ b/scm-webapp/src/test/java/sonia/scm/security/JwtAccessTokenBuilderTest.java @@ -21,122 +21,98 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - + package sonia.scm.security; -import com.github.sdorra.shiro.ShiroRule; -import com.github.sdorra.shiro.SubjectAware; import com.google.common.collect.Sets; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; +import org.apache.shiro.authz.AuthorizationException; +import org.apache.shiro.subject.PrincipalCollection; +import org.apache.shiro.subject.Subject; import org.apache.shiro.util.ThreadContext; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.junit.jupiter.MockitoExtension; import java.util.Set; import java.util.concurrent.TimeUnit; -import static org.hamcrest.Matchers.isEmptyOrNullString; -import static org.hamcrest.Matchers.not; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; +import static java.util.Collections.singleton; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertThrows; import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.lenient; import static sonia.scm.security.SecureKeyTestUtil.createSecureKey; /** * Unit test for {@link JwtAccessTokenBuilder}. - * + * * @author Sebastian Sdorra */ -@RunWith(MockitoJUnitRunner.class) -@SubjectAware( - configuration = "classpath:sonia/scm/shiro-001.ini", - username = "trillian", - password = "secret" -) -public class JwtAccessTokenBuilderTest { - - { - ThreadContext.unbindSubject(); - } +@ExtendWith(MockitoExtension.class) +class JwtAccessTokenBuilderTest { @Mock private KeyGenerator keyGenerator; - + @Mock private SecureKeyResolver secureKeyResolver; - + private Set enrichers; - + private JwtAccessTokenBuilderFactory factory; - - @Rule - public ShiroRule shiro = new ShiroRule(); - + + @Mock + private Subject subject; + @Mock + private PrincipalCollection principalCollection; + + @BeforeEach + void bindSubject() { + lenient().when(subject.getPrincipal()).thenReturn("trillian"); + lenient().when(subject.getPrincipals()).thenReturn(principalCollection); + ThreadContext.bind(subject); + } + + @AfterEach + void unbindSubject() { + ThreadContext.unbindSubject(); + } + /** * Prepare mocks and set up object under test. */ - @Before - public void setUpObjectUnderTest() { - when(keyGenerator.createKey()).thenReturn("42"); - when(secureKeyResolver.getSecureKey(anyString())).thenReturn(createSecureKey()); + @BeforeEach + void setUpObjectUnderTest() { + lenient().when(keyGenerator.createKey()).thenReturn("42"); + lenient().when(secureKeyResolver.getSecureKey(anyString())).thenReturn(createSecureKey()); enrichers = Sets.newHashSet(); factory = new JwtAccessTokenBuilderFactory(keyGenerator, secureKeyResolver, enrichers); } - - /** - * Tests {@link JwtAccessTokenBuilder#build()} with subject from shiro context. - */ - @Test - public void testBuildWithoutSubject() { - JwtAccessToken token = factory.create().build(); - assertEquals("trillian", token.getSubject()); - } - - /** - * Tests {@link JwtAccessTokenBuilder#build()} with explicit subject. - */ - @Test - public void testBuildWithSubject() { - JwtAccessToken token = factory.create().subject("dent").build(); - assertEquals("dent", token.getSubject()); - } - - /** - * Tests {@link JwtAccessTokenBuilder#build()} with enricher. - */ - @Test - public void testBuildWithEnricher() { - enrichers.add((b) -> b.custom("c", "d")); - JwtAccessToken token = factory.create().subject("dent").build(); - assertEquals("d", token.getCustom("c").get()); - } - + /** * Tests {@link JwtAccessTokenBuilder#build()}. */ @Test - public void testBuild(){ + void testBuild() { JwtAccessToken token = factory.create().subject("dent") .issuer("https://www.scm-manager.org") .expiresIn(5, TimeUnit.SECONDS) .custom("a", "b") .scope(Scope.valueOf("repo:*")) .build(); - + // assert claims assertClaims(token); - + // reparse and assert again String compact = token.compact(); - assertThat(compact, not(isEmptyOrNullString())); + assertThat(compact).isNotEmpty(); Claims claims = Jwts.parser() .setSigningKey(secureKeyResolver.getSecureKey("dent").getBytes()) .parseClaimsJws(compact) @@ -144,15 +120,67 @@ public class JwtAccessTokenBuilderTest { assertClaims(new JwtAccessToken(claims, compact)); } - private void assertClaims(JwtAccessToken token){ - assertThat(token.getId(), not(isEmptyOrNullString())); - assertNotNull( token.getIssuedAt() ); - assertNotNull( token.getExpiration()); - assertTrue(token.getExpiration().getTime() > token.getIssuedAt().getTime()); - assertEquals("dent", token.getSubject()); - assertTrue(token.getIssuer().isPresent()); - assertEquals(token.getIssuer().get(), "https://www.scm-manager.org"); - assertEquals("b", token.getCustom("a").get()); - assertEquals("[\"repo:*\"]", token.getScope().toString()); + private void assertClaims(JwtAccessToken token) { + assertThat(token.getId()).isNotEmpty(); + assertThat(token.getIssuedAt()).isNotNull(); + assertThat(token.getExpiration()).isNotNull(); + assertThat(token.getExpiration().getTime() > token.getIssuedAt().getTime()).isTrue(); + assertThat(token.getSubject()).isEqualTo("dent"); + assertThat(token.getIssuer()).isNotEmpty(); + assertThat(token.getIssuer()).get().isEqualTo("https://www.scm-manager.org"); + assertThat(token.getCustom("a")).get().isEqualTo("b"); + assertThat(token.getScope()).hasToString("[\"repo:*\"]"); + } + + @Nested + class FromApiKeyRealm { + + @BeforeEach + void mockApiKeyRealm() { + lenient().when(principalCollection.getRealmNames()).thenReturn(singleton("ApiTokenRealm")); + } + + @Test + void testRejectedRequest() { + JwtAccessTokenBuilder builder = factory.create().subject("dent"); + assertThrows(AuthorizationException.class, builder::build); + } + } + + @Nested + class FromDefaultRealm { + + @BeforeEach + void mockDefaultRealm() { + lenient().when(principalCollection.getRealmNames()).thenReturn(singleton("DefaultRealm")); + } + + /** + * Tests {@link JwtAccessTokenBuilder#build()} with subject from shiro context. + */ + @Test + void testBuildWithoutSubject() { + JwtAccessToken token = factory.create().build(); + assertThat(token.getSubject()).isEqualTo("trillian"); + } + + /** + * Tests {@link JwtAccessTokenBuilder#build()} with explicit subject. + */ + @Test + void testBuildWithSubject() { + JwtAccessToken token = factory.create().subject("dent").build(); + assertThat(token.getSubject()).isEqualTo("dent"); + } + + /** + * Tests {@link JwtAccessTokenBuilder#build()} with enricher. + */ + @Test + void testBuildWithEnricher() { + enrichers.add((b) -> b.custom("c", "d")); + JwtAccessToken token = factory.create().subject("dent").build(); + assertThat(token.getCustom("c")).get().isEqualTo("d"); + } } } diff --git a/yarn.lock b/yarn.lock index 087b9f224d..92d3df06cc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3861,10 +3861,10 @@ dependencies: redux "^4.0.0" -"@types/refractor@^2.8.0": - version "2.8.0" - resolved "https://registry.yarnpkg.com/@types/refractor/-/refractor-2.8.0.tgz#2e17b69f27e89c1ea076f49b599abe3567c54e01" - integrity sha512-l3wSB96RFZnvB8bnbF8UmYsDD1MQl+u7jtYq+DgI/vo3RD5pdbK3OitGEvMO3DNJhTYmCEhXLVWyyWTddzwNzQ== +"@types/refractor@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/refractor/-/refractor-3.0.0.tgz#c535cfad1c54cf377ae2984f6cf6e9627a36ea66" + integrity sha512-jkCqkTpxMXXfN03Xpzj+mBMxo9IxG616SV2U42iwHkBGq/f8RrX3DCzLayIqUV+MAIBCUvl5xPnjqpUtZRnMqA== dependencies: "@types/prismjs" "*" @@ -4775,6 +4775,11 @@ babel-code-frame@^6.22.0: esutils "^2.0.2" js-tokens "^3.0.2" +babel-core@7.0.0-bridge.0: + version "7.0.0-bridge.0" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece" + integrity sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg== + babel-eslint@^10.0.3: version "10.1.0" resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" @@ -8994,10 +8999,9 @@ gitconfiglocal@^1.0.0: dependencies: ini "^1.3.2" -gitdiff-parser@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/gitdiff-parser/-/gitdiff-parser-0.1.2.tgz#26a256e05e9c2d5016b512a96c1dacb40862b92a" - integrity sha512-glDM6E1AwLYYTOPyI0CqamNEUSuwwAkmwULWpE2sHMpMZNzGJwErt7+eV+yIZcsbDza0pVSlwlBHFWbTf2Wu7A== +gitdiff-parser@^0.1.2, "gitdiff-parser@https://github.com/scm-manager/gitdiff-parser#420d6cfa17a6a8f9bf1a517a2c629dcb332dbe13": + version "0.2.2" + resolved "https://github.com/scm-manager/gitdiff-parser#420d6cfa17a6a8f9bf1a517a2c629dcb332dbe13" glob-base@^0.3.0: version "0.3.0" @@ -9318,16 +9322,6 @@ hast-util-parse-selector@^2.0.0: resolved "https://registry.yarnpkg.com/hast-util-parse-selector/-/hast-util-parse-selector-2.2.4.tgz#60c99d0b519e12ab4ed32e58f150ec3f61ed1974" integrity sha512-gW3sxfynIvZApL4L07wryYF4+C9VvH3AUi7LAnVXV4MneGEgwOByXvFo18BgmTWnm7oHAe874jKbIB1YhHSIzA== -hastscript@^5.0.0: - version "5.1.2" - resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-5.1.2.tgz#bde2c2e56d04c62dd24e8c5df288d050a355fb8a" - integrity sha512-WlztFuK+Lrvi3EggsqOkQ52rKbxkXL3RwB6t5lwoa8QLMemoWfBuL43eDrwOamJyR7uKQKdmKYaBH1NZBiIRrQ== - dependencies: - comma-separated-tokens "^1.0.0" - hast-util-parse-selector "^2.0.0" - property-information "^5.0.0" - space-separated-tokens "^1.0.0" - hastscript@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-6.0.0.tgz#e8768d7eac56c3fdeac8a92830d58e811e5bf640" @@ -13445,7 +13439,7 @@ parse-asn1@^5.0.0, parse-asn1@^5.1.5: pbkdf2 "^3.0.3" safe-buffer "^5.1.1" -parse-entities@^1.1.0, parse-entities@^1.1.2: +parse-entities@^1.1.0: version "1.2.2" resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-1.2.2.tgz#c31bf0f653b6661354f8973559cb86dd1d5edf50" integrity sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg== @@ -14234,20 +14228,13 @@ prism-themes@^1.4.0: resolved "https://registry.yarnpkg.com/prism-themes/-/prism-themes-1.4.1.tgz#2e1b5877792e3d19fa365b1f0462335ae348aceb" integrity sha512-Sxk5+Wr63WxMq/sU/JYxnq5WbB0CTjv9dscGGMF91iBo3rHEJFfhZVxEsepEOMRbOQ9Exc+xySuAEaX4ATxtIQ== -prismjs@^1.21.0, prismjs@^1.8.4, prismjs@~1.22.0: +prismjs@1.22.0, prismjs@^1.21.0, prismjs@^1.8.4, prismjs@~1.22.0: version "1.22.0" resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.22.0.tgz#73c3400afc58a823dd7eed023f8e1ce9fd8977fa" integrity sha512-lLJ/Wt9yy0AiSYBf212kK3mM5L8ycwlyTlSxHBAneXLR0nzFMlZ5y7riFPF3E33zXOF2IH95xdY5jIyZbM9z/w== optionalDependencies: clipboard "^2.0.0" -prismjs@~1.17.0: - version "1.17.1" - resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.17.1.tgz#e669fcbd4cdd873c35102881c33b14d0d68519be" - integrity sha512-PrEDJAFdUGbOP6xK/UsfkC5ghJsPJviKgnQOoxaDbBjwc8op68Quupwt1DeAFoG8GImPhiKXAvvsH7wDSLsu1Q== - optionalDependencies: - clipboard "^2.0.0" - private@~0.1.5: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" @@ -15227,16 +15214,7 @@ reflect.ownkeys@^0.2.0: resolved "https://registry.yarnpkg.com/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz#749aceec7f3fdf8b63f927a04809e90c5c0b3460" integrity sha1-dJrO7H8/34tj+SegSAnpDFwLNGA= -refractor@^2.4.1: - version "2.10.1" - resolved "https://registry.yarnpkg.com/refractor/-/refractor-2.10.1.tgz#166c32f114ed16fd96190ad21d5193d3afc7d34e" - integrity sha512-Xh9o7hQiQlDbxo5/XkOX6H+x/q8rmlmZKr97Ie1Q8ZM32IRRd3B/UxuA/yXDW79DBSXGWxm2yRTbcTVmAciJRw== - dependencies: - hastscript "^5.0.0" - parse-entities "^1.1.2" - prismjs "~1.17.0" - -refractor@^3.0.0, refractor@^3.1.0: +refractor@3.2.0, refractor@^2.4.1, refractor@^3.0.0, refractor@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/refractor/-/refractor-3.2.0.tgz#bc46f7cfbb6adbf45cd304e8e299b7fa854804e0" integrity sha512-hSo+EyMIZTLBvNNgIU5lW4yjCzNYMZ4dcEhBq/3nReGfqzd2JfVhdlPDfU9rEsgcAyWx+OimIIUoL4ZU7NtYHQ==