diff --git a/.drone.yml b/.drone.yml index 1181b809b0da..0e8e8abcbfd5 100644 --- a/.drone.yml +++ b/.drone.yml @@ -9,8 +9,6 @@ platform: trigger: event: - - push - - tag - pull_request paths: exclude: @@ -28,7 +26,7 @@ steps: - make deps-frontend - name: deps-backend - image: golang:1.20 + image: gitea/test_env:linux-1.20-amd64 pull: always commands: - make deps-backend @@ -44,7 +42,7 @@ steps: depends_on: [deps-frontend] - name: lint-backend - image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env + image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env pull: always commands: - make lint-backend @@ -58,7 +56,7 @@ steps: path: /go - name: lint-backend-windows - image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env + image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env commands: - make golangci-lint-windows vet environment: @@ -73,7 +71,7 @@ steps: path: /go - name: lint-backend-gogit - image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env + image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env commands: - make lint-backend environment: @@ -92,7 +90,7 @@ steps: depends_on: [deps-frontend] - name: checks-backend - image: golang:1.20 + image: gitea/test_env:linux-1.20-amd64 commands: - make --always-make checks-backend # ensure the 'go-licenses' make target runs depends_on: [deps-backend] @@ -113,7 +111,7 @@ steps: depends_on: [deps-frontend] - name: build-backend-no-gcc - image: golang:1.19 # this step is kept as the lowest version of golang that we support + image: gitea/test_env:linux-1.19-amd64 # this step is kept as the lowest version of golang that we support pull: always environment: GOPROXY: https://goproxy.io @@ -125,7 +123,7 @@ steps: path: /go - name: build-backend-arm64 - image: golang:1.20 + image: gitea/test_env:linux-1.20-amd64 environment: GOPROXY: https://goproxy.io GOOS: linux @@ -140,7 +138,7 @@ steps: path: /go - name: build-backend-windows - image: golang:1.20 + image: gitea/test_env:linux-1.20-amd64 environment: GOPROXY: https://goproxy.io GOOS: windows @@ -154,7 +152,7 @@ steps: path: /go - name: build-backend-386 - image: golang:1.20 + image: gitea/test_env:linux-1.20-amd64 environment: GOPROXY: https://goproxy.io GOOS: linux @@ -180,8 +178,6 @@ depends_on: trigger: event: - - push - - tag - pull_request paths: exclude: @@ -217,7 +213,6 @@ steps: image: docker:git pull: always commands: - - git config --global --add safe.directory /drone/src - git fetch --tags --force when: event: @@ -225,7 +220,7 @@ steps: - pull_request - name: deps-backend - image: golang:1.20 + image: gitea/test_env:linux-1.20-amd64 pull: always commands: - make deps-backend @@ -234,13 +229,13 @@ steps: path: /go - name: prepare-test-env - image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env + image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env pull: always commands: - ./build/test-env-prepare.sh - name: build - image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env + image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env user: gitea commands: - ./build/test-env-check.sh @@ -255,7 +250,7 @@ steps: path: /go - name: test-pgsql - image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env + image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env user: gitea commands: - timeout -s ABRT 50m make test-pgsql-migration test-pgsql @@ -285,8 +280,6 @@ depends_on: trigger: event: - - push - - tag - pull_request paths: exclude: @@ -319,7 +312,6 @@ steps: image: docker:git pull: always commands: - - git config --global --add safe.directory /drone/src - git fetch --tags --force when: event: @@ -327,7 +319,7 @@ steps: - pull_request - name: deps-backend - image: golang:1.20 + image: gitea/test_env:linux-1.20-amd64 pull: always commands: - make deps-backend @@ -336,13 +328,13 @@ steps: path: /go - name: prepare-test-env - image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env + image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env pull: always commands: - ./build/test-env-prepare.sh - name: build - image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env + image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env user: gitea commands: - ./build/test-env-check.sh @@ -357,7 +349,7 @@ steps: path: /go - name: unit-test - image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env + image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env user: gitea commands: - make unit-test-coverage test-check @@ -373,7 +365,7 @@ steps: path: /go - name: unit-test-gogit - image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env + image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env user: gitea commands: - make unit-test-coverage test-check @@ -389,7 +381,7 @@ steps: path: /go - name: test-mysql - image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env + image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env user: gitea commands: - make test-mysql-migration integration-test-coverage @@ -405,7 +397,7 @@ steps: path: /go - name: generate-coverage - image: golang:1.20 + image: gitea/test_env:linux-1.20-amd64 commands: - make coverage environment: @@ -449,8 +441,6 @@ depends_on: trigger: event: - - push - - tag - pull_request paths: exclude: @@ -473,7 +463,6 @@ steps: image: docker:git pull: always commands: - - git config --global --add safe.directory /drone/src - git fetch --tags --force when: event: @@ -481,7 +470,7 @@ steps: - pull_request - name: deps-backend - image: golang:1.20 + image: gitea/test_env:linux-1.20-amd64 pull: always commands: - make deps-backend @@ -490,13 +479,13 @@ steps: path: /go - name: prepare-test-env - image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env + image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env pull: always commands: - ./build/test-env-prepare.sh - name: build - image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env + image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env user: gitea commands: - ./build/test-env-check.sh @@ -511,7 +500,7 @@ steps: path: /go - name: test-mysql8 - image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env + image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env user: gitea commands: - timeout -s ABRT 50m make test-mysql8-migration test-mysql8 @@ -538,8 +527,6 @@ depends_on: trigger: event: - - push - - tag - pull_request paths: exclude: @@ -563,7 +550,6 @@ steps: image: docker:git pull: always commands: - - git config --global --add safe.directory /drone/src - git fetch --tags --force when: event: @@ -571,7 +557,7 @@ steps: - pull_request - name: deps-backend - image: golang:1.20 + image: gitea/test_env:linux-1.20-amd64 pull: always commands: - make deps-backend @@ -580,13 +566,13 @@ steps: path: /go - name: prepare-test-env - image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env + image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env pull: always commands: - ./build/test-env-prepare.sh - name: build - image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env + image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env user: gitea commands: - ./build/test-env-check.sh @@ -601,7 +587,7 @@ steps: path: /go - name: test-mssql - image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env + image: gitea/test_env:linux-1.20-amd64 # https://gitea.com/gitea/test-env user: gitea commands: - make test-mssql-migration test-mssql @@ -627,8 +613,6 @@ depends_on: trigger: event: - - push - - tag - pull_request paths: exclude: @@ -643,7 +627,6 @@ steps: image: docker:git pull: always commands: - - git config --global --add safe.directory /drone/src - git fetch --tags --force when: event: @@ -651,7 +634,7 @@ steps: - pull_request - name: deps-backend - image: golang:1.20 + image: gitea/test_env:linux-1.20-arm64 pull: always commands: - make deps-backend @@ -660,13 +643,13 @@ steps: path: /go - name: prepare-test-env - image: gitea/test_env:linux-arm64 # https://gitea.com/gitea/test-env + image: gitea/test_env:linux-1.20-arm64 # https://gitea.com/gitea/test-env pull: always commands: - ./build/test-env-prepare.sh - name: build - image: gitea/test_env:linux-arm64 # https://gitea.com/gitea/test-env + image: gitea/test_env:linux-1.20-arm64 # https://gitea.com/gitea/test-env user: gitea commands: - ./build/test-env-check.sh @@ -681,7 +664,7 @@ steps: path: /go - name: test-sqlite - image: gitea/test_env:linux-arm64 # https://gitea.com/gitea/test-env + image: gitea/test_env:linux-1.20-arm64 # https://gitea.com/gitea/test-env user: gitea commands: - timeout -s ABRT 50m make test-sqlite-migration test-sqlite @@ -733,7 +716,7 @@ steps: depends_on: [deps-frontend] - name: deps-backend - image: golang:1.18 + image: gitea/test_env:linux-1.20-amd64 pull: always commands: - make deps-backend @@ -842,7 +825,7 @@ trigger: steps: - name: download - image: golang:1.20 + image: gitea/test_env:linux-1.20-amd64 pull: always commands: - timeout -s ABRT 40m make generate-license generate-gitignore @@ -902,7 +885,6 @@ steps: image: docker:git pull: always commands: - - git config --global --add safe.directory /drone/src - git fetch --tags --force - name: deps-frontend @@ -912,7 +894,7 @@ steps: - make deps-frontend - name: deps-backend - image: golang:1.20 + image: gitea/test_env:linux-1.20-amd64 pull: always commands: - make deps-backend @@ -1038,7 +1020,6 @@ steps: image: docker:git pull: always commands: - - git config --global --add safe.directory /drone/src - git fetch --tags --force - name: deps-frontend @@ -1048,7 +1029,7 @@ steps: - make deps-frontend - name: deps-backend - image: golang:1.20 + image: gitea/test_env:linux-1.20-amd64 pull: always commands: - make deps-backend @@ -1148,7 +1129,7 @@ trigger: steps: - name: build-docs - image: golang:1.20 + image: gitea/test_env:linux-1.20-amd64 commands: - cd docs - make trans-copy clean build @@ -1202,7 +1183,6 @@ steps: image: docker:git pull: always commands: - - git config --global --add safe.directory /drone/src - git fetch --tags --force - name: publish @@ -1280,7 +1260,6 @@ steps: image: docker:git pull: always commands: - - git config --global --add safe.directory /drone/src - git fetch --tags --force - name: publish @@ -1353,7 +1332,6 @@ steps: image: docker:git pull: always commands: - - git config --global --add safe.directory /drone/src - git fetch --tags --force - name: publish @@ -1427,7 +1405,6 @@ steps: image: docker:git pull: always commands: - - git config --global --add safe.directory /drone/src - git fetch --tags --force - name: publish @@ -1477,7 +1454,7 @@ steps: --- kind: pipeline type: docker -name: docker-linux-amd64-dry-run +name: docker-linux-arm64-dry-run platform: os: linux @@ -1487,8 +1464,8 @@ depends_on: - compliance trigger: - ref: - - "refs/pull/**" + event: + - pull_request paths: exclude: - docs/** @@ -1545,7 +1522,6 @@ steps: image: docker:git pull: always commands: - - git config --global --add safe.directory /drone/src - git fetch --tags --force - name: publish @@ -1623,7 +1599,6 @@ steps: image: docker:git pull: always commands: - - git config --global --add safe.directory /drone/src - git fetch --tags --force - name: publish @@ -1699,7 +1674,6 @@ steps: image: docker:git pull: always commands: - - git config --global --add safe.directory /drone/src - git fetch --tags --force - name: publish @@ -1773,7 +1747,6 @@ steps: image: docker:git pull: always commands: - - git config --global --add safe.directory /drone/src - git fetch --tags --force - name: publish diff --git a/.stylelintrc.yaml b/.stylelintrc.yaml index c488d0677f18..62660fcf9440 100644 --- a/.stylelintrc.yaml +++ b/.stylelintrc.yaml @@ -5,8 +5,6 @@ ignoreFiles: - "**/*.go" overrides: - - files: ["**/*.less"] - customSyntax: postcss-less - files: ["**/chroma/*", "**/codemirror/*", "**/standalone/*", "**/console/*"] rules: scale-unlimited/declaration-strict-value: null diff --git a/Makefile b/Makefile index d770ed453f4f..0d49bdfdfb27 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,7 @@ AIR_PACKAGE ?= github.com/cosmtrek/air@v1.40.4 EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/cmd/editorconfig-checker@2.6.0 ERRCHECK_PACKAGE ?= github.com/kisielk/errcheck@v1.6.2 GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.4.0 -GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.51.0 +GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.51.2 GXZ_PAGAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.10 MISSPELL_PACKAGE ?= github.com/client9/misspell/cmd/misspell@v0.3.4 SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.30.4 @@ -105,7 +105,7 @@ GO_TEST_PACKAGES ?= $(filter-out $(shell $(GO) list code.gitea.io/gitea/models/m FOMANTIC_WORK_DIR := web_src/fomantic -WEBPACK_SOURCES := $(shell find web_src/js web_src/less -type f) +WEBPACK_SOURCES := $(shell find web_src/js web_src/css -type f) WEBPACK_CONFIGS := webpack.config.js WEBPACK_DEST := public/js/index.js public/css/index.css WEBPACK_DEST_ENTRIES := public/js public/css public/fonts public/img/webpack public/serviceworker.js @@ -131,7 +131,7 @@ TEST_TAGS ?= sqlite sqlite_unlock_notify TAR_EXCLUDES := .git data indexers queues log node_modules $(EXECUTABLE) $(FOMANTIC_WORK_DIR)/node_modules $(DIST) $(MAKE_EVIDENCE_DIR) $(AIR_TMP_DIR) $(GO_LICENSE_TMP_DIR) GO_DIRS := cmd tests models modules routers build services tools -WEB_DIRS := web_src/js web_src/less +WEB_DIRS := web_src/js web_src/css GO_SOURCES := $(wildcard *.go) GO_SOURCES += $(shell find $(GO_DIRS) -type f -name "*.go" -not -path modules/options/bindata.go -not -path modules/public/bindata.go -not -path modules/templates/bindata.go) @@ -342,7 +342,7 @@ lint: lint-frontend lint-backend .PHONY: lint-frontend lint-frontend: node_modules npx eslint --color --max-warnings=0 --ext js,vue web_src/js build *.config.js docs/assets/js tests/e2e - npx stylelint --color --max-warnings=0 web_src/less + npx stylelint --color --max-warnings=0 web_src/css npx spectral lint -q -F hint $(SWAGGER_SPEC) npx markdownlint docs *.md diff --git a/cmd/dump.go b/cmd/dump.go index c802849f8e50..00d279b99187 100644 --- a/cmd/dump.go +++ b/cmd/dump.go @@ -250,7 +250,7 @@ func runDump(ctx *cli.Context) error { if ctx.IsSet("skip-lfs-data") && ctx.Bool("skip-lfs-data") { log.Info("Skip dumping LFS data") - } else if err := storage.LFS.IterateObjects(func(objPath string, object storage.Object) error { + } else if err := storage.LFS.IterateObjects("", func(objPath string, object storage.Object) error { info, err := object.Stat() if err != nil { return err @@ -351,7 +351,7 @@ func runDump(ctx *cli.Context) error { if ctx.IsSet("skip-attachment-data") && ctx.Bool("skip-attachment-data") { log.Info("Skip dumping attachment data") - } else if err := storage.Attachments.IterateObjects(func(objPath string, object storage.Object) error { + } else if err := storage.Attachments.IterateObjects("", func(objPath string, object storage.Object) error { info, err := object.Stat() if err != nil { return err @@ -364,7 +364,7 @@ func runDump(ctx *cli.Context) error { if ctx.IsSet("skip-package-data") && ctx.Bool("skip-package-data") { log.Info("Skip dumping package data") - } else if err := storage.Packages.IterateObjects(func(objPath string, object storage.Object) error { + } else if err := storage.Packages.IterateObjects("", func(objPath string, object storage.Object) error { info, err := object.Stat() if err != nil { return err diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini index c3c20a216c2d..1e55ce73a238 100644 --- a/custom/conf/app.example.ini +++ b/custom/conf/app.example.ini @@ -20,7 +20,7 @@ ;; - The environment variable `$GITEA_WORK_DIR` ;; - A built-in value set at build time (see building from source) ;; - Otherwise it defaults to the directory of the _`AppPath`_ -;; - If any of the above are relative paths then they are made absolute against the +;; - If any of the above are relative paths then they are made absolute against ;; the directory of the _`AppPath`_ ;; - _`CustomPath`_: This is the base directory for custom templates and other options. ;; It is determined by using the first set thing in the following hierarchy: @@ -2272,6 +2272,17 @@ ROUTER = console ;PULL = 300 ;GC = 60 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Git Reflog timeout in days +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;[git.reflog] +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;ENABLED = true +;EXPIRATION = 90 + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;[mirror] @@ -2505,6 +2516,8 @@ ROUTER = console ;LIMIT_SIZE_PYPI = -1 ;; Maximum size of a RubyGems upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`) ;LIMIT_SIZE_RUBYGEMS = -1 +;; Maximum size of a Swift upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`) +;LIMIT_SIZE_SWIFT = -1 ;; Maximum size of a Vagrant upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`) ;LIMIT_SIZE_VAGRANT = -1 diff --git a/docs/content/doc/advanced/config-cheat-sheet.en-us.md b/docs/content/doc/advanced/config-cheat-sheet.en-us.md index a5ef977f15be..e0df371a0f0a 100644 --- a/docs/content/doc/advanced/config-cheat-sheet.en-us.md +++ b/docs/content/doc/advanced/config-cheat-sheet.en-us.md @@ -46,7 +46,7 @@ reported as part of the default configuration when running `gitea --help` or on - The environment variable `$GITEA_WORK_DIR` - A built-in value set at build time (see building from source) - Otherwise it defaults to the directory of the _`AppPath`_ - - If any of the above are relative paths then they are made absolute against the + - If any of the above are relative paths then they are made absolute against the directory of the _`AppPath`_ - _`CustomPath`_: This is the base directory for custom templates and other options. It is determined by using the first set thing in the following hierarchy: @@ -1093,6 +1093,11 @@ Default templates for project boards: - `DISABLE_CORE_PROTECT_NTFS`: **false** Set to true to forcibly set `core.protectNTFS` to false. - `DISABLE_PARTIAL_CLONE`: **false** Disable the usage of using partial clones for git. +## Git - Reflog settings (`git.reflog`) + +- `ENABLED`: **true** Set to true to enable Git to write changes to reflogs in each repo. +- `EXPIRATION`: **90** Reflog entry lifetime, in days. Entries are removed opportunistically by Git. + ## Git - Timeout settings (`git.timeout`) - `DEFAULT`: **360**: Git operations default timeout seconds. @@ -1249,6 +1254,7 @@ Task queue configuration has been moved to `queue.task`. However, the below conf - `LIMIT_SIZE_PUB`: **-1**: Maximum size of a Pub upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`) - `LIMIT_SIZE_PYPI`: **-1**: Maximum size of a PyPI upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`) - `LIMIT_SIZE_RUBYGEMS`: **-1**: Maximum size of a RubyGems upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`) +- `LIMIT_SIZE_SWIFT`: **-1**: Maximum size of a Swift upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`) - `LIMIT_SIZE_VAGRANT`: **-1**: Maximum size of a Vagrant upload (`-1` means no limits, format `1000`, `1 MB`, `1 GiB`) ## Mirror (`mirror`) diff --git a/docs/content/doc/advanced/customizing-gitea.en-us.md b/docs/content/doc/advanced/customizing-gitea.en-us.md index bad6342aad44..4c0235c04aca 100644 --- a/docs/content/doc/advanced/customizing-gitea.en-us.md +++ b/docs/content/doc/advanced/customizing-gitea.en-us.md @@ -354,7 +354,7 @@ To make a custom theme available to all users: Community themes are listed in [gitea/awesome-gitea#themes](https://gitea.com/gitea/awesome-gitea#themes). -The `arc-green` theme source can be found [here](https://github.com/go-gitea/gitea/blob/main/web_src/less/themes/theme-arc-green.less). +The `arc-green` theme source can be found [here](https://github.com/go-gitea/gitea/blob/main/web_src/css/themes/theme-arc-green.css). If your custom theme is considered a dark theme, set the global css variable `--is-dark-theme` to `true`. This allows Gitea to adjust the Monaco code editor's theme accordingly. diff --git a/docs/content/doc/developers/guidelines-frontend.en-us.md b/docs/content/doc/developers/guidelines-frontend.en-us.md index 9ac317f40190..e2bdc7adcb59 100644 --- a/docs/content/doc/developers/guidelines-frontend.en-us.md +++ b/docs/content/doc/developers/guidelines-frontend.en-us.md @@ -21,13 +21,13 @@ menu: ## Background -Gitea uses [Less CSS](https://lesscss.org), [Fomantic-UI](https://fomantic-ui.com/introduction/getting-started.html) (based on [jQuery](https://api.jquery.com)) and [Vue3](https://vuejs.org/) for its frontend. +Gitea uses [Fomantic-UI](https://fomantic-ui.com/introduction/getting-started.html) (based on [jQuery](https://api.jquery.com)) and [Vue3](https://vuejs.org/) for its frontend. The HTML pages are rendered by [Go HTML Template](https://pkg.go.dev/html/template). The source files can be found in the following directories: -* **Less styles:** `web_src/less/` +* **CSS styles:** `web_src/css/` * **JavaScript files:** `web_src/js/` * **Vue components:** `web_src/js/components/` * **Go HTML templates:** `templates/` diff --git a/docs/content/doc/features/localization.zh-cn.md b/docs/content/doc/features/localization.zh-cn.md index 6a6f63732665..dd2dc1fa90f6 100644 --- a/docs/content/doc/features/localization.zh-cn.md +++ b/docs/content/doc/features/localization.zh-cn.md @@ -15,4 +15,18 @@ menu: # 本地化 -## TBD +Gitea的本地化是通过我们的[Crowdin项目](https://crowdin.com/project/gitea)进行的。 + +对于对**英语翻译**的更改,可以发出pull-request,来更改[英语语言环境](https://github.com/go-gitea/gitea/blob/master/options/locale/locale_en-US.ini)中合适的关键字。 + +有关对**非英语**翻译的更改,请参阅上面的 Crowdin 项目。 + +## 支持的语言 + +上述 Crowdin 项目中列出的任何语言一旦翻译了 25% 或更多都将得到支持。 + +翻译被接受后,它将在下一次 Crowdin 同步后反映在主存储库中,这通常是在任何 PR 合并之后。 + +在撰写本文时,这意味着更改后的翻译可能要到 Gitea 的下一个版本才会出现。 + +如果使用开发版本,则在同步更改内容后,它应该会在更新后立即显示。 diff --git a/docs/content/doc/packages/overview.en-us.md b/docs/content/doc/packages/overview.en-us.md index f93fec639349..08da8ced4844 100644 --- a/docs/content/doc/packages/overview.en-us.md +++ b/docs/content/doc/packages/overview.en-us.md @@ -40,6 +40,7 @@ The following package managers are currently supported: | [Pub]({{< relref "doc/packages/pub.en-us.md" >}}) | Dart | `dart`, `flutter` | | [PyPI]({{< relref "doc/packages/pypi.en-us.md" >}}) | Python | `pip`, `twine` | | [RubyGems]({{< relref "doc/packages/rubygems.en-us.md" >}}) | Ruby | `gem`, `Bundler` | +| [Swift]({{< relref "doc/packages/rubygems.en-us.md" >}}) | Swift | `swift` | | [Vagrant]({{< relref "doc/packages/vagrant.en-us.md" >}}) | - | `vagrant` | **The following paragraphs only apply if Packages are not globally disabled!** diff --git a/docs/content/doc/packages/swift.en-us.md b/docs/content/doc/packages/swift.en-us.md new file mode 100644 index 000000000000..61a4c9a55d42 --- /dev/null +++ b/docs/content/doc/packages/swift.en-us.md @@ -0,0 +1,93 @@ +--- +date: "2023-01-10T00:00:00+00:00" +title: "Swift Packages Repository" +slug: "packages/swift" +draft: false +toc: false +menu: + sidebar: + parent: "packages" + name: "Swift" + weight: 95 + identifier: "swift" +--- + +# Swift Packages Repository + +Publish [Swift](hhttps://www.swift.org/) packages for your user or organization. + +**Table of Contents** + +{{< toc >}} + +## Requirements + +To work with the Swift package registry, you need to use [swift](https://www.swift.org/getting-started/) to consume and a HTTP client (like `curl`) to publish packages. + +## Configuring the package registry + +To register the package registry and provide credentials, execute: + +```shell +swift package-registry set https://gitea.example.com/api/packages/{owner}/swift -login {username} -password {password} +``` + +| Placeholder | Description | +| ------------ | ----------- | +| `owner` | The owner of the package. | +| `username` | Your Gitea username. | +| `password` | Your Gitea password. If you are using 2FA or OAuth use a [personal access token]({{< relref "doc/developers/api-usage.en-us.md#authentication" >}}) instead of the password. | + +The login is optional and only needed if the package registry is private. + +## Publish a package + +First you have to pack the contents of your package: + +```shell +swift package archive-source +``` + +To publish the package perform a HTTP PUT request with the package content in the request body. + +```shell --user your_username:your_password_or_token \ +curl -X PUT --user {username}:{password} \ + -H "Accept: application/vnd.swift.registry.v1+json" \ + -F source-archive=@/path/to/package.zip \ + -F metadata={metadata} \ + https://gitea.example.com/api/packages/{owner}/swift/{scope}/{name}/{version} +``` + +| Placeholder | Description | +| ----------- | ----------- | +| `username` | Your Gitea username. | +| `password` | Your Gitea password. If you are using 2FA or OAuth use a [personal access token]({{< relref "doc/developers/api-usage.en-us.md#authentication" >}}) instead of the password. | +| `owner` | The owner of the package. | +| `scope` | The package scope. | +| `name` | The package name. | +| `version` | The package version. | +| `metadata` | (Optional) The metadata of the package. JSON encoded subset of https://schema.org/SoftwareSourceCode | + +You cannot publish a package if a package of the same name and version already exists. You must delete the existing package first. + +## Install a package + +To install a Swift package from the package registry, add it in the `Package.swift` file dependencies list: + +``` +dependencies: [ + .package(id: "{scope}.{name}", from:"{version}") +] +``` + +| Parameter | Description | +| ----------- | ----------- | +| `scope` | The package scope. | +| `name` | The package name. | +| `version` | The package version. | + +Afterwards execute the following command to install it: + +```shell +swift package resolve +``` diff --git a/docs/content/doc/usage/push-options.en-us.md b/docs/content/doc/usage/push-options.en-us.md index 8d7de19609c8..b58a91c2cc54 100644 --- a/docs/content/doc/usage/push-options.en-us.md +++ b/docs/content/doc/usage/push-options.en-us.md @@ -29,5 +29,5 @@ were added. Example of changing a repository's visibility to public: ```shell -git push -o repo.private=false -u origin master +git push -o repo.private=false -u origin main ``` diff --git a/docs/content/doc/usage/push-options.zh-tw.md b/docs/content/doc/usage/push-options.zh-tw.md index d6ffbe695b40..558492af7707 100644 --- a/docs/content/doc/usage/push-options.zh-tw.md +++ b/docs/content/doc/usage/push-options.zh-tw.md @@ -29,5 +29,5 @@ Gitea 從 `1.13` 版開始支援某些 [push options](https://git-scm.com/docs/g 以下範例修改儲存庫的可見性為公開: ```shell -git push -o repo.private=false -u origin master +git push -o repo.private=false -u origin main ``` diff --git a/docs/content/doc/usage/push-to-create.en-us.md b/docs/content/doc/usage/push-to-create.en-us.md new file mode 100644 index 000000000000..7ed3f563687d --- /dev/null +++ b/docs/content/doc/usage/push-to-create.en-us.md @@ -0,0 +1,40 @@ +--- +date: "2020-07-06T16:00:00+02:00" +title: "Usage: Push To Create" +slug: "push-to-create" +weight: 15 +toc: false +draft: false +menu: + sidebar: + parent: "usage" + name: "Push To Create" + weight: 15 + identifier: "push-to-create" +--- + +# Push To Create + +Push to create is a feature that allows you to push to a repository that does not exist yet in Gitea. This is useful for automation and for allowing users to create repositories without having to go through the web interface. This feature is disabled by default. + +## Enabling Push To Create + +In the `app.ini` file, set `ENABLE_PUSH_CREATE_USER` to `true` and `ENABLE_PUSH_CREATE_ORG` to `true` if you want to allow users to create repositories in their own user account and in organizations they are a member of respectively. Restart Gitea for the changes to take effect. You can read more about these two options in the [Configuration Cheat Sheet]({{< relref "doc/advanced/config-cheat-sheet.en-us.md#repository-repository" >}}). + +## Using Push To Create + +Assuming you have a git repository in the current directory, you can push to a repository that does not exist yet in Gitea by running the following command: + +```shell +# Add the remote you want to push to +git remote add origin git@{domain}:{username}/{repo name that does not exist yet}.git + +# push to the remote +git push -u origin main +``` + +This assumes you are using an SSH remote, but you can also use HTTPS remotes as well. + +## Push options (bonus) + +Push-to-create will default to the visibility defined by `DEFAULT_PUSH_CREATE_PRIVATE` in `app.ini`. To explicitly set the visibility, you can use a [push option]({{< relref "doc/usage/push-options.en-us.md" >}}). diff --git a/models/actions/run.go b/models/actions/run.go index d5ab45a51958..a711cfee2ecd 100644 --- a/models/actions/run.go +++ b/models/actions/run.go @@ -128,6 +128,17 @@ func (run *ActionRun) GetPushEventPayload() (*api.PushPayload, error) { return nil, fmt.Errorf("event %s is not a push event", run.Event) } +func (run *ActionRun) GetPullRequestEventPayload() (*api.PullRequestPayload, error) { + if run.Event == webhook_module.HookEventPullRequest { + var payload api.PullRequestPayload + if err := json.Unmarshal([]byte(run.EventPayload), &payload); err != nil { + return nil, err + } + return &payload, nil + } + return nil, fmt.Errorf("event %s is not a pull request event", run.Event) +} + func updateRepoRunsNumbers(ctx context.Context, repo *repo_model.Repository) error { _, err := db.GetEngine(ctx).ID(repo.ID). SetExpr("num_action_runs", diff --git a/models/issues/pull.go b/models/issues/pull.go index 6a1dc3155624..a15ebec0b52a 100644 --- a/models/issues/pull.go +++ b/models/issues/pull.go @@ -660,10 +660,10 @@ func GetPullRequestByIssueID(ctx context.Context, issueID int64) (*PullRequest, // GetAllUnmergedAgitPullRequestByPoster get all unmerged agit flow pull request // By poster id. -func GetAllUnmergedAgitPullRequestByPoster(uid int64) ([]*PullRequest, error) { +func GetAllUnmergedAgitPullRequestByPoster(ctx context.Context, uid int64) ([]*PullRequest, error) { pulls := make([]*PullRequest, 0, 10) - err := db.GetEngine(db.DefaultContext). + err := db.GetEngine(ctx). Where("has_merged=? AND flow = ? AND issue.is_closed=? AND issue.poster_id=?", false, PullRequestFlowAGit, false, uid). Join("INNER", "issue", "issue.id=pull_request.issue_id"). diff --git a/models/migrations/fixtures/Test_DeleteOrphanedIssueLabels/label.yml b/models/migrations/fixtures/Test_DeleteOrphanedIssueLabels/label.yml index 085b7f0882d5..d651c87d5b0d 100644 --- a/models/migrations/fixtures/Test_DeleteOrphanedIssueLabels/label.yml +++ b/models/migrations/fixtures/Test_DeleteOrphanedIssueLabels/label.yml @@ -4,7 +4,6 @@ org_id: 0 name: label1 color: '#abcdef' - exclusive: false num_issues: 2 num_closed_issues: 0 @@ -14,7 +13,6 @@ org_id: 0 name: label2 color: '#000000' - exclusive: false num_issues: 1 num_closed_issues: 1 - @@ -23,7 +21,6 @@ org_id: 3 name: orglabel3 color: '#abcdef' - exclusive: false num_issues: 0 num_closed_issues: 0 @@ -33,7 +30,6 @@ org_id: 3 name: orglabel4 color: '#000000' - exclusive: false num_issues: 1 num_closed_issues: 0 @@ -43,6 +39,5 @@ org_id: 0 name: pull-test-label color: '#000000' - exclusive: false num_issues: 0 num_closed_issues: 0 diff --git a/models/packages/descriptor.go b/models/packages/descriptor.go index f4be21e74e20..06699b5d572b 100644 --- a/models/packages/descriptor.go +++ b/models/packages/descriptor.go @@ -24,6 +24,7 @@ import ( "code.gitea.io/gitea/modules/packages/pub" "code.gitea.io/gitea/modules/packages/pypi" "code.gitea.io/gitea/modules/packages/rubygems" + "code.gitea.io/gitea/modules/packages/swift" "code.gitea.io/gitea/modules/packages/vagrant" "github.com/hashicorp/go-version" @@ -159,6 +160,8 @@ func GetPackageDescriptor(ctx context.Context, pv *PackageVersion) (*PackageDesc metadata = &pypi.Metadata{} case TypeRubyGems: metadata = &rubygems.Metadata{} + case TypeSwift: + metadata = &swift.Metadata{} case TypeVagrant: metadata = &vagrant.Metadata{} default: diff --git a/models/packages/package.go b/models/packages/package.go index 32f30fab9b40..ccc9257c3123 100644 --- a/models/packages/package.go +++ b/models/packages/package.go @@ -44,6 +44,7 @@ const ( TypePub Type = "pub" TypePyPI Type = "pypi" TypeRubyGems Type = "rubygems" + TypeSwift Type = "swift" TypeVagrant Type = "vagrant" ) @@ -62,6 +63,7 @@ var TypeList = []Type{ TypePub, TypePyPI, TypeRubyGems, + TypeSwift, TypeVagrant, } @@ -96,6 +98,8 @@ func (pt Type) Name() string { return "PyPI" case TypeRubyGems: return "RubyGems" + case TypeSwift: + return "Swift" case TypeVagrant: return "Vagrant" } @@ -133,6 +137,8 @@ func (pt Type) SVGName() string { return "gitea-python" case TypeRubyGems: return "gitea-rubygems" + case TypeSwift: + return "gitea-swift" case TypeVagrant: return "gitea-vagrant" } diff --git a/models/repo/repo_list.go b/models/repo/repo_list.go index d9cd905a1936..92b9c15b4bd8 100644 --- a/models/repo/repo_list.go +++ b/models/repo/repo_list.go @@ -62,7 +62,8 @@ func RepositoryListOfMap(repoMap map[int64]*Repository) RepositoryList { return RepositoryList(ValuesRepository(repoMap)) } -func (repos RepositoryList) loadAttributes(ctx context.Context) error { +// LoadAttributes loads the attributes for the given RepositoryList +func (repos RepositoryList) LoadAttributes(ctx context.Context) error { if len(repos) == 0 { return nil } @@ -107,11 +108,6 @@ func (repos RepositoryList) loadAttributes(ctx context.Context) error { return nil } -// LoadAttributes loads the attributes for the given RepositoryList -func (repos RepositoryList) LoadAttributes() error { - return repos.loadAttributes(db.DefaultContext) -} - // SearchRepoOptions holds the search options type SearchRepoOptions struct { db.ListOptions @@ -547,7 +543,7 @@ func SearchRepositoryByCondition(ctx context.Context, opts *SearchRepoOptions, c } if loadAttributes { - if err := repos.loadAttributes(ctx); err != nil { + if err := repos.LoadAttributes(ctx); err != nil { return nil, 0, fmt.Errorf("LoadAttributes: %w", err) } } diff --git a/models/user/user.go b/models/user/user.go index 454779b9ea36..82c2d3b6cdc1 100644 --- a/models/user/user.go +++ b/models/user/user.go @@ -742,13 +742,13 @@ func VerifyUserActiveCode(code string) (user *User) { } // ChangeUserName changes all corresponding setting from old user name to new one. -func ChangeUserName(u *User, newUserName string) (err error) { +func ChangeUserName(ctx context.Context, u *User, newUserName string) (err error) { oldUserName := u.Name if err = IsUsableUsername(newUserName); err != nil { return err } - ctx, committer, err := db.TxContext(db.DefaultContext) + ctx, committer, err := db.TxContext(ctx) if err != nil { return err } diff --git a/modules/actions/github.go b/modules/actions/github.go new file mode 100644 index 000000000000..bcde9a0f552e --- /dev/null +++ b/modules/actions/github.go @@ -0,0 +1,41 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package actions + +import ( + webhook_module "code.gitea.io/gitea/modules/webhook" + + "github.com/nektos/act/pkg/jobparser" +) + +const ( + githubEventPullRequest = "pull_request" + githubEventPullRequestTarget = "pull_request_target" + githubEventPullRequestReviewComment = "pull_request_review_comment" + githubEventPullRequestReview = "pull_request_review" + githubEventRegistryPackage = "registry_package" + githubEventCreate = "create" + githubEventDelete = "delete" + githubEventFork = "fork" + githubEventPush = "push" + githubEventIssues = "issues" + githubEventIssueComment = "issue_comment" + githubEventRelease = "release" + githubEventPullRequestComment = "pull_request_comment" +) + +func convertFromGithubEvent(evt *jobparser.Event) string { + switch evt.Name { + case githubEventPullRequest, githubEventPullRequestTarget, githubEventPullRequestReview, + githubEventPullRequestReviewComment: + return string(webhook_module.HookEventPullRequest) + case githubEventRegistryPackage: + return string(webhook_module.HookEventPackage) + case githubEventCreate, githubEventDelete, githubEventFork, githubEventPush, + githubEventIssues, githubEventIssueComment, githubEventRelease, githubEventPullRequestComment: + fallthrough + default: + return evt.Name + } +} diff --git a/modules/actions/workflows.go b/modules/actions/workflows.go index 7f0e6e456436..67c3b12427ad 100644 --- a/modules/actions/workflows.go +++ b/modules/actions/workflows.go @@ -44,6 +44,32 @@ func ListWorkflows(commit *git.Commit) (git.Entries, error) { return ret, nil } +func GetContentFromEntry(entry *git.TreeEntry) ([]byte, error) { + f, err := entry.Blob().DataAsync() + if err != nil { + return nil, err + } + content, err := io.ReadAll(f) + _ = f.Close() + if err != nil { + return nil, err + } + return content, nil +} + +func GetEventsFromContent(content []byte) ([]*jobparser.Event, error) { + workflow, err := model.ReadWorkflow(bytes.NewReader(content)) + if err != nil { + return nil, err + } + events, err := jobparser.ParseRawOn(&workflow.RawOn) + if err != nil { + return nil, err + } + + return events, nil +} + func DetectWorkflows(commit *git.Commit, triggedEvent webhook_module.HookEventType, payload api.Payloader) (map[string][]byte, error) { entries, err := ListWorkflows(commit) if err != nil { @@ -52,29 +78,17 @@ func DetectWorkflows(commit *git.Commit, triggedEvent webhook_module.HookEventTy workflows := make(map[string][]byte, len(entries)) for _, entry := range entries { - f, err := entry.Blob().DataAsync() - if err != nil { - return nil, err - } - content, err := io.ReadAll(f) - _ = f.Close() + content, err := GetContentFromEntry(entry) if err != nil { return nil, err } - workflow, err := model.ReadWorkflow(bytes.NewReader(content)) - if err != nil { - log.Warn("ignore invalid workflow %q: %v", entry.Name(), err) - continue - } - events, err := jobparser.ParseRawOn(&workflow.RawOn) + events, err := GetEventsFromContent(content) if err != nil { log.Warn("ignore invalid workflow %q: %v", entry.Name(), err) continue } for _, evt := range events { - if evt.Name != triggedEvent.Event() { - continue - } + log.Trace("detect workflow %q for event %#v matching %q", entry.Name(), evt, triggedEvent) if detectMatched(commit, triggedEvent, payload, evt) { workflows[entry.Name()] = content } @@ -85,138 +99,197 @@ func DetectWorkflows(commit *git.Commit, triggedEvent webhook_module.HookEventTy } func detectMatched(commit *git.Commit, triggedEvent webhook_module.HookEventType, payload api.Payloader, evt *jobparser.Event) bool { - if len(evt.Acts) == 0 { - return true + if convertFromGithubEvent(evt) != string(triggedEvent) { + return false } switch triggedEvent { - case webhook_module.HookEventCreate: - fallthrough - case webhook_module.HookEventDelete: - fallthrough - case webhook_module.HookEventFork: - log.Warn("unsupported event %q", triggedEvent.Event()) - return false + case webhook_module.HookEventCreate, + webhook_module.HookEventDelete, + webhook_module.HookEventFork, + webhook_module.HookEventIssueAssign, + webhook_module.HookEventIssueLabel, + webhook_module.HookEventIssueMilestone, + webhook_module.HookEventPullRequestAssign, + webhook_module.HookEventPullRequestLabel, + webhook_module.HookEventPullRequestMilestone, + webhook_module.HookEventPullRequestComment, + webhook_module.HookEventPullRequestReviewApproved, + webhook_module.HookEventPullRequestReviewRejected, + webhook_module.HookEventPullRequestReviewComment, + webhook_module.HookEventWiki, + webhook_module.HookEventRepository, + webhook_module.HookEventRelease, + webhook_module.HookEventPackage: + if len(evt.Acts) != 0 { + log.Warn("Ignore unsupported %s event arguments %q", triggedEvent, evt.Acts) + } + // no special filter parameters for these events, just return true if name matched + return true + case webhook_module.HookEventPush: - pushPayload := payload.(*api.PushPayload) - matchTimes := 0 - // all acts conditions should be satisfied - for cond, vals := range evt.Acts { - switch cond { - case "branches", "tags": - refShortName := git.RefName(pushPayload.Ref).ShortName() + return matchPushEvent(commit, payload.(*api.PushPayload), evt) + + case webhook_module.HookEventIssues: + return matchIssuesEvent(commit, payload.(*api.IssuePayload), evt) + + case webhook_module.HookEventPullRequest, webhook_module.HookEventPullRequestSync: + return matchPullRequestEvent(commit, payload.(*api.PullRequestPayload), evt) + + case webhook_module.HookEventIssueComment: + return matchIssueCommentEvent(commit, payload.(*api.IssueCommentPayload), evt) + + default: + log.Warn("unsupported event %q", triggedEvent) + return false + } +} + +func matchPushEvent(commit *git.Commit, pushPayload *api.PushPayload, evt *jobparser.Event) bool { + // with no special filter parameters + if len(evt.Acts) == 0 { + return true + } + + matchTimes := 0 + // all acts conditions should be satisfied + for cond, vals := range evt.Acts { + switch cond { + case "branches", "tags": + refShortName := git.RefName(pushPayload.Ref).ShortName() + for _, val := range vals { + if glob.MustCompile(val, '/').Match(refShortName) { + matchTimes++ + break + } + } + case "paths": + filesChanged, err := commit.GetFilesChangedSinceCommit(pushPayload.Before) + if err != nil { + log.Error("GetFilesChangedSinceCommit [commit_sha1: %s]: %v", commit.ID.String(), err) + } else { for _, val := range vals { - if glob.MustCompile(val, '/').Match(refShortName) { + matched := false + for _, file := range filesChanged { + if glob.MustCompile(val, '/').Match(file) { + matched = true + break + } + } + if matched { matchTimes++ break } } - case "paths": - filesChanged, err := commit.GetFilesChangedSinceCommit(pushPayload.Before) - if err != nil { - log.Error("GetFilesChangedSinceCommit [commit_sha1: %s]: %v", commit.ID.String(), err) - } else { - for _, val := range vals { - matched := false - for _, file := range filesChanged { - if glob.MustCompile(val, '/').Match(file) { - matched = true - break - } - } - if matched { - matchTimes++ - break - } - } + } + default: + log.Warn("push event unsupported condition %q", cond) + } + } + return matchTimes == len(evt.Acts) +} + +func matchIssuesEvent(commit *git.Commit, issuePayload *api.IssuePayload, evt *jobparser.Event) bool { + // with no special filter parameters + if len(evt.Acts) == 0 { + return true + } + + matchTimes := 0 + // all acts conditions should be satisfied + for cond, vals := range evt.Acts { + switch cond { + case "types": + for _, val := range vals { + if glob.MustCompile(val, '/').Match(string(issuePayload.Action)) { + matchTimes++ + break } - default: - log.Warn("unsupported condition %q", cond) } + default: + log.Warn("issue event unsupported condition %q", cond) } - return matchTimes == len(evt.Acts) + } + return matchTimes == len(evt.Acts) +} - case webhook_module.HookEventIssues: - fallthrough - case webhook_module.HookEventIssueAssign: - fallthrough - case webhook_module.HookEventIssueLabel: - fallthrough - case webhook_module.HookEventIssueMilestone: - fallthrough - case webhook_module.HookEventIssueComment: - fallthrough - case webhook_module.HookEventPullRequest: - prPayload := payload.(*api.PullRequestPayload) - matchTimes := 0 - // all acts conditions should be satisfied - for cond, vals := range evt.Acts { - switch cond { - case "types": - for _, val := range vals { - if glob.MustCompile(val, '/').Match(string(prPayload.Action)) { - matchTimes++ - break - } +func matchPullRequestEvent(commit *git.Commit, prPayload *api.PullRequestPayload, evt *jobparser.Event) bool { + // with no special filter parameters + if len(evt.Acts) == 0 { + // defaultly, only pull request opened and synchronized will trigger workflow + return prPayload.Action == api.HookIssueSynchronized || prPayload.Action == api.HookIssueOpened + } + + matchTimes := 0 + // all acts conditions should be satisfied + for cond, vals := range evt.Acts { + switch cond { + case "types": + action := prPayload.Action + if prPayload.Action == api.HookIssueSynchronized { + action = "synchronize" + } + log.Trace("matching pull_request %s with %v", action, vals) + for _, val := range vals { + if glob.MustCompile(val, '/').Match(string(action)) { + matchTimes++ + break + } + } + case "branches": + refShortName := git.RefName(prPayload.PullRequest.Base.Ref).ShortName() + for _, val := range vals { + if glob.MustCompile(val, '/').Match(refShortName) { + matchTimes++ + break } - case "branches": - refShortName := git.RefName(prPayload.PullRequest.Base.Ref).ShortName() + } + case "paths": + filesChanged, err := commit.GetFilesChangedSinceCommit(prPayload.PullRequest.Base.Ref) + if err != nil { + log.Error("GetFilesChangedSinceCommit [commit_sha1: %s]: %v", commit.ID.String(), err) + } else { for _, val := range vals { - if glob.MustCompile(val, '/').Match(refShortName) { + matched := false + for _, file := range filesChanged { + if glob.MustCompile(val, '/').Match(file) { + matched = true + break + } + } + if matched { matchTimes++ break } } - case "paths": - filesChanged, err := commit.GetFilesChangedSinceCommit(prPayload.PullRequest.Base.Ref) - if err != nil { - log.Error("GetFilesChangedSinceCommit [commit_sha1: %s]: %v", commit.ID.String(), err) - } else { - for _, val := range vals { - matched := false - for _, file := range filesChanged { - if glob.MustCompile(val, '/').Match(file) { - matched = true - break - } - } - if matched { - matchTimes++ - break - } - } + } + default: + log.Warn("pull request event unsupported condition %q", cond) + } + } + return matchTimes == len(evt.Acts) +} + +func matchIssueCommentEvent(commit *git.Commit, issueCommentPayload *api.IssueCommentPayload, evt *jobparser.Event) bool { + // with no special filter parameters + if len(evt.Acts) == 0 { + return true + } + + matchTimes := 0 + // all acts conditions should be satisfied + for cond, vals := range evt.Acts { + switch cond { + case "types": + for _, val := range vals { + if glob.MustCompile(val, '/').Match(string(issueCommentPayload.Action)) { + matchTimes++ + break } - default: - log.Warn("unsupported condition %q", cond) } + default: + log.Warn("issue comment unsupported condition %q", cond) } - return matchTimes == len(evt.Acts) - case webhook_module.HookEventPullRequestAssign: - fallthrough - case webhook_module.HookEventPullRequestLabel: - fallthrough - case webhook_module.HookEventPullRequestMilestone: - fallthrough - case webhook_module.HookEventPullRequestComment: - fallthrough - case webhook_module.HookEventPullRequestReviewApproved: - fallthrough - case webhook_module.HookEventPullRequestReviewRejected: - fallthrough - case webhook_module.HookEventPullRequestReviewComment: - fallthrough - case webhook_module.HookEventPullRequestSync: - fallthrough - case webhook_module.HookEventWiki: - fallthrough - case webhook_module.HookEventRepository: - fallthrough - case webhook_module.HookEventRelease: - fallthrough - case webhook_module.HookEventPackage: - fallthrough - default: - log.Warn("unsupported event %q", triggedEvent.Event()) } - return false + return matchTimes == len(evt.Acts) } diff --git a/modules/context/pagination.go b/modules/context/pagination.go index 3effd88f109c..5a88c92053aa 100644 --- a/modules/context/pagination.go +++ b/modules/context/pagination.go @@ -18,10 +18,11 @@ type Pagination struct { urlParams []string } -// NewPagination creates a new instance of the Pagination struct -func NewPagination(total, page, issueNum, numPages int) *Pagination { +// NewPagination creates a new instance of the Pagination struct. +// "pagingNum" is "page size" or "limit", "current" is "page" +func NewPagination(total, pagingNum, current, numPages int) *Pagination { p := &Pagination{} - p.Paginater = paginator.New(total, page, issueNum, numPages) + p.Paginater = paginator.New(total, pagingNum, current, numPages) return p } diff --git a/modules/doctor/storage.go b/modules/doctor/storage.go index aa987de4477b..c20566d67593 100644 --- a/modules/doctor/storage.go +++ b/modules/doctor/storage.go @@ -31,7 +31,7 @@ func commonCheckStorage(ctx context.Context, logger log.Logger, autofix bool, op totalSize, orphanedSize := int64(0), int64(0) var pathsToDelete []string - if err := opts.storer.IterateObjects(func(p string, obj storage.Object) error { + if err := opts.storer.IterateObjects("", func(p string, obj storage.Object) error { defer obj.Close() totalCount++ diff --git a/modules/git/git.go b/modules/git/git.go index 24cfea8c7fe1..a31afc077a5c 100644 --- a/modules/git/git.go +++ b/modules/git/git.go @@ -201,6 +201,23 @@ func InitFull(ctx context.Context) (err error) { return syncGitConfig() } +func enableReflogs() error { + if err := configSet("core.logAllRefUpdates", "true"); err != nil { + return err + } + err := configSet("gc.reflogExpire", fmt.Sprintf("%d", setting.Git.Reflog.Expiration)) + return err +} + +func disableReflogs() error { + if err := configUnsetAll("core.logAllRefUpdates", "true"); err != nil { + return err + } else if err := configUnsetAll("gc.reflogExpire", ""); err != nil { + return err + } + return nil +} + // syncGitConfig only modifies gitconfig, won't change global variables (otherwise there will be data-race problem) func syncGitConfig() (err error) { if err = os.MkdirAll(HomeDir(), os.ModePerm); err != nil { @@ -224,6 +241,16 @@ func syncGitConfig() (err error) { return err } + if setting.Git.Reflog.Enabled { + if err := enableReflogs(); err != nil { + return err + } + } else { + if err := disableReflogs(); err != nil { + return err + } + } + if CheckGitVersionAtLeast("2.10") == nil { if err := configSet("receive.advertisePushOptions", "true"); err != nil { return err diff --git a/modules/highlight/highlight.go b/modules/highlight/highlight.go index a5c38940a7be..fac682b8a81a 100644 --- a/modules/highlight/highlight.go +++ b/modules/highlight/highlight.go @@ -36,6 +36,8 @@ var ( once sync.Once cache *lru.TwoQueueCache + + githubStyles = styles.Get("github") ) // NewContext loads custom highlight map from local config @@ -121,7 +123,7 @@ func CodeFromLexer(lexer chroma.Lexer, code string) string { return code } // style not used for live site but need to pass something - err = formatter.Format(htmlw, styles.GitHub, iterator) + err = formatter.Format(htmlw, githubStyles, iterator) if err != nil { log.Error("Can't format code: %v", err) return code @@ -184,7 +186,7 @@ func File(fileName, language string, code []byte) ([]string, string, error) { lines := make([]string, 0, len(tokensLines)) for _, tokens := range tokensLines { iterator = chroma.Literator(tokens...) - err = formatter.Format(htmlBuf, styles.GitHub, iterator) + err = formatter.Format(htmlBuf, githubStyles, iterator) if err != nil { return nil, "", fmt.Errorf("can't format code: %w", err) } diff --git a/modules/packages/swift/metadata.go b/modules/packages/swift/metadata.go new file mode 100644 index 000000000000..24c4262ab724 --- /dev/null +++ b/modules/packages/swift/metadata.go @@ -0,0 +1,214 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package swift + +import ( + "archive/zip" + "fmt" + "io" + "path" + "regexp" + "strings" + + "code.gitea.io/gitea/modules/json" + "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/modules/validation" + + "github.com/hashicorp/go-version" +) + +var ( + ErrMissingManifestFile = util.NewInvalidArgumentErrorf("Package.swift file is missing") + ErrManifestFileTooLarge = util.NewInvalidArgumentErrorf("Package.swift file is too large") + ErrInvalidManifestVersion = util.NewInvalidArgumentErrorf("manifest version is invalid") + + manifestPattern = regexp.MustCompile(`\APackage(?:@swift-(\d+(?:\.\d+)?(?:\.\d+)?))?\.swift\z`) + toolsVersionPattern = regexp.MustCompile(`\A// swift-tools-version:(\d+(?:\.\d+)?(?:\.\d+)?)`) +) + +const ( + maxManifestFileSize = 128 * 1024 + + PropertyScope = "swift.scope" + PropertyName = "swift.name" + PropertyRepositoryURL = "swift.repository_url" +) + +// Package represents a Swift package +type Package struct { + RepositoryURLs []string + Metadata *Metadata +} + +// Metadata represents the metadata of a Swift package +type Metadata struct { + Description string `json:"description,omitempty"` + Keywords []string `json:"keywords,omitempty"` + RepositoryURL string `json:"repository_url,omitempty"` + License string `json:"license,omitempty"` + Author Person `json:"author,omitempty"` + Manifests map[string]*Manifest `json:"manifests,omitempty"` +} + +// Manifest represents a Package.swift file +type Manifest struct { + Content string `json:"content"` + ToolsVersion string `json:"tools_version,omitempty"` +} + +// https://schema.org/SoftwareSourceCode +type SoftwareSourceCode struct { + Context []string `json:"@context"` + Type string `json:"@type"` + Name string `json:"name"` + Version string `json:"version"` + Description string `json:"description,omitempty"` + Keywords []string `json:"keywords,omitempty"` + CodeRepository string `json:"codeRepository,omitempty"` + License string `json:"license,omitempty"` + Author Person `json:"author"` + ProgrammingLanguage ProgrammingLanguage `json:"programmingLanguage"` + RepositoryURLs []string `json:"repositoryURLs,omitempty"` +} + +// https://schema.org/ProgrammingLanguage +type ProgrammingLanguage struct { + Type string `json:"@type"` + Name string `json:"name"` + URL string `json:"url"` +} + +// https://schema.org/Person +type Person struct { + Type string `json:"@type,omitempty"` + GivenName string `json:"givenName,omitempty"` + MiddleName string `json:"middleName,omitempty"` + FamilyName string `json:"familyName,omitempty"` +} + +func (p Person) String() string { + var sb strings.Builder + if p.GivenName != "" { + sb.WriteString(p.GivenName) + } + if p.MiddleName != "" { + if sb.Len() > 0 { + sb.WriteRune(' ') + } + sb.WriteString(p.MiddleName) + } + if p.FamilyName != "" { + if sb.Len() > 0 { + sb.WriteRune(' ') + } + sb.WriteString(p.FamilyName) + } + return sb.String() +} + +// ParsePackage parses the Swift package upload +func ParsePackage(sr io.ReaderAt, size int64, mr io.Reader) (*Package, error) { + zr, err := zip.NewReader(sr, size) + if err != nil { + return nil, err + } + + p := &Package{ + Metadata: &Metadata{ + Manifests: make(map[string]*Manifest), + }, + } + + for _, file := range zr.File { + manifestMatch := manifestPattern.FindStringSubmatch(path.Base(file.Name)) + if len(manifestMatch) == 0 { + continue + } + + if file.UncompressedSize64 > maxManifestFileSize { + return nil, ErrManifestFileTooLarge + } + + f, err := zr.Open(file.Name) + if err != nil { + return nil, err + } + + content, err := io.ReadAll(f) + + if err := f.Close(); err != nil { + return nil, err + } + + if err != nil { + return nil, err + } + + swiftVersion := "" + if len(manifestMatch) == 2 && manifestMatch[1] != "" { + v, err := version.NewSemver(manifestMatch[1]) + if err != nil { + return nil, ErrInvalidManifestVersion + } + swiftVersion = TrimmedVersionString(v) + } + + manifest := &Manifest{ + Content: string(content), + } + + toolsMatch := toolsVersionPattern.FindStringSubmatch(manifest.Content) + if len(toolsMatch) == 2 { + v, err := version.NewSemver(toolsMatch[1]) + if err != nil { + return nil, ErrInvalidManifestVersion + } + + manifest.ToolsVersion = TrimmedVersionString(v) + } + + p.Metadata.Manifests[swiftVersion] = manifest + } + + if _, found := p.Metadata.Manifests[""]; !found { + return nil, ErrMissingManifestFile + } + + if mr != nil { + var ssc *SoftwareSourceCode + if err := json.NewDecoder(mr).Decode(&ssc); err != nil { + return nil, err + } + + p.Metadata.Description = ssc.Description + p.Metadata.Keywords = ssc.Keywords + p.Metadata.License = ssc.License + p.Metadata.Author = Person{ + GivenName: ssc.Author.GivenName, + MiddleName: ssc.Author.MiddleName, + FamilyName: ssc.Author.FamilyName, + } + + p.Metadata.RepositoryURL = ssc.CodeRepository + if !validation.IsValidURL(p.Metadata.RepositoryURL) { + p.Metadata.RepositoryURL = "" + } + + p.RepositoryURLs = ssc.RepositoryURLs + } + + return p, nil +} + +// TrimmedVersionString returns the version string without the patch segment if it is zero +func TrimmedVersionString(v *version.Version) string { + segments := v.Segments64() + + var b strings.Builder + fmt.Fprintf(&b, "%d.%d", segments[0], segments[1]) + if segments[2] != 0 { + fmt.Fprintf(&b, ".%d", segments[2]) + } + return b.String() +} diff --git a/modules/packages/swift/metadata_test.go b/modules/packages/swift/metadata_test.go new file mode 100644 index 000000000000..3913c2355ba2 --- /dev/null +++ b/modules/packages/swift/metadata_test.go @@ -0,0 +1,144 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package swift + +import ( + "archive/zip" + "bytes" + "strings" + "testing" + + "github.com/hashicorp/go-version" + "github.com/stretchr/testify/assert" +) + +const ( + packageName = "gitea" + packageVersion = "1.0.1" + packageDescription = "Package Description" + packageRepositoryURL = "https://gitea.io/gitea/gitea" + packageAuthor = "KN4CK3R" + packageLicense = "MIT" +) + +func TestParsePackage(t *testing.T) { + createArchive := func(files map[string][]byte) *bytes.Reader { + var buf bytes.Buffer + zw := zip.NewWriter(&buf) + for filename, content := range files { + w, _ := zw.Create(filename) + w.Write(content) + } + zw.Close() + return bytes.NewReader(buf.Bytes()) + } + + t.Run("MissingManifestFile", func(t *testing.T) { + data := createArchive(map[string][]byte{"dummy.txt": {}}) + + p, err := ParsePackage(data, data.Size(), nil) + assert.Nil(t, p) + assert.ErrorIs(t, err, ErrMissingManifestFile) + }) + + t.Run("ManifestFileTooLarge", func(t *testing.T) { + data := createArchive(map[string][]byte{ + "Package.swift": make([]byte, maxManifestFileSize+1), + }) + + p, err := ParsePackage(data, data.Size(), nil) + assert.Nil(t, p) + assert.ErrorIs(t, err, ErrManifestFileTooLarge) + }) + + t.Run("WithoutMetadata", func(t *testing.T) { + content1 := "// swift-tools-version:5.7\n//\n// Package.swift" + content2 := "// swift-tools-version:5.6\n//\n// Package@swift-5.6.swift" + + data := createArchive(map[string][]byte{ + "Package.swift": []byte(content1), + "Package@swift-5.5.swift": []byte(content2), + }) + + p, err := ParsePackage(data, data.Size(), nil) + assert.NotNil(t, p) + assert.NoError(t, err) + + assert.NotNil(t, p.Metadata) + assert.Empty(t, p.RepositoryURLs) + assert.Len(t, p.Metadata.Manifests, 2) + m := p.Metadata.Manifests[""] + assert.Equal(t, "5.7", m.ToolsVersion) + assert.Equal(t, content1, m.Content) + m = p.Metadata.Manifests["5.5"] + assert.Equal(t, "5.6", m.ToolsVersion) + assert.Equal(t, content2, m.Content) + }) + + t.Run("WithMetadata", func(t *testing.T) { + data := createArchive(map[string][]byte{ + "Package.swift": []byte("// swift-tools-version:5.7\n//\n// Package.swift"), + }) + + p, err := ParsePackage( + data, + data.Size(), + strings.NewReader(`{"name":"`+packageName+`","version":"`+packageVersion+`","description":"`+packageDescription+`","keywords":["swift","package"],"license":"`+packageLicense+`","codeRepository":"`+packageRepositoryURL+`","author":{"givenName":"`+packageAuthor+`"},"repositoryURLs":["`+packageRepositoryURL+`"]}`), + ) + assert.NotNil(t, p) + assert.NoError(t, err) + + assert.NotNil(t, p.Metadata) + assert.Len(t, p.Metadata.Manifests, 1) + m := p.Metadata.Manifests[""] + assert.Equal(t, "5.7", m.ToolsVersion) + + assert.Equal(t, packageDescription, p.Metadata.Description) + assert.ElementsMatch(t, []string{"swift", "package"}, p.Metadata.Keywords) + assert.Equal(t, packageLicense, p.Metadata.License) + assert.Equal(t, packageAuthor, p.Metadata.Author.GivenName) + assert.Equal(t, packageRepositoryURL, p.Metadata.RepositoryURL) + assert.ElementsMatch(t, []string{packageRepositoryURL}, p.RepositoryURLs) + }) +} + +func TestTrimmedVersionString(t *testing.T) { + cases := []struct { + Version *version.Version + Expected string + }{ + { + Version: version.Must(version.NewVersion("1")), + Expected: "1.0", + }, + { + Version: version.Must(version.NewVersion("1.0")), + Expected: "1.0", + }, + { + Version: version.Must(version.NewVersion("1.0.0")), + Expected: "1.0", + }, + { + Version: version.Must(version.NewVersion("1.0.1")), + Expected: "1.0.1", + }, + { + Version: version.Must(version.NewVersion("1.0+meta")), + Expected: "1.0", + }, + { + Version: version.Must(version.NewVersion("1.0.0+meta")), + Expected: "1.0", + }, + { + Version: version.Must(version.NewVersion("1.0.1+meta")), + Expected: "1.0.1", + }, + } + + for _, c := range cases { + assert.Equal(t, c.Expected, TrimmedVersionString(c.Version)) + } +} diff --git a/modules/setting/git.go b/modules/setting/git.go index 457b35936e9f..b8e7bb9cf81f 100644 --- a/modules/setting/git.go +++ b/modules/setting/git.go @@ -12,9 +12,13 @@ import ( // Git settings var Git = struct { - Path string - HomePath string - DisableDiffHighlight bool + Path string + HomePath string + DisableDiffHighlight bool + Reflog struct { + Enabled bool + Expiration int + } `ini:"git.reflog"` MaxGitDiffLines int MaxGitDiffLineCharacters int MaxGitDiffFiles int @@ -37,6 +41,13 @@ var Git = struct { GC int `ini:"GC"` } `ini:"git.timeout"` }{ + Reflog: struct { + Enabled bool + Expiration int + }{ + Enabled: true, + Expiration: 90, + }, DisableDiffHighlight: false, MaxGitDiffLines: 1000, MaxGitDiffLineCharacters: 5000, diff --git a/modules/setting/packages.go b/modules/setting/packages.go index 13599e5a63e7..ac0ad62bca3d 100644 --- a/modules/setting/packages.go +++ b/modules/setting/packages.go @@ -39,6 +39,7 @@ var ( LimitSizePub int64 LimitSizePyPI int64 LimitSizeRubyGems int64 + LimitSizeSwift int64 LimitSizeVagrant int64 }{ Enabled: true, @@ -81,6 +82,7 @@ func loadPackagesFrom(rootCfg ConfigProvider) { Packages.LimitSizePub = mustBytes(sec, "LIMIT_SIZE_PUB") Packages.LimitSizePyPI = mustBytes(sec, "LIMIT_SIZE_PYPI") Packages.LimitSizeRubyGems = mustBytes(sec, "LIMIT_SIZE_RUBYGEMS") + Packages.LimitSizeSwift = mustBytes(sec, "LIMIT_SIZE_SWIFT") Packages.LimitSizeVagrant = mustBytes(sec, "LIMIT_SIZE_VAGRANT") } diff --git a/modules/storage/helper.go b/modules/storage/helper.go index 1ab99d98b31b..d1959830b977 100644 --- a/modules/storage/helper.go +++ b/modules/storage/helper.go @@ -90,6 +90,6 @@ func (s discardStorage) URL(_, _ string) (*url.URL, error) { return nil, fmt.Errorf("%s", s) } -func (s discardStorage) IterateObjects(_ func(string, Object) error) error { +func (s discardStorage) IterateObjects(_ string, _ func(string, Object) error) error { return fmt.Errorf("%s", s) } diff --git a/modules/storage/helper_test.go b/modules/storage/helper_test.go index 7d74671c544a..f4c2d0467f7e 100644 --- a/modules/storage/helper_test.go +++ b/modules/storage/helper_test.go @@ -42,7 +42,7 @@ func Test_discardStorage(t *testing.T) { assert.Errorf(t, err, string(tt)) } { - err := tt.IterateObjects(func(_ string, _ Object) error { return nil }) + err := tt.IterateObjects("", func(_ string, _ Object) error { return nil }) assert.Error(t, err, string(tt)) } }) diff --git a/modules/storage/local.go b/modules/storage/local.go index 05bf1fb28a56..15f5761e8f05 100644 --- a/modules/storage/local.go +++ b/modules/storage/local.go @@ -127,8 +127,12 @@ func (l *LocalStorage) URL(path, name string) (*url.URL, error) { } // IterateObjects iterates across the objects in the local storage -func (l *LocalStorage) IterateObjects(fn func(path string, obj Object) error) error { - return filepath.WalkDir(l.dir, func(path string, d os.DirEntry, err error) error { +func (l *LocalStorage) IterateObjects(prefix string, fn func(path string, obj Object) error) error { + dir := l.dir + if prefix != "" { + dir = filepath.Join(l.dir, util.CleanPath(prefix)) + } + return filepath.WalkDir(dir, func(path string, d os.DirEntry, err error) error { if err != nil { return err } diff --git a/modules/storage/local_test.go b/modules/storage/local_test.go index 994c54e8590d..2b112df8f12b 100644 --- a/modules/storage/local_test.go +++ b/modules/storage/local_test.go @@ -4,6 +4,10 @@ package storage import ( + "bytes" + "context" + "os" + "path/filepath" "testing" "github.com/stretchr/testify/assert" @@ -50,3 +54,41 @@ func TestBuildLocalPath(t *testing.T) { }) } } + +func TestLocalStorageIterator(t *testing.T) { + dir := filepath.Join(os.TempDir(), "TestLocalStorageIteratorTestDir") + l, err := NewLocalStorage(context.Background(), LocalStorageConfig{Path: dir}) + assert.NoError(t, err) + + testFiles := [][]string{ + {"a/1.txt", "a1"}, + {"/a/1.txt", "aa1"}, // same as above, but with leading slash that will be trim + {"b/1.txt", "b1"}, + {"b/2.txt", "b2"}, + {"b/3.txt", "b3"}, + {"b/x 4.txt", "bx4"}, + } + for _, f := range testFiles { + _, err = l.Save(f[0], bytes.NewBufferString(f[1]), -1) + assert.NoError(t, err) + } + + expectedList := map[string][]string{ + "a": {"a/1.txt"}, + "b": {"b/1.txt", "b/2.txt", "b/3.txt", "b/x 4.txt"}, + "": {"a/1.txt", "b/1.txt", "b/2.txt", "b/3.txt", "b/x 4.txt"}, + "/": {"a/1.txt", "b/1.txt", "b/2.txt", "b/3.txt", "b/x 4.txt"}, + "a/b/../../a": {"a/1.txt"}, + } + for dir, expected := range expectedList { + count := 0 + err = l.IterateObjects(dir, func(path string, f Object) error { + defer f.Close() + assert.Contains(t, expected, path) + count++ + return nil + }) + assert.NoError(t, err) + assert.Equal(t, count, len(expected)) + } +} diff --git a/modules/storage/minio.go b/modules/storage/minio.go index 24da14b63463..8cc06bcdd3df 100644 --- a/modules/storage/minio.go +++ b/modules/storage/minio.go @@ -209,12 +209,18 @@ func (m *MinioStorage) URL(path, name string) (*url.URL, error) { } // IterateObjects iterates across the objects in the miniostorage -func (m *MinioStorage) IterateObjects(fn func(path string, obj Object) error) error { +func (m *MinioStorage) IterateObjects(prefix string, fn func(path string, obj Object) error) error { opts := minio.GetObjectOptions{} lobjectCtx, cancel := context.WithCancel(m.ctx) defer cancel() + + basePath := m.basePath + if prefix != "" { + basePath = m.buildMinioPath(prefix) + } + for mObjInfo := range m.client.ListObjects(lobjectCtx, m.bucket, minio.ListObjectsOptions{ - Prefix: m.basePath, + Prefix: basePath, Recursive: true, }) { object, err := m.client.GetObject(lobjectCtx, m.bucket, mObjInfo.Key, opts) @@ -223,7 +229,7 @@ func (m *MinioStorage) IterateObjects(fn func(path string, obj Object) error) er } if err := func(object *minio.Object, fn func(path string, obj Object) error) error { defer object.Close() - return fn(strings.TrimPrefix(mObjInfo.Key, m.basePath), &minioObject{object}) + return fn(strings.TrimPrefix(mObjInfo.Key, basePath), &minioObject{object}) }(object, fn); err != nil { return convertMinioErr(err) } diff --git a/modules/storage/storage.go b/modules/storage/storage.go index d8998b19225f..caecab306e63 100644 --- a/modules/storage/storage.go +++ b/modules/storage/storage.go @@ -65,7 +65,7 @@ type ObjectStorage interface { Stat(path string) (os.FileInfo, error) Delete(path string) error URL(path, name string) (*url.URL, error) - IterateObjects(func(path string, obj Object) error) error + IterateObjects(path string, iterator func(path string, obj Object) error) error } // Copy copies a file from source ObjectStorage to dest ObjectStorage @@ -87,7 +87,7 @@ func Copy(dstStorage ObjectStorage, dstPath string, srcStorage ObjectStorage, sr // Clean delete all the objects in this storage func Clean(storage ObjectStorage) error { - return storage.IterateObjects(func(path string, obj Object) error { + return storage.IterateObjects("", func(path string, obj Object) error { _ = obj.Close() return storage.Delete(path) }) diff --git a/modules/structs/user.go b/modules/structs/user.go index c5e96f335690..f68b92ac069e 100644 --- a/modules/structs/user.go +++ b/modules/structs/user.go @@ -93,3 +93,12 @@ type UserSettingsOptions struct { HideEmail *bool `json:"hide_email"` HideActivity *bool `json:"hide_activity"` } + +// RenameUserOption options when renaming a user +type RenameUserOption struct { + // New username for this user. This name cannot be in use yet by any other user. + // + // required: true + // unique: true + NewName string `json:"new_username" binding:"Required"` +} diff --git a/modules/structs/user_email.go b/modules/structs/user_email.go index 6a11e040afb3..9319667e8fca 100644 --- a/modules/structs/user_email.go +++ b/modules/structs/user_email.go @@ -1,4 +1,5 @@ // Copyright 2015 The Gogs Authors. All rights reserved. +// Copyright 2023 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT package structs @@ -9,6 +10,8 @@ type Email struct { Email string `json:"email"` Verified bool `json:"verified"` Primary bool `json:"primary"` + UserID int64 `json:"user_id"` + UserName string `json:"username"` } // CreateEmailOption options when creating email addresses diff --git a/options/locale/locale_cs-CZ.ini b/options/locale/locale_cs-CZ.ini index 543cd44045de..258267fac1e7 100644 --- a/options/locale/locale_cs-CZ.ini +++ b/options/locale/locale_cs-CZ.ini @@ -3269,6 +3269,7 @@ rubygems.dependencies.development=Vývojové závislosti rubygems.required.ruby=Vyžaduje verzi Ruby rubygems.required.rubygems=Vyžaduje verzi RubyGem rubygems.documentation=Další informace o registru RubyGems naleznete v dokumentaci. +swift.registry=Nastavte tento registr z příkazového řádku: vagrant.install=Pro přidání Vagrant box spusťte následující příkaz: vagrant.documentation=Další informace o registru Vagrant naleznete v dokumentaci. settings.link=Propojit tento balíček s repozitářem diff --git a/options/locale/locale_de-DE.ini b/options/locale/locale_de-DE.ini index 9bee2104e4d6..d195fe206cd8 100644 --- a/options/locale/locale_de-DE.ini +++ b/options/locale/locale_de-DE.ini @@ -3122,6 +3122,7 @@ rubygems.dependencies.development=Entwicklungsabhängigkeiten rubygems.required.ruby=Benötigt Ruby Version rubygems.required.rubygems=Benötigt RubyGem Version rubygems.documentation=Weitere Informationen zur RubyGems-Paketverwaltung findest du in der Dokumentation. +swift.registry=Diese Registry über die Kommandozeile einrichten: vagrant.install=Um eine Vagrant-Box hinzuzufügen, führen Sie folgenden Befehl aus: vagrant.documentation=Für weitere Informationen zur Vagrant-Registry, siehe Dokumentation. settings.link=Dieses Paket einem Repository zuweisen diff --git a/options/locale/locale_el-GR.ini b/options/locale/locale_el-GR.ini index 6affdf7e8be7..5fd330fa841f 100644 --- a/options/locale/locale_el-GR.ini +++ b/options/locale/locale_el-GR.ini @@ -3155,6 +3155,7 @@ rubygems.dependencies.development=Εξαρτήσεις Ανάπτυξης rubygems.required.ruby=Απαιτεί την έκδοση Ruby rubygems.required.rubygems=Απαιτεί έκδοση RubyGem rubygems.documentation=Για περισσότερες πληροφορίες σχετικά με το μητρώο RubyGems, ανατρέξτε στην τεκμηρίωση. +swift.registry=Ρυθμίστε αυτό το μητρώο από τη γραμμή εντολών: vagrant.install=Για προσθήκη ενός κυτίου Vagrant, εκτελέστε την ακόλουθη εντολή: vagrant.documentation=Για περισσότερες πληροφορίες σχετικά με το μητρώο του Vagrant, ανατρέξτε στην τεκμηρίωση. settings.link=Σύνδεση αυτού του πακέτου με ένα αποθετήριο diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index dccf184335b2..afcf9ade04da 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -2934,6 +2934,8 @@ config.git_disable_diff_highlight = Disable Diff Syntax Highlight config.git_max_diff_lines = Max Diff Lines (for a single file) config.git_max_diff_line_characters = Max Diff Characters (for a single line) config.git_max_diff_files = Max Diff Files (to be shown) +config.git_enable_reflogs = Enable Reflogs +config.git_reflog_expiry_time = Expiry Time config.git_gc_args = GC Arguments config.git_migrate_timeout = Migration Timeout config.git_mirror_timeout = Mirror Update Timeout @@ -3237,6 +3239,10 @@ rubygems.dependencies.development = Development Dependencies rubygems.required.ruby = Requires Ruby version rubygems.required.rubygems = Requires RubyGem version rubygems.documentation = For more information on the RubyGems registry, see the documentation. +swift.registry = Setup this registry from the command line: +swift.install = Add the package in your Package.swift file: +swift.install2 = and run the following command: +swift.documentation = For more information on the Swift registry, see the documentation. vagrant.install = To add a Vagrant box, run the following command: vagrant.documentation = For more information on the Vagrant registry, see the documentation. settings.link = Link this package to a repository @@ -3354,5 +3360,7 @@ runs.open_tab = %d Open runs.closed_tab = %d Closed runs.commit = Commit runs.pushed_by = Pushed by +runs.valid_workflow_helper = Workflow config file is valid. +runs.invalid_workflow_helper = Workflow config file is invalid. Please check your config file: %s need_approval_desc = Need approval to run workflows for fork pull request. diff --git a/options/locale/locale_es-ES.ini b/options/locale/locale_es-ES.ini index f104d3c49d30..f67eb7ee9f98 100644 --- a/options/locale/locale_es-ES.ini +++ b/options/locale/locale_es-ES.ini @@ -3154,6 +3154,7 @@ rubygems.dependencies.development=Dependencias de desarrollo rubygems.required.ruby=Requiere versión Ruby rubygems.required.rubygems=Requiere la versión de RubyGem rubygems.documentation=Para obtener más información sobre el registro de RubyGems, consulte la documentación. +swift.registry=Configurar este registro desde la línea de comandos: vagrant.install=Para añadir un paquete Vagrant, ejecuta el siguiente comando: vagrant.documentation=Para más información sobre el registro de paquetes Vagrant, revisa la documentación. settings.link=Vincular este paquete a un repositorio diff --git a/options/locale/locale_it-IT.ini b/options/locale/locale_it-IT.ini index d77baee6e502..a4dfa501c5be 100644 --- a/options/locale/locale_it-IT.ini +++ b/options/locale/locale_it-IT.ini @@ -3121,6 +3121,7 @@ rubygems.dependencies.development=Dipendenze Di Sviluppo rubygems.required.ruby=Richiede la versione di Ruby rubygems.required.rubygems=Richiede la versione RubyGem rubygems.documentation=Per ulteriori informazioni sul registro di RubyGems, vedere la documentazione. +swift.registry=Configura questo registro dalla riga di comando: settings.link=Collega questo pacchetto a un repository settings.link.description=Se si collega un pacchetto a un repository, il pacchetto è elencato nell'elenco dei pacchetti del repository. settings.link.select=Seleziona Repository diff --git a/options/locale/locale_ja-JP.ini b/options/locale/locale_ja-JP.ini index 8e77329f5cc9..c0ff33b1e7eb 100644 --- a/options/locale/locale_ja-JP.ini +++ b/options/locale/locale_ja-JP.ini @@ -3232,6 +3232,7 @@ rubygems.dependencies.development=開発用依存関係 rubygems.required.ruby=必要なRubyバージョン rubygems.required.rubygems=必要なRubyGemバージョン rubygems.documentation=RubyGemsレジストリの詳細については、ドキュメント を参照してください。 +swift.registry=このレジストリをコマンドラインからセットアップします: vagrant.install=Vagrant ボックスを追加するには、次のコマンドを実行します。 vagrant.documentation=Vagrantレジストリの詳細については ドキュメントを参照してください。 settings.link=このパッケージをリポジトリにリンク diff --git a/options/locale/locale_lv-LV.ini b/options/locale/locale_lv-LV.ini index 0f7862f8a3de..2172c23f2152 100644 --- a/options/locale/locale_lv-LV.ini +++ b/options/locale/locale_lv-LV.ini @@ -3329,6 +3329,7 @@ rubygems.dependencies.development=Izstrādes atkarības rubygems.required.ruby=Nepieciešamā Ruby versija rubygems.required.rubygems=Nepieciešamā RubyGem versija rubygems.documentation=Papildus informācija par RubyGems reģistru pieejama dokumentācijā. +swift.registry=Konfigurējiet šo reģistru no komandrindas: vagrant.install=Lai pievienotu Vagrant kasti, izpildiet sekojošu komandu: vagrant.documentation=Papildus informācija par Vagrant reģistru pieejama dokumentācijā. settings.link=Piesaistīt pakotni šim repozitorijam diff --git a/options/locale/locale_pt-BR.ini b/options/locale/locale_pt-BR.ini index 55529df8829a..5ec3e084bf7f 100644 --- a/options/locale/locale_pt-BR.ini +++ b/options/locale/locale_pt-BR.ini @@ -247,6 +247,7 @@ default_enable_timetracking_popup=Habilitar o cronômetro para novos repositóri no_reply_address=Domínio de e-mail oculto no_reply_address_helper=Nome de domínio para usuários com um endereço de e-mail oculto. Por exemplo, o nome de usuário 'joe' será registrado no Git como 'joe@noreply.example.org' se o domínio de e-mail oculto estiver definido como 'noreply.example.org'. password_algorithm=Algoritmo Hash de Senha +invalid_password_algorithm=Algoritmo de hash de senha inválido password_algorithm_helper=Escolha o algoritmo de hash para as senhas. Diferentes algoritmos têm requerimentos e forças diversos. O `Argon2` possui boa qualidade, porém usa muita memória e pode ser inapropriado para sistemas com menos recursos. enable_update_checker=Habilitar Verificador de Atualizações enable_update_checker_helper=Procura por novas versões periodicamente conectando-se ao gitea.io. @@ -284,6 +285,7 @@ users=Usuários organizations=Organizações search=Pesquisar code=Código +search.type.tooltip=Tipo de pesquisa search.fuzzy=Similar search.fuzzy.tooltip=Incluir resultados que sejam próximos ao termo de busca search.match=Correspondência @@ -819,6 +821,7 @@ remove_account_link=Remover conta vinculada remove_account_link_desc=A exclusão da chave SSH revogará o acesso à sua conta. Continuar? remove_account_link_success=A conta vinculada foi removida. +hooks.desc=Adicionar webhooks que serão acionados para todos os repositórios pertencentes a este usuário. orgs_none=Você não é membro de nenhuma organização. repos_none=Você não possui nenhum repositório @@ -1231,6 +1234,7 @@ projects.column.color=Colorido projects.open=Abrir projects.close=Fechar projects.column.assigned_to=Atribuído a +projects.card_type.desc=Pré-visualizações de Cards projects.card_type.images_and_text=Imagens e Texto projects.card_type.text_only=Somente texto @@ -1399,6 +1403,7 @@ issues.label_title=Nome da etiqueta issues.label_description=Descrição da etiqueta issues.label_color=Cor da etiqueta issues.label_exclusive=Exclusivo +issues.label_exclusive_desc=Nomeie o rótulo escopo/item para torná-lo mutuamente exclusivo com outros rótulos do escopo/. issues.label_exclusive_warning=Quaisquer rótulos com escopo conflitantes serão removidos ao editar os rótulos de uma issue ou pull request. issues.label_count=%d etiquetas issues.label_open_issues=%d issues abertas @@ -1655,6 +1660,7 @@ pulls.merge_instruction_hint=`Você também pode ver as *, eventos para todos os branches serão relatados. Veja github.com/gobwas/glob documentação da sintaxe. Exemplos: master, {master,release*}. settings.authorization_header=Header de Autorização +settings.authorization_header_desc=Será incluído como header de autorização para solicitações quando estiver presente. Exemplos: %s. settings.active=Ativo settings.active_helper=Informações sobre eventos disparados serão enviadas para esta URL do webhook. settings.add_hook_success=O webhook foi adicionado. @@ -2124,6 +2132,7 @@ settings.dismiss_stale_approvals=Descartar aprovações obsoletas settings.dismiss_stale_approvals_desc=Quando novos commits que mudam o conteúdo do pull request são enviados para o branch, as antigas aprovações serão descartadas. settings.require_signed_commits=Exibir commits assinados settings.require_signed_commits_desc=Rejeitar pushes para este branch se não estiverem assinados ou não forem validáveis. +settings.protect_branch_name_pattern=Padrão de Nome de Branch Protegida settings.protect_protected_file_patterns=Padrões de arquivos protegidos (separados usando ponto e vírgula '\;'): settings.protect_protected_file_patterns_desc=Arquivos protegidos que não têm permissão para serem alterados diretamente, mesmo se o usuário tiver permissão para adicionar, editar ou apagar arquivos neste branch. Vários padrões podem ser separados usando ponto e vírgula ('\;'). Veja github.com/gobwas/glob documentação para sintaxe de padrões. Exemplos: .drone.yml, /docs/**/*.txt. settings.protect_unprotected_file_patterns=Padrões de arquivos desprotegidos (separados usando ponto e vírgula '\;'): @@ -2132,6 +2141,7 @@ settings.add_protected_branch=Habilitar proteção settings.delete_protected_branch=Desabilitar proteção settings.update_protect_branch_success=Proteção do branch '%s' foi atualizada. settings.remove_protected_branch_success=Proteção do branch '%s' foi desabilitada. +settings.remove_protected_branch_failed=Removendo regra de proteção de branch '%s' falhou. settings.protected_branch_deletion=Desabilitar proteção de branch settings.protected_branch_deletion_desc=Desabilitar a proteção de branch permite que os usuários com permissão de escrita realizem push. Continuar? settings.block_rejected_reviews=Bloquear merge em revisões rejeitadas @@ -2146,6 +2156,8 @@ settings.default_merge_style_desc=Estilo de merge padrão para pull requests: settings.choose_branch=Escolha um branch... settings.no_protected_branch=Não há branches protegidos. settings.edit_protected_branch=Editar +settings.protected_branch_required_rule_name=Nome da regra é obrigatório +settings.protected_branch_duplicate_rule_name=Regra com nome duplicado settings.protected_branch_required_approvals_min=Aprovações necessárias não podem ser negativas. settings.tags=Tags settings.tags.protection=Proteção das Tags @@ -2278,6 +2290,8 @@ release.edit_subheader=Lançamentos organizam versões do projeto. release.tag_name=Nome da tag release.target=Destino release.tag_helper=Escolha uma tag existente, ou crie uma nova tag. +release.tag_helper_new=Nova tag. Esta tag será criada a partir do alvo. +release.tag_helper_existing=Tag existente. release.title=Título release.content=Conteúdo release.prerelease_desc=Marcar como pré-lançamento @@ -2570,6 +2584,10 @@ dashboard.delete_old_actions=Excluir todas as ações antigas do banco de dados dashboard.delete_old_actions.started=A exclusão de todas as ações antigas do banco de dados foi iniciada. dashboard.update_checker=Verificador de atualização dashboard.delete_old_system_notices=Excluir todos os avisos de sistema antigos do banco de dados +dashboard.gc_lfs=Coletar lixos dos meta-objetos LFS +dashboard.stop_zombie_tasks=Parar tarefas zumbi +dashboard.stop_endless_tasks=Parar tarefas infinitas +dashboard.cancel_abandoned_jobs=Cancelar trabalhos abandonados users.user_manage_panel=Gerenciamento de conta de usuário users.new_account=Criar conta de usuário @@ -2658,6 +2676,7 @@ repos.size=Tamanho packages.package_manage_panel=Gerenciamento de Pacotes packages.total_size=Tamanho Total: %s +packages.unreferenced_size=Tamanho Não Referenciado: %s packages.owner=Proprietário packages.creator=Criador packages.name=Nome @@ -2751,6 +2770,8 @@ auths.oauth2_required_claim_value_helper=Defina este valor para permitir o login auths.oauth2_group_claim_name=Nome do claim que fornece os nomes dos grupos para esta fonte. (Opcional) auths.oauth2_admin_group=Valor do Claim de Grupo para os usuários administradores. (Opcional - requer nome do claim acima) auths.oauth2_restricted_group=Valor do Claim de Grupo para os usuários restritos. (Opcional - requer nome do claim acima) +auths.oauth2_map_group_to_team=Mapear grupos para Organizações. (Opcional - requer nome do claim acima) +auths.oauth2_map_group_to_team_removal=Remover usuários de equipes sincronizadas se o usuário não pertence ao grupo correspondente. auths.enable_auto_register=Habilitar cadastro automático auths.sspi_auto_create_users=Criar usuários automaticamente auths.sspi_auto_create_users_helper=Permitir que o método de autenticação SSPI crie automaticamente novas contas para usuários que fazem o login pela primeira vez @@ -2791,6 +2812,8 @@ auths.still_in_used=A fonte de autenticação ainda está em uso. Converta ou ex auths.deletion_success=A fonte de autenticação foi excluída. auths.login_source_exist=A fonte de autenticação '%s' já existe. auths.login_source_of_type_exist=Uma fonte de autenticação deste tipo já existe. +auths.unable_to_initialize_openid=Não é possível inicializar o Provedor OpenID Connect: %s +auths.invalid_openIdConnectAutoDiscoveryURL=URL do Auto Discovery inválida (deve ser uma URL válida, começando com http:// ou https://) config.server_config=Configuração do servidor config.app_name=Nome do servidor @@ -3039,6 +3062,7 @@ reopen_pull_request=`reabriu o pull request %[3]s#%[2]s` comment_issue=`comentou na issue %[3]s#%[2]s` comment_pull=`comentou no pull request %[3]s#%[2]s` merge_pull_request=`fez merge do pull request %[3]s#%[2]s` +auto_merge_pull_request=`fez merge automático do pull request %[3]s#%[2]s` transfer_repo=transferiu repositório de %s para %s push_tag=fez push da tag %[3]s to %[4]s delete_tag=excluiu tag %[2]s de %[3]s @@ -3148,10 +3172,12 @@ dependency.id=ID dependency.version=Versão cargo.registry=Configurar este registro no arquivo de configuração de Cargo (por exemplo ~/.cargo/config.toml): cargo.install=Para instalar o pacote usando Cargo, execute o seguinte comando: +cargo.documentation=Para obter mais informações sobre o registro Cargo, consulte a documentação. cargo.details.repository_site=Site do Repositório cargo.details.documentation_site=Site da Documentação chef.registry=Configure este registro em seu arquivo ~/.chef/config.rb: chef.install=Para instalar o pacote, execute o seguinte comando: +chef.documentation=Para obter mais informações sobre o registro Chef, consulte a documentação. composer.registry=Configure este registro em seu arquivo ~/.composer/config.json: composer.install=Para instalar o pacote usando o Composer, execute o seguinte comando: composer.documentation=Para obter mais informações sobre o registro do Composer, consulte a documentação. @@ -3211,6 +3237,7 @@ rubygems.dependencies.development=Dependências de Desenvolvimento rubygems.required.ruby=Requer o Ruby versão rubygems.required.rubygems=Requer o RubyGem versão rubygems.documentation=Para obter mais informações sobre o registro do RubyGems, consulte a documentação. +swift.registry=Configure este registro pela linha de comando: vagrant.install=Para adicionar uma Vagrant box, execute o seguinte comando: vagrant.documentation=Para obter mais informações sobre o registro do Vagrant, consulte a documentação. settings.link=Vincular este pacote a um repositório @@ -3224,6 +3251,15 @@ settings.delete.description=A exclusão de um pacote é permanente e não pode s settings.delete.notice=Você está prestes a excluir %s (%s). Esta operação é irreversível, tem certeza? settings.delete.success=O pacote foi excluído. settings.delete.error=Falha ao excluir o pacote. +owner.settings.cargo.title=Índice do Registro Cargo +owner.settings.cargo.initialize=Iniciar Índice +owner.settings.cargo.initialize.description=Para usar o registro Cargo é necessário um repositório git especial. Aqui você pode (re)criá-lo com a configuração necessária. +owner.settings.cargo.initialize.error=Falha ao inicializar índice Cargo: %v +owner.settings.cargo.initialize.success=O índice Cargo foi criado com sucesso. +owner.settings.cargo.rebuild=Reconstruir Índice +owner.settings.cargo.rebuild.description=Se o índice está fora de sincronia com os pacotes Cargo, você pode reconstruí-lo aqui. +owner.settings.cargo.rebuild.error=Falha ao reconstruir índice Cargo: %v +owner.settings.cargo.rebuild.success=O índice Cargo foi reconstruído com sucesso. owner.settings.cleanuprules.title=Gerenciar Regras de Limpeza owner.settings.cleanuprules.add=Adicionar Regra de Limpeza owner.settings.cleanuprules.edit=Editar Regra de Limpeza @@ -3232,6 +3268,7 @@ owner.settings.cleanuprules.preview=Pré-visualizar Regra de Limpeza owner.settings.cleanuprules.preview.overview=%d pacotes agendados para serem removidos. owner.settings.cleanuprules.preview.none=A regra de limpeza não corresponde a nenhum pacote. owner.settings.cleanuprules.enabled=Habilitado +owner.settings.cleanuprules.pattern_full_match=Aplicar padrão ao nome completo do pacote owner.settings.cleanuprules.keep.title=Versões que correspondem a estas regras são mantidas, mesmo se corresponderem a uma regra de remoção abaixo. owner.settings.cleanuprules.keep.count=Manter o mais recente owner.settings.cleanuprules.keep.count.1=1 versão por pacote @@ -3245,6 +3282,7 @@ owner.settings.cleanuprules.success.update=Regra de limpeza foi atualizada. owner.settings.cleanuprules.success.delete=Regra de limpeza foi excluída. owner.settings.chef.title=Registro Chef owner.settings.chef.keypair=Gerar par de chaves +owner.settings.chef.keypair.description=Gerar um par de chaves usado para autenticar no registro Chef. A chave anterior não pode ser usada depois. [secrets] secrets=Segredos @@ -3253,6 +3291,8 @@ none=Não há segredos ainda. value=Valor name=Nome creation=Adicionar Segredo +creation.name_placeholder=apenas caracteres alfanuméricos ou underline (_), não pode começar com GITEA_ ou GITHUB_ +creation.value_placeholder=Insira qualquer conteúdo. Espaços em branco no início e no fim serão omitidos. creation.success=O segredo '%s' foi adicionado. creation.failed=Falha ao adicionar segredo. deletion=Excluir segredo @@ -3274,6 +3314,10 @@ status.cancelled=Cancelado status.skipped=Ignorado status.blocked=Bloqueado +runners=Runners +runners.runner_manage_panel=Gerenciamento de Runners +runners.new=Criar novo Runner +runners.new_notice=Como iniciar um runner runners.status=Status runners.id=ID runners.name=Nome @@ -3281,21 +3325,36 @@ runners.owner_type=Tipo runners.description=Descrição runners.labels=Rótulos runners.last_online=Última Vez Online +runners.agent_labels=Etiquetas do Agente runners.custom_labels=Etiquetas Personalizadas runners.custom_labels_helper=Etiquetas personalizadas são etiquetas que são adicionadas manualmente por um administrador. Separe as etiquetas com vírgula. Espaço em branco no começo ou no final de cada etiqueta é ignorado. +runners.runner_title=Runner +runners.task_list=Tarefas recentes neste runner runners.task_list.run=Executar runners.task_list.status=Status runners.task_list.repository=Repositório runners.task_list.commit=Commit +runners.task_list.done_at=Feito em +runners.edit_runner=Editar Runner runners.update_runner=Atualizar as Alterações +runners.update_runner_success=Runner atualizado com sucesso +runners.update_runner_failed=Falha ao atualizar runner +runners.delete_runner=Deletar esse runner +runners.delete_runner_success=Runner excluído com sucesso +runners.delete_runner_failed=Falha ao excluir runner +runners.delete_runner_header=Confirme para excluir este runner +runners.delete_runner_notice=Se uma tarefa estiver sendo executada neste runner, ela será encerrada e marcada como falha. Pode quebrar o workflow de construção. +runners.none=Nenhum runner disponível runners.status.unspecified=Desconhecido runners.status.idle=Inativo runners.status.active=Ativo runners.status.offline=Offiline +runs.all_workflows=Todos os Workflows runs.open_tab=%d Aberto runs.closed_tab=%d Fechado runs.commit=Commit runs.pushed_by=Push realizado por +need_approval_desc=Precisa de aprovação para executar workflowa para pull request do fork. diff --git a/options/locale/locale_pt-PT.ini b/options/locale/locale_pt-PT.ini index ef7a400ec8b8..ee36a0f4e64c 100644 --- a/options/locale/locale_pt-PT.ini +++ b/options/locale/locale_pt-PT.ini @@ -1357,8 +1357,8 @@ issues.opened_by_fake=%[1]s aberta(s) por %[2]s issues.closed_by_fake=por %[2]s foi fechada %[1]s issues.previous=Anterior issues.next=Seguinte -issues.open_title=Aberta -issues.closed_title=Fechada +issues.open_title=aberta(s) +issues.closed_title=fechada(s) issues.draft_title=Rascunho issues.num_comments=%d comentários issues.commented_at=`comentou %s` @@ -1780,7 +1780,7 @@ activity.title.issues_1=%d questão activity.title.issues_n=%d questões activity.title.issues_closed_from=%s resolvida(s) de %s activity.title.issues_created_by=%s criada por %s -activity.closed_issue_label=Encerrada +activity.closed_issue_label=Fechada activity.new_issues_count_1=questão nova activity.new_issues_count_n=questões novas activity.new_issue_label=Em aberto @@ -2934,6 +2934,8 @@ config.git_disable_diff_highlight=Desabilitar o realce de sintaxe no diff config.git_max_diff_lines=Número máximo de linhas diff (por ficheiro) config.git_max_diff_line_characters=Número máximos de caracteres diff (por linha) config.git_max_diff_files=Número máximo de ficheiros diff a serem apresentados +config.git_enable_reflogs=Habilitar reflogs +config.git_reflog_expiry_time=Tempo de expiração config.git_gc_args=Argumentos da recolha de lixo config.git_migrate_timeout=Prazo da migração config.git_mirror_timeout=Prazo para sincronização da réplica @@ -3237,6 +3239,10 @@ rubygems.dependencies.development=Dependências de desenvolvimento rubygems.required.ruby=Requer a versão do Ruby rubygems.required.rubygems=Requer a versão do RubyGem rubygems.documentation=Para obter mais informações sobre o registo do RubyGems, consulte a documentação. +swift.registry=Configurar este registo usando a linha de comandos: +swift.install=Adicione o pacote no seu ficheiro Package.swift: +swift.install2=e execute o seguinte comando: +swift.documentation=Para obter mais informações sobre o registo do Swift, consulte a documentação. vagrant.install=Para adicionar uma máquina virtual Vagrant, execute o seguinte comando: vagrant.documentation=Para obter mais informações sobre o registo do Vagrant, consulte a documentação. settings.link=Vincular este pacote a um repositório diff --git a/options/locale/locale_tr-TR.ini b/options/locale/locale_tr-TR.ini index 131dfa69af19..ae5b42c7d834 100644 --- a/options/locale/locale_tr-TR.ini +++ b/options/locale/locale_tr-TR.ini @@ -57,6 +57,7 @@ new_mirror=Yeni Yansı new_fork=Yeni Depo Çatalı new_org=Yeni Organizasyon new_project=Yeni Proje +new_project_column=Yeni Sütun manage_org=Organizasyonları Yönet admin_panel=Site Yönetimi account_settings=Hesap Ayarları @@ -90,9 +91,11 @@ disabled=Devre Dışı copy=Kopyala copy_url=URL'yi kopyala +copy_content=İçeriği kopyala copy_branch=Dal adını kopyala copy_success=Kopyalandı! copy_error=Kopyalama başarısız oldu +copy_type_unsupported=Bu dosya türü kopyalanamaz write=Yaz preview=Önizleme @@ -109,6 +112,10 @@ never=Asla rss_feed=RSS Beslemesi [aria] +navbar=Gezinti Çubuğu +footer=Alt Bilgi +footer.software=Yazılım Hakkında +footer.links=Bağlantılar [filter] string.asc=A - Z @@ -240,7 +247,10 @@ default_enable_timetracking_popup=Yeni depolar için zaman takibini varsayılan no_reply_address=Gizlenecek E-Posta Alan Adı no_reply_address_helper=Gizlenmiş e-posta adresine sahip kullanıcılar için alan adı. Örneğin 'ali' kullanıcı adı, gizlenmiş e-postalar için alan adı 'yanityok.ornek.org' olarak ayarlandığında Git günlüğüne 'ali@yanityok.ornek.org' olarak kaydedilecektir. password_algorithm=Parola Hash Algoritması +invalid_password_algorithm=Hatalı parola hash algoritması password_algorithm_helper=Parola için hash algoritmasını ayarlayın. Algoritmalar değişen gereksinimlere ve güce sahiptirler. `argon2` iyi özelliklere sahip olmasına rağmen fazla miktarda bellek kullanır ve küçük sistemler için uygun olmayabilir. +enable_update_checker=Güncelleme Denetleyicisini Etkinleştir +enable_update_checker_helper=Düzenli olarak gitea.io'ya bağlanarak yeni yayınlanan sürümleri denetler. [home] uname_holder=Kullanıcı Adı veya E-Posta Adresi @@ -290,14 +300,36 @@ code_last_indexed_at=Son endekslenen %s relevant_repositories_tooltip=Çatal olan veya konusu, simgesi veya açıklaması olmayan depolar gizlenmiştir. relevant_repositories=`Sadece ilişkili depolar gösteriliyor, belgeye bakabilirsiniz. +swift.registry=Bu kütüğü komut satırını kullanarak kurun: vagrant.install=Vagrant paketi eklemek için aşağıdaki komutu çalıştırın: vagrant.documentation=Vagrant kütüğü hakkında daha fazla bilgi için, belgeye bakabilirsiniz. settings.link=Bu paketi bir depoya bağlayın diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index aa4cc4dde974..21836963f1ce 100644 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -3232,6 +3232,7 @@ rubygems.dependencies.development=开发依赖 rubygems.required.ruby=需要 Ruby 版本 rubygems.required.rubygems=需要 RubyGem 版本 rubygems.documentation=关于 RubyGems 注册中心的更多信息,请参阅 文档。 +swift.registry=从命令行设置此注册中心: vagrant.install=若要添加一个 Vagrant box,请运行以下命令: vagrant.documentation=关于 Vagrant 注册中心的更多信息,请参阅 文档。 settings.link=将此软件包链接到仓库 diff --git a/options/locale/locale_zh-TW.ini b/options/locale/locale_zh-TW.ini index e98e55b77700..5ef7b96dee48 100644 --- a/options/locale/locale_zh-TW.ini +++ b/options/locale/locale_zh-TW.ini @@ -3232,6 +3232,7 @@ rubygems.dependencies.development=開發相依性 rubygems.required.ruby=需要的 Ruby 版本 rubygems.required.rubygems=需要的 RubyGem 版本 rubygems.documentation=關於 RubyGems registry 的詳情請參閱說明文件。 +swift.registry=透過下列命令設定此註冊中心: vagrant.install=執行下列命令以新增 Vagrant box: vagrant.documentation=關於 Vagrant registry 的詳情請參閱說明文件。 settings.link=連結此套件到儲存庫 diff --git a/package-lock.json b/package-lock.json index 7ec6d09d1996..815b58c344e6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,8 +28,6 @@ "jquery": "3.6.3", "jquery.are-you-sure": "1.9.0", "katex": "0.16.4", - "less": "4.1.3", - "less-loader": "11.1.0", "license-checker-webpack-plugin": "0.2.1", "mermaid": "10.0.2", "mini-css-extract-plugin": "2.7.2", @@ -45,7 +43,7 @@ "vue-bar-graph": "2.0.0", "vue-loader": "17.0.1", "vue3-calendar-heatmap": "2.0.0", - "webpack": "5.75.0", + "webpack": "5.76.0", "webpack-cli": "5.0.1", "workbox-routing": "6.5.4", "workbox-strategies": "6.5.4", @@ -64,7 +62,6 @@ "eslint-plugin-vue": "9.9.0", "jsdom": "21.0.0", "markdownlint-cli": "0.33.0", - "postcss-less": "6.0.0", "stylelint": "15.2.0", "stylelint-declaration-strict-value": "1.9.2", "svgo": "3.0.2", @@ -2667,6 +2664,9 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", + "dev": true, + "optional": true, + "peer": true, "dependencies": { "is-what": "^3.14.1" }, @@ -3813,7 +3813,9 @@ "version": "0.1.8", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, "optional": true, + "peer": true, "dependencies": { "prr": "~1.0.1" }, @@ -5240,7 +5242,9 @@ "version": "0.5.5", "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", + "dev": true, "optional": true, + "peer": true, "bin": { "image-size": "bin/image-size.js" }, @@ -5675,7 +5679,10 @@ "node_modules/is-what": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", - "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==" + "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", + "dev": true, + "optional": true, + "peer": true }, "node_modules/isarray": { "version": "0.0.1", @@ -5933,14 +5940,6 @@ "node": ">=0.10.0" } }, - "node_modules/klona": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", - "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", - "engines": { - "node": ">= 8" - } - }, "node_modules/known-css-properties": { "version": "0.26.0", "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.26.0.tgz", @@ -5956,6 +5955,9 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/less/-/less-4.1.3.tgz", "integrity": "sha512-w16Xk/Ta9Hhyei0Gpz9m7VS8F28nieJaL/VyShID7cYvP6IL5oHeL6p4TXSDJqZE/lNv0oJ2pGVjJsRkfwm5FA==", + "dev": true, + "optional": true, + "peer": true, "dependencies": { "copy-anything": "^2.0.1", "parse-node-version": "^1.0.1", @@ -5977,25 +5979,6 @@ "source-map": "~0.6.0" } }, - "node_modules/less-loader": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-11.1.0.tgz", - "integrity": "sha512-C+uDBV7kS7W5fJlUjq5mPBeBVhYpTIm5gB09APT9o3n/ILeaXVsiSFTbZpTJCJwQ/Crczfn3DmfQFwxYusWFug==", - "dependencies": { - "klona": "^2.0.4" - }, - "engines": { - "node": ">= 14.15.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "less": "^3.5.0 || ^4.0.0", - "webpack": "^5.0.0" - } - }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -6201,7 +6184,9 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, "optional": true, + "peer": true, "dependencies": { "pify": "^4.0.1", "semver": "^5.6.0" @@ -6214,7 +6199,9 @@ "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, "optional": true, + "peer": true, "bin": { "semver": "bin/semver" } @@ -6505,7 +6492,9 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, "optional": true, + "peer": true, "bin": { "mime": "cli.js" }, @@ -6637,7 +6626,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "devOptional": true + "dev": true }, "node_modules/nanoid": { "version": "3.3.4", @@ -6660,7 +6649,9 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/needle/-/needle-3.2.0.tgz", "integrity": "sha512-oUvzXnyLiVyVGoianLijF9O/RecZUf7TkBfimjGrLM4eQhXyeJwM6GeAWccwfQ9aa4gMCZKqhAOuLaMIcQxajQ==", + "dev": true, "optional": true, + "peer": true, "dependencies": { "debug": "^3.2.6", "iconv-lite": "^0.6.3", @@ -6677,7 +6668,9 @@ "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, "optional": true, + "peer": true, "dependencies": { "ms": "^2.1.1" } @@ -7047,6 +7040,9 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true, + "optional": true, + "peer": true, "engines": { "node": ">= 0.10" } @@ -7148,7 +7144,9 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, "optional": true, + "peer": true, "engines": { "node": ">=6" } @@ -7288,18 +7286,6 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/postcss-less": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-less/-/postcss-less-6.0.0.tgz", - "integrity": "sha512-FPX16mQLyEjLzEuuJtxA8X3ejDLNGGEG503d2YGZR5Ask1SpDN8KmZUMpzCvyalWRywAn1n1VOA5dcqfCLo5rg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "postcss": "^8.3.5" - } - }, "node_modules/postcss-media-query-parser": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", @@ -7481,7 +7467,9 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", - "optional": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/psl": { "version": "1.9.0", @@ -7987,7 +7975,9 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "optional": true + "dev": true, + "optional": true, + "peer": true }, "node_modules/saxes": { "version": "6.0.0", @@ -8917,7 +8907,8 @@ "node_modules/tslib": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", + "dev": true }, "node_modules/type-check": { "version": "0.4.0", @@ -9413,9 +9404,9 @@ } }, "node_modules/webpack": { - "version": "5.75.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.75.0.tgz", - "integrity": "sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ==", + "version": "5.76.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.0.tgz", + "integrity": "sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA==", "dependencies": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^0.0.51", @@ -11852,6 +11843,9 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", + "dev": true, + "optional": true, + "peer": true, "requires": { "is-what": "^3.14.1" } @@ -12710,7 +12704,9 @@ "version": "0.1.8", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, "optional": true, + "peer": true, "requires": { "prr": "~1.0.1" } @@ -13783,7 +13779,9 @@ "version": "0.5.5", "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", - "optional": true + "dev": true, + "optional": true, + "peer": true }, "immer": { "version": "9.0.18", @@ -14076,7 +14074,10 @@ "is-what": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", - "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==" + "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", + "dev": true, + "optional": true, + "peer": true }, "isarray": { "version": "0.0.1", @@ -14269,11 +14270,6 @@ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" }, - "klona": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", - "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==" - }, "known-css-properties": { "version": "0.26.0", "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.26.0.tgz", @@ -14289,6 +14285,9 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/less/-/less-4.1.3.tgz", "integrity": "sha512-w16Xk/Ta9Hhyei0Gpz9m7VS8F28nieJaL/VyShID7cYvP6IL5oHeL6p4TXSDJqZE/lNv0oJ2pGVjJsRkfwm5FA==", + "dev": true, + "optional": true, + "peer": true, "requires": { "copy-anything": "^2.0.1", "errno": "^0.1.1", @@ -14302,14 +14301,6 @@ "tslib": "^2.3.0" } }, - "less-loader": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-11.1.0.tgz", - "integrity": "sha512-C+uDBV7kS7W5fJlUjq5mPBeBVhYpTIm5gB09APT9o3n/ILeaXVsiSFTbZpTJCJwQ/Crczfn3DmfQFwxYusWFug==", - "requires": { - "klona": "^2.0.4" - } - }, "leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -14484,7 +14475,9 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, "optional": true, + "peer": true, "requires": { "pify": "^4.0.1", "semver": "^5.6.0" @@ -14494,7 +14487,9 @@ "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "optional": true + "dev": true, + "optional": true, + "peer": true } } }, @@ -14721,7 +14716,9 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "optional": true + "dev": true, + "optional": true, + "peer": true }, "mime-db": { "version": "1.52.0", @@ -14817,7 +14814,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "devOptional": true + "dev": true }, "nanoid": { "version": "3.3.4", @@ -14834,7 +14831,9 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/needle/-/needle-3.2.0.tgz", "integrity": "sha512-oUvzXnyLiVyVGoianLijF9O/RecZUf7TkBfimjGrLM4eQhXyeJwM6GeAWccwfQ9aa4gMCZKqhAOuLaMIcQxajQ==", + "dev": true, "optional": true, + "peer": true, "requires": { "debug": "^3.2.6", "iconv-lite": "^0.6.3", @@ -14845,7 +14844,9 @@ "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, "optional": true, + "peer": true, "requires": { "ms": "^2.1.1" } @@ -15127,7 +15128,10 @@ "parse-node-version": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==" + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true, + "optional": true, + "peer": true }, "parse5": { "version": "7.1.2", @@ -15198,7 +15202,9 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "optional": true + "dev": true, + "optional": true, + "peer": true }, "pkg-dir": { "version": "4.2.0", @@ -15296,13 +15302,6 @@ "source-map-js": "^1.0.2" } }, - "postcss-less": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-less/-/postcss-less-6.0.0.tgz", - "integrity": "sha512-FPX16mQLyEjLzEuuJtxA8X3ejDLNGGEG503d2YGZR5Ask1SpDN8KmZUMpzCvyalWRywAn1n1VOA5dcqfCLo5rg==", - "dev": true, - "requires": {} - }, "postcss-media-query-parser": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", @@ -15433,7 +15432,9 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", - "optional": true + "dev": true, + "optional": true, + "peer": true }, "psl": { "version": "1.9.0", @@ -15792,7 +15793,9 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "optional": true + "dev": true, + "optional": true, + "peer": true }, "saxes": { "version": "6.0.0", @@ -16527,7 +16530,8 @@ "tslib": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==", + "dev": true }, "type-check": { "version": "0.4.0", @@ -16847,9 +16851,9 @@ "dev": true }, "webpack": { - "version": "5.75.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.75.0.tgz", - "integrity": "sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ==", + "version": "5.76.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.0.tgz", + "integrity": "sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA==", "requires": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^0.0.51", diff --git a/package.json b/package.json index c4457fe9708f..f10b331ed721 100644 --- a/package.json +++ b/package.json @@ -28,8 +28,6 @@ "jquery": "3.6.3", "jquery.are-you-sure": "1.9.0", "katex": "0.16.4", - "less": "4.1.3", - "less-loader": "11.1.0", "license-checker-webpack-plugin": "0.2.1", "mermaid": "10.0.2", "mini-css-extract-plugin": "2.7.2", @@ -45,7 +43,7 @@ "vue-bar-graph": "2.0.0", "vue-loader": "17.0.1", "vue3-calendar-heatmap": "2.0.0", - "webpack": "5.75.0", + "webpack": "5.76.0", "webpack-cli": "5.0.1", "workbox-routing": "6.5.4", "workbox-strategies": "6.5.4", @@ -64,7 +62,6 @@ "eslint-plugin-vue": "9.9.0", "jsdom": "21.0.0", "markdownlint-cli": "0.33.0", - "postcss-less": "6.0.0", "stylelint": "15.2.0", "stylelint-declaration-strict-value": "1.9.2", "svgo": "3.0.2", diff --git a/public/img/svg/fontawesome-save.svg b/public/img/svg/fontawesome-save.svg new file mode 100644 index 000000000000..f7beb90d949e --- /dev/null +++ b/public/img/svg/fontawesome-save.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/img/svg/gitea-swift.svg b/public/img/svg/gitea-swift.svg new file mode 100644 index 000000000000..ebfea951da33 --- /dev/null +++ b/public/img/svg/gitea-swift.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/routers/api/packages/README.md b/routers/api/packages/README.md new file mode 100644 index 000000000000..533a0d32f066 --- /dev/null +++ b/routers/api/packages/README.md @@ -0,0 +1,50 @@ +# Gitea Package Registry + +This document gives a brief overview how the package registry is organized in code. + +## Structure + +The package registry code is divided into multiple modules to split the functionality and make code reuse possible. + +| Module | Description | +| - | - | +| `models/packages` | Common methods and models used by all registry types | +| `models/packages/` | Methods used by specific registry type. There should be no need to use type specific models. | +| `modules/packages` | Common methods and types used by multiple registry types | +| `modules/packages/` | Registry type specific methods and types (e.g. metadata extraction of package files) | +| `routers/api/packages` | Route definitions for all registry types | +| `routers/api/packages/` | Route implementation for a specific registry type | +| `services/packages` | Helper methods used by registry types to handle common tasks like package creation and deletion in `routers` | +| `services/packages/` | Registry type specific methods used by `routers` and `services` | + +## Models + +Every package registry implementation uses the same underlaying models: + +| Model | Description | +| - | - | +| `Package` | The root of a package providing values fixed for every version (e.g. the package name) | +| `PackageVersion` | A version of a package containing metadata (e.g. the package description) | +| `PackageFile` | A file of a package describing its content (e.g. file name) | +| `PackageBlob` | The content of a file (may be shared by multiple files) | +| `PackageProperty` | Additional properties attached to `Package`, `PackageVersion` or `PackageFile` (e.g. used if metadata is needed for routing) | + +The following diagram shows the relationship between the models: +``` +Package <1---*> PackageVersion <1---*> PackageFile <*---1> PackageBlob +``` + +## Adding a new package registry type + +Before adding a new package registry type have a look at the existing implementation to get an impression of how it could work. +Most registry types offer endpoints to retrieve the metadata, upload and download package files. +The upload endpoint is often the heavy part because it must validate the uploaded blob, extract metadata and create the models. +The methods to validate and extract the metadata should be added in the `modules/packages/` package. +If the upload is valid the methods in `services/packages` allow to store the upload and create the corresponding models. +It depends if the registry type allows multiple files per package version which method should be called: +- `CreatePackageAndAddFile`: error if package version already exists +- `CreatePackageOrAddFileToExisting`: error if file already exists +- `AddFileToExistingPackage`: error if package version does not exist or file already exists + +`services/packages` also contains helper methods to download a file or to remove a package version. +There are no helper methods for metadata endpoints because they are very type specific. diff --git a/routers/api/packages/api.go b/routers/api/packages/api.go index 0e3d8b7a02d7..c0c7b117f696 100644 --- a/routers/api/packages/api.go +++ b/routers/api/packages/api.go @@ -28,6 +28,7 @@ import ( "code.gitea.io/gitea/routers/api/packages/pub" "code.gitea.io/gitea/routers/api/packages/pypi" "code.gitea.io/gitea/routers/api/packages/rubygems" + "code.gitea.io/gitea/routers/api/packages/swift" "code.gitea.io/gitea/routers/api/packages/vagrant" "code.gitea.io/gitea/services/auth" context_service "code.gitea.io/gitea/services/context" @@ -375,6 +376,41 @@ func CommonRoutes(ctx gocontext.Context) *web.Route { r.Delete("/yank", rubygems.DeletePackage) }, reqPackageAccess(perm.AccessModeWrite)) }, reqPackageAccess(perm.AccessModeRead)) + r.Group("/swift", func() { + r.Group("/{scope}/{name}", func() { + r.Group("", func() { + r.Get("", swift.EnumeratePackageVersions) + r.Get(".json", swift.EnumeratePackageVersions) + }, swift.CheckAcceptMediaType(swift.AcceptJSON)) + r.Group("/{version}", func() { + r.Get("/Package.swift", swift.CheckAcceptMediaType(swift.AcceptSwift), swift.DownloadManifest) + r.Put("", reqPackageAccess(perm.AccessModeWrite), swift.CheckAcceptMediaType(swift.AcceptJSON), swift.UploadPackageFile) + r.Get("", func(ctx *context.Context) { + // Can't use normal routes here: https://github.com/go-chi/chi/issues/781 + + version := ctx.Params("version") + if strings.HasSuffix(version, ".zip") { + swift.CheckAcceptMediaType(swift.AcceptZip)(ctx) + if ctx.Written() { + return + } + ctx.SetParams("version", version[:len(version)-4]) + swift.DownloadPackageFile(ctx) + } else { + swift.CheckAcceptMediaType(swift.AcceptJSON)(ctx) + if ctx.Written() { + return + } + if strings.HasSuffix(version, ".json") { + ctx.SetParams("version", version[:len(version)-5]) + } + swift.PackageVersionMetadata(ctx) + } + }) + }) + }) + r.Get("/identifiers", swift.CheckAcceptMediaType(swift.AcceptJSON), swift.LookupPackageIdentifiers) + }, reqPackageAccess(perm.AccessModeRead)) r.Group("/vagrant", func() { r.Group("/authenticate", func() { r.Get("", vagrant.CheckAuthenticate) diff --git a/routers/api/packages/swift/swift.go b/routers/api/packages/swift/swift.go new file mode 100644 index 000000000000..f78f703778ba --- /dev/null +++ b/routers/api/packages/swift/swift.go @@ -0,0 +1,464 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package swift + +import ( + "errors" + "fmt" + "io" + "net/http" + "regexp" + "sort" + "strings" + + packages_model "code.gitea.io/gitea/models/packages" + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/json" + "code.gitea.io/gitea/modules/log" + packages_module "code.gitea.io/gitea/modules/packages" + swift_module "code.gitea.io/gitea/modules/packages/swift" + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/util" + "code.gitea.io/gitea/routers/api/packages/helper" + packages_service "code.gitea.io/gitea/services/packages" + + "github.com/hashicorp/go-version" +) + +// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#35-api-versioning +const ( + AcceptJSON = "application/vnd.swift.registry.v1+json" + AcceptSwift = "application/vnd.swift.registry.v1+swift" + AcceptZip = "application/vnd.swift.registry.v1+zip" +) + +var ( + // https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#361-package-scope + scopePattern = regexp.MustCompile(`\A[a-zA-Z0-9][a-zA-Z0-9-]{0,38}\z`) + // https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#362-package-name + namePattern = regexp.MustCompile(`\A[a-zA-Z0-9][a-zA-Z0-9-_]{0,99}\z`) +) + +type headers struct { + Status int + ContentType string + Digest string + Location string + Link string +} + +// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#35-api-versioning +func setResponseHeaders(resp http.ResponseWriter, h *headers) { + if h.ContentType != "" { + resp.Header().Set("Content-Type", h.ContentType) + } + if h.Digest != "" { + resp.Header().Set("Digest", "sha256="+h.Digest) + } + if h.Location != "" { + resp.Header().Set("Location", h.Location) + } + if h.Link != "" { + resp.Header().Set("Link", h.Link) + } + resp.Header().Set("Content-Version", "1") + if h.Status != 0 { + resp.WriteHeader(h.Status) + } +} + +// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#33-error-handling +func apiError(ctx *context.Context, status int, obj interface{}) { + // https://www.rfc-editor.org/rfc/rfc7807 + type Problem struct { + Status int `json:"status"` + Detail string `json:"detail"` + } + + helper.LogAndProcessError(ctx, status, obj, func(message string) { + setResponseHeaders(ctx.Resp, &headers{ + Status: status, + ContentType: "application/problem+json", + }) + if err := json.NewEncoder(ctx.Resp).Encode(Problem{ + Status: status, + Detail: message, + }); err != nil { + log.Error("JSON encode: %v", err) + } + }) +} + +// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#35-api-versioning +func CheckAcceptMediaType(requiredAcceptHeader string) func(ctx *context.Context) { + return func(ctx *context.Context) { + accept := ctx.Req.Header.Get("Accept") + if accept != "" && accept != requiredAcceptHeader { + apiError(ctx, http.StatusBadRequest, fmt.Sprintf("Unexpected accept header. Should be '%s'.", requiredAcceptHeader)) + } + } +} + +func buildPackageID(scope, name string) string { + return scope + "." + name +} + +type Release struct { + URL string `json:"url"` +} + +type EnumeratePackageVersionsResponse struct { + Releases map[string]Release `json:"releases"` +} + +// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#41-list-package-releases +func EnumeratePackageVersions(ctx *context.Context) { + packageScope := ctx.Params("scope") + packageName := ctx.Params("name") + + pvs, err := packages_model.GetVersionsByPackageName(ctx, ctx.Package.Owner.ID, packages_model.TypeSwift, buildPackageID(packageScope, packageName)) + if err != nil { + apiError(ctx, http.StatusInternalServerError, err) + return + } + if len(pvs) == 0 { + apiError(ctx, http.StatusNotFound, nil) + return + } + + pds, err := packages_model.GetPackageDescriptors(ctx, pvs) + if err != nil { + apiError(ctx, http.StatusInternalServerError, err) + return + } + + sort.Slice(pds, func(i, j int) bool { + return pds[i].SemVer.LessThan(pds[j].SemVer) + }) + + baseURL := fmt.Sprintf("%sapi/packages/%s/swift/%s/%s/", setting.AppURL, ctx.Package.Owner.LowerName, packageScope, packageName) + + releases := make(map[string]Release) + for _, pd := range pds { + version := pd.SemVer.String() + releases[version] = Release{ + URL: baseURL + version, + } + } + + setResponseHeaders(ctx.Resp, &headers{ + Link: fmt.Sprintf(`<%s%s>; rel="latest-version"`, baseURL, pds[len(pds)-1].Version.Version), + }) + + ctx.JSON(http.StatusOK, EnumeratePackageVersionsResponse{ + Releases: releases, + }) +} + +type Resource struct { + Name string `json:"id"` + Type string `json:"type"` + Checksum string `json:"checksum"` +} + +type PackageVersionMetadataResponse struct { + ID string `json:"id"` + Version string `json:"version"` + Resources []Resource `json:"resources"` + Metadata *swift_module.SoftwareSourceCode `json:"metadata"` +} + +// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#endpoint-2 +func PackageVersionMetadata(ctx *context.Context) { + id := buildPackageID(ctx.Params("scope"), ctx.Params("name")) + + pv, err := packages_model.GetVersionByNameAndVersion(ctx, ctx.Package.Owner.ID, packages_model.TypeSwift, id, ctx.Params("version")) + if err != nil { + if errors.Is(err, util.ErrNotExist) { + apiError(ctx, http.StatusNotFound, err) + } else { + apiError(ctx, http.StatusInternalServerError, err) + } + return + } + + pd, err := packages_model.GetPackageDescriptor(ctx, pv) + if err != nil { + apiError(ctx, http.StatusInternalServerError, err) + return + } + + metadata := pd.Metadata.(*swift_module.Metadata) + + setResponseHeaders(ctx.Resp, &headers{}) + + ctx.JSON(http.StatusOK, PackageVersionMetadataResponse{ + ID: id, + Version: pd.Version.Version, + Resources: []Resource{ + { + Name: "source-archive", + Type: "application/zip", + Checksum: pd.Files[0].Blob.HashSHA256, + }, + }, + Metadata: &swift_module.SoftwareSourceCode{ + Context: []string{"http://schema.org/"}, + Type: "SoftwareSourceCode", + Name: pd.PackageProperties.GetByName(swift_module.PropertyName), + Version: pd.Version.Version, + Description: metadata.Description, + Keywords: metadata.Keywords, + CodeRepository: metadata.RepositoryURL, + License: metadata.License, + ProgrammingLanguage: swift_module.ProgrammingLanguage{ + Type: "ComputerLanguage", + Name: "Swift", + URL: "https://swift.org", + }, + Author: swift_module.Person{ + Type: "Person", + GivenName: metadata.Author.GivenName, + MiddleName: metadata.Author.MiddleName, + FamilyName: metadata.Author.FamilyName, + }, + }, + }) +} + +// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#43-fetch-manifest-for-a-package-release +func DownloadManifest(ctx *context.Context) { + packageScope := ctx.Params("scope") + packageName := ctx.Params("name") + packageVersion := ctx.Params("version") + + pv, err := packages_model.GetVersionByNameAndVersion(ctx, ctx.Package.Owner.ID, packages_model.TypeSwift, buildPackageID(packageScope, packageName), packageVersion) + if err != nil { + if errors.Is(err, util.ErrNotExist) { + apiError(ctx, http.StatusNotFound, err) + } else { + apiError(ctx, http.StatusInternalServerError, err) + } + return + } + + pd, err := packages_model.GetPackageDescriptor(ctx, pv) + if err != nil { + apiError(ctx, http.StatusInternalServerError, err) + return + } + + swiftVersion := ctx.FormTrim("swift-version") + if swiftVersion != "" { + v, err := version.NewVersion(swiftVersion) + if err == nil { + swiftVersion = swift_module.TrimmedVersionString(v) + } + } + m, ok := pd.Metadata.(*swift_module.Metadata).Manifests[swiftVersion] + if !ok { + setResponseHeaders(ctx.Resp, &headers{ + Status: http.StatusSeeOther, + Location: fmt.Sprintf("%sapi/packages/%s/swift/%s/%s/%s/Package.swift", setting.AppURL, ctx.Package.Owner.LowerName, packageScope, packageName, packageVersion), + }) + return + } + + setResponseHeaders(ctx.Resp, &headers{}) + + filename := "Package.swift" + if swiftVersion != "" { + filename = fmt.Sprintf("Package@swift-%s.swift", swiftVersion) + } + + ctx.ServeContent(strings.NewReader(m.Content), &context.ServeHeaderOptions{ + ContentType: "text/x-swift", + Filename: filename, + LastModified: pv.CreatedUnix.AsLocalTime(), + }) +} + +// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#endpoint-6 +func UploadPackageFile(ctx *context.Context) { + packageScope := ctx.Params("scope") + packageName := ctx.Params("name") + + v, err := version.NewVersion(ctx.Params("version")) + + if !scopePattern.MatchString(packageScope) || !namePattern.MatchString(packageName) || err != nil { + apiError(ctx, http.StatusBadRequest, err) + return + } + + packageVersion := v.Core().String() + + file, _, err := ctx.Req.FormFile("source-archive") + if err != nil { + apiError(ctx, http.StatusBadRequest, err) + return + } + defer file.Close() + + buf, err := packages_module.CreateHashedBufferFromReader(file, 32*1024*1024) + if err != nil { + apiError(ctx, http.StatusInternalServerError, err) + return + } + defer buf.Close() + + var mr io.Reader + metadata := ctx.Req.FormValue("metadata") + if metadata != "" { + mr = strings.NewReader(metadata) + } + + pck, err := swift_module.ParsePackage(buf, buf.Size(), mr) + if err != nil { + if errors.Is(err, util.ErrInvalidArgument) { + apiError(ctx, http.StatusBadRequest, err) + } else { + apiError(ctx, http.StatusInternalServerError, err) + } + return + } + + if _, err := buf.Seek(0, io.SeekStart); err != nil { + apiError(ctx, http.StatusInternalServerError, err) + return + } + + pv, _, err := packages_service.CreatePackageAndAddFile( + &packages_service.PackageCreationInfo{ + PackageInfo: packages_service.PackageInfo{ + Owner: ctx.Package.Owner, + PackageType: packages_model.TypeSwift, + Name: buildPackageID(packageScope, packageName), + Version: packageVersion, + }, + SemverCompatible: true, + Creator: ctx.Doer, + Metadata: pck.Metadata, + PackageProperties: map[string]string{ + swift_module.PropertyScope: packageScope, + swift_module.PropertyName: packageName, + }, + }, + &packages_service.PackageFileCreationInfo{ + PackageFileInfo: packages_service.PackageFileInfo{ + Filename: fmt.Sprintf("%s-%s.zip", packageName, packageVersion), + }, + Creator: ctx.Doer, + Data: buf, + IsLead: true, + }, + ) + if err != nil { + switch err { + case packages_model.ErrDuplicatePackageVersion: + apiError(ctx, http.StatusConflict, err) + case packages_service.ErrQuotaTotalCount, packages_service.ErrQuotaTypeSize, packages_service.ErrQuotaTotalSize: + apiError(ctx, http.StatusForbidden, err) + default: + apiError(ctx, http.StatusInternalServerError, err) + } + return + } + + for _, url := range pck.RepositoryURLs { + _, err = packages_model.InsertProperty(ctx, packages_model.PropertyTypeVersion, pv.ID, swift_module.PropertyRepositoryURL, url) + if err != nil { + log.Error("InsertProperty failed: %v", err) + } + } + + setResponseHeaders(ctx.Resp, &headers{}) + + ctx.Status(http.StatusCreated) +} + +// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#endpoint-4 +func DownloadPackageFile(ctx *context.Context) { + pv, err := packages_model.GetVersionByNameAndVersion(ctx, ctx.Package.Owner.ID, packages_model.TypeSwift, buildPackageID(ctx.Params("scope"), ctx.Params("name")), ctx.Params("version")) + if err != nil { + if errors.Is(err, util.ErrNotExist) { + apiError(ctx, http.StatusNotFound, err) + } else { + apiError(ctx, http.StatusInternalServerError, err) + } + return + } + + pd, err := packages_model.GetPackageDescriptor(ctx, pv) + if err != nil { + apiError(ctx, http.StatusInternalServerError, err) + return + } + + pf := pd.Files[0].File + + s, _, err := packages_service.GetPackageFileStream(ctx, pf) + if err != nil { + apiError(ctx, http.StatusInternalServerError, err) + return + } + defer s.Close() + + setResponseHeaders(ctx.Resp, &headers{ + Digest: pd.Files[0].Blob.HashSHA256, + }) + + ctx.ServeContent(s, &context.ServeHeaderOptions{ + Filename: pf.Name, + ContentType: "application/zip", + LastModified: pf.CreatedUnix.AsLocalTime(), + }) +} + +type LookupPackageIdentifiersResponse struct { + Identifiers []string `json:"identifiers"` +} + +// https://github.com/apple/swift-package-manager/blob/main/Documentation/Registry.md#endpoint-5 +func LookupPackageIdentifiers(ctx *context.Context) { + url := ctx.FormTrim("url") + if url == "" { + apiError(ctx, http.StatusBadRequest, nil) + return + } + + pvs, _, err := packages_model.SearchLatestVersions(ctx, &packages_model.PackageSearchOptions{ + OwnerID: ctx.Package.Owner.ID, + Type: packages_model.TypeSwift, + Properties: map[string]string{ + swift_module.PropertyRepositoryURL: url, + }, + IsInternal: util.OptionalBoolFalse, + }) + if err != nil { + apiError(ctx, http.StatusInternalServerError, err) + return + } + + if len(pvs) == 0 { + apiError(ctx, http.StatusNotFound, nil) + return + } + + pds, err := packages_model.GetPackageDescriptors(ctx, pvs) + if err != nil { + apiError(ctx, http.StatusInternalServerError, err) + return + } + + identifiers := make([]string, 0, len(pds)) + for _, pd := range pds { + identifiers = append(identifiers, pd.Package.Name) + } + + setResponseHeaders(ctx.Resp, &headers{}) + + ctx.JSON(http.StatusOK, LookupPackageIdentifiersResponse{ + Identifiers: identifiers, + }) +} diff --git a/routers/api/v1/admin/email.go b/routers/api/v1/admin/email.go new file mode 100644 index 000000000000..8d0491e07024 --- /dev/null +++ b/routers/api/v1/admin/email.go @@ -0,0 +1,87 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package admin + +import ( + "net/http" + + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/context" + api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/routers/api/v1/utils" + "code.gitea.io/gitea/services/convert" +) + +// GetAllEmails +func GetAllEmails(ctx *context.APIContext) { + // swagger:operation GET /admin/emails admin adminGetAllEmails + // --- + // summary: List all emails + // produces: + // - application/json + // parameters: + // - name: page + // in: query + // description: page number of results to return (1-based) + // type: integer + // - name: limit + // in: query + // description: page size of results + // type: integer + // responses: + // "200": + // "$ref": "#/responses/EmailList" + // "403": + // "$ref": "#/responses/forbidden" + + listOptions := utils.GetListOptions(ctx) + + emails, maxResults, err := user_model.SearchEmails(&user_model.SearchEmailOptions{ + Keyword: ctx.Params(":email"), + ListOptions: listOptions, + }) + if err != nil { + ctx.Error(http.StatusInternalServerError, "GetAllEmails", err) + return + } + + results := make([]*api.Email, len(emails)) + for i := range emails { + results[i] = convert.ToEmailSearch(emails[i]) + } + + ctx.SetLinkHeader(int(maxResults), listOptions.PageSize) + ctx.SetTotalCountHeader(maxResults) + ctx.JSON(http.StatusOK, &results) +} + +// SearchEmail +func SearchEmail(ctx *context.APIContext) { + // swagger:operation GET /admin/emails/search admin adminSearchEmails + // --- + // summary: Search all emails + // produces: + // - application/json + // parameters: + // - name: q + // in: query + // description: keyword + // type: string + // - name: page + // in: query + // description: page number of results to return (1-based) + // type: integer + // - name: limit + // in: query + // description: page size of results + // type: integer + // responses: + // "200": + // "$ref": "#/responses/EmailList" + // "403": + // "$ref": "#/responses/forbidden" + + ctx.SetParams(":email", ctx.FormTrim("q")) + GetAllEmails(ctx) +} diff --git a/routers/api/v1/admin/repo.go b/routers/api/v1/admin/repo.go index 83ed06e49bce..a4895f260bec 100644 --- a/routers/api/v1/admin/repo.go +++ b/routers/api/v1/admin/repo.go @@ -32,6 +32,8 @@ func CreateRepo(ctx *context.APIContext) { // responses: // "201": // "$ref": "#/responses/Repository" + // "400": + // "$ref": "#/responses/error" // "403": // "$ref": "#/responses/forbidden" // "404": diff --git a/routers/api/v1/admin/user.go b/routers/api/v1/admin/user.go index 1fbdab3e5598..369d13943a32 100644 --- a/routers/api/v1/admin/user.go +++ b/routers/api/v1/admin/user.go @@ -305,6 +305,10 @@ func DeleteUser(ctx *context.APIContext) { // description: username of user to delete // type: string // required: true + // - name: purge + // in: query + // description: purge the user from the system completely + // type: boolean // responses: // "204": // "$ref": "#/responses/empty" @@ -457,3 +461,61 @@ func GetAllUsers(ctx *context.APIContext) { ctx.SetTotalCountHeader(maxResults) ctx.JSON(http.StatusOK, &results) } + +// RenameUser api for renaming a user +func RenameUser(ctx *context.APIContext) { + // swagger:operation POST /admin/users/{username}/rename admin adminRenameUser + // --- + // summary: Rename a user + // produces: + // - application/json + // parameters: + // - name: username + // in: path + // description: existing username of user + // type: string + // required: true + // - name: body + // in: body + // required: true + // schema: + // "$ref": "#/definitions/RenameUserOption" + // responses: + // "204": + // "$ref": "#/responses/empty" + // "403": + // "$ref": "#/responses/forbidden" + // "422": + // "$ref": "#/responses/validationError" + + if ctx.ContextUser.IsOrganization() { + ctx.Error(http.StatusUnprocessableEntity, "", fmt.Errorf("%s is an organization not a user", ctx.ContextUser.Name)) + return + } + + newName := web.GetForm(ctx).(*api.RenameUserOption).NewName + + if strings.EqualFold(newName, ctx.ContextUser.Name) { + // Noop as username is not changed + ctx.Status(http.StatusNoContent) + return + } + + // Check if user name has been changed + if err := user_service.RenameUser(ctx, ctx.ContextUser, newName); err != nil { + switch { + case user_model.IsErrUserAlreadyExist(err): + ctx.Error(http.StatusUnprocessableEntity, "", ctx.Tr("form.username_been_taken")) + case db.IsErrNameReserved(err): + ctx.Error(http.StatusUnprocessableEntity, "", ctx.Tr("user.form.name_reserved", newName)) + case db.IsErrNamePatternNotAllowed(err): + ctx.Error(http.StatusUnprocessableEntity, "", ctx.Tr("user.form.name_pattern_not_allowed", newName)) + case db.IsErrNameCharsNotAllowed(err): + ctx.Error(http.StatusUnprocessableEntity, "", ctx.Tr("user.form.name_chars_not_allowed", newName)) + default: + ctx.ServerError("ChangeUserName", err) + } + return + } + ctx.Status(http.StatusNoContent) +} diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 735939a5517c..5c32164fa706 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -1257,8 +1257,13 @@ func Routes(ctx gocontext.Context) *web.Route { m.Get("/orgs", org.ListUserOrgs) m.Post("/orgs", bind(api.CreateOrgOption{}), admin.CreateOrg) m.Post("/repos", bind(api.CreateRepoOption{}), admin.CreateRepo) + m.Post("/rename", bind(api.RenameUserOption{}), admin.RenameUser) }, context_service.UserAssignmentAPI()) }) + m.Group("/emails", func() { + m.Get("", admin.GetAllEmails) + m.Get("/search", admin.SearchEmail) + }) m.Group("/unadopted", func() { m.Get("", admin.ListUnadoptedRepositories) m.Post("/{username}/{reponame}", admin.AdoptRepository) diff --git a/routers/api/v1/packages/package.go b/routers/api/v1/packages/package.go index ab077090d1c7..200dc5aaf140 100644 --- a/routers/api/v1/packages/package.go +++ b/routers/api/v1/packages/package.go @@ -40,7 +40,7 @@ func ListPackages(ctx *context.APIContext) { // in: query // description: package type filter // type: string - // enum: [cargo, chef, composer, conan, conda, container, generic, helm, maven, npm, nuget, pub, pypi, rubygems, vagrant] + // enum: [cargo, chef, composer, conan, conda, container, generic, helm, maven, npm, nuget, pub, pypi, rubygems, swift, vagrant] // - name: q // in: query // description: name filter diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index 397600dc50a9..16608e5bbbdb 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -231,6 +231,13 @@ func CreateUserRepo(ctx *context.APIContext, owner *user_model.User, opt api.Cre if opt.AutoInit && opt.Readme == "" { opt.Readme = "Default" } + + // If the readme template does not exist, a 400 will be returned. + if opt.AutoInit && len(opt.Readme) > 0 && !util.SliceContains(repo_module.Readmes, opt.Readme) { + ctx.Error(http.StatusBadRequest, "", fmt.Errorf("readme template does not exist, available templates: %v", repo_module.Readmes)) + return + } + repo, err := repo_service.CreateRepository(ctx, ctx.Doer, owner, repo_module.CreateRepoOptions{ Name: opt.Name, Description: opt.Description, @@ -283,6 +290,8 @@ func Create(ctx *context.APIContext) { // responses: // "201": // "$ref": "#/responses/Repository" + // "400": + // "$ref": "#/responses/error" // "409": // description: The repository with the same name already exists. // "422": @@ -464,6 +473,8 @@ func CreateOrgRepo(ctx *context.APIContext) { // responses: // "201": // "$ref": "#/responses/Repository" + // "400": + // "$ref": "#/responses/error" // "404": // "$ref": "#/responses/notFound" // "403": diff --git a/routers/api/v1/swagger/options.go b/routers/api/v1/swagger/options.go index 979b18407590..0c8d3d353fec 100644 --- a/routers/api/v1/swagger/options.go +++ b/routers/api/v1/swagger/options.go @@ -48,6 +48,9 @@ type swaggerParameterBodies struct { // in:body CreateKeyOption api.CreateKeyOption + // in:body + RenameUserOption api.RenameUserOption + // in:body CreateLabelOption api.CreateLabelOption // in:body diff --git a/routers/api/v1/user/repo.go b/routers/api/v1/user/repo.go index dcb14780a729..7a8978cc4e69 100644 --- a/routers/api/v1/user/repo.go +++ b/routers/api/v1/user/repo.go @@ -31,7 +31,7 @@ func listUserRepos(ctx *context.APIContext, u *user_model.User, private bool) { return } - if err := repos.LoadAttributes(); err != nil { + if err := repos.LoadAttributes(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "RepositoryList.LoadAttributes", err) return } diff --git a/routers/web/org/setting.go b/routers/web/org/setting.go index b57ebfbcda23..654e9000fa1b 100644 --- a/routers/web/org/setting.go +++ b/routers/web/org/setting.go @@ -79,7 +79,7 @@ func SettingsPost(ctx *context.Context) { ctx.Data["OrgName"] = true ctx.RenderWithErr(ctx.Tr("form.username_been_taken"), tplSettingsOptions, &form) return - } else if err = user_model.ChangeUserName(org.AsUser(), form.Name); err != nil { + } else if err = user_model.ChangeUserName(ctx, org.AsUser(), form.Name); err != nil { switch { case db.IsErrNameReserved(err): ctx.Data["OrgName"] = true diff --git a/routers/web/repo/actions/actions.go b/routers/web/repo/actions/actions.go index e5496676a9dd..dd2dc55bd5bc 100644 --- a/routers/web/repo/actions/actions.go +++ b/routers/web/repo/actions/actions.go @@ -23,6 +23,12 @@ const ( tplViewActions base.TplName = "repo/actions/view" ) +type Workflow struct { + Entry git.TreeEntry + IsInvalid bool + ErrMsg string +} + // MustEnableActions check if actions are enabled in settings func MustEnableActions(ctx *context.Context) { if !setting.Actions.Enabled { @@ -47,7 +53,7 @@ func List(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("actions.actions") ctx.Data["PageIsActions"] = true - var workflows git.Entries + var workflows []Workflow if empty, err := ctx.Repo.GitRepo.IsEmpty(); err != nil { ctx.Error(http.StatusInternalServerError, err.Error()) return @@ -62,13 +68,27 @@ func List(ctx *context.Context) { ctx.Error(http.StatusInternalServerError, err.Error()) return } - workflows, err = actions.ListWorkflows(commit) + entries, err := actions.ListWorkflows(commit) if err != nil { ctx.Error(http.StatusInternalServerError, err.Error()) return } + workflows = make([]Workflow, 0, len(entries)) + for _, entry := range entries { + workflow := Workflow{Entry: *entry} + content, err := actions.GetContentFromEntry(entry) + if err != nil { + ctx.Error(http.StatusInternalServerError, err.Error()) + return + } + _, err = actions.GetEventsFromContent(content) + if err != nil { + workflow.IsInvalid = true + workflow.ErrMsg = err.Error() + } + workflows = append(workflows, workflow) + } } - ctx.Data["workflows"] = workflows ctx.Data["RepoLink"] = ctx.Repo.Repository.Link() @@ -133,6 +153,8 @@ func List(ctx *context.Context) { pager := context.NewPagination(int(total), opts.PageSize, opts.Page, 5) pager.SetDefaultParams(ctx) + pager.AddParamString("workflow", workflow) + pager.AddParamString("state", ctx.FormString("state")) ctx.Data["Page"] = pager ctx.HTML(http.StatusOK, tplListActions) diff --git a/routers/web/repo/branch.go b/routers/web/repo/branch.go index d23367e04790..9f2663431112 100644 --- a/routers/web/repo/branch.go +++ b/routers/web/repo/branch.go @@ -8,6 +8,7 @@ import ( "errors" "fmt" "net/http" + "net/url" "strings" "code.gitea.io/gitea/models" @@ -65,21 +66,17 @@ func Branches(ctx *context.Context) { if page <= 1 { page = 1 } + pageSize := setting.Git.BranchesRangeSize - limit := ctx.FormInt("limit") - if limit <= 0 || limit > setting.Git.BranchesRangeSize { - limit = setting.Git.BranchesRangeSize - } - - skip := (page - 1) * limit - log.Debug("Branches: skip: %d limit: %d", skip, limit) - defaultBranchBranch, branches, branchesCount := loadBranches(ctx, skip, limit) + skip := (page - 1) * pageSize + log.Debug("Branches: skip: %d limit: %d", skip, pageSize) + defaultBranchBranch, branches, branchesCount := loadBranches(ctx, skip, pageSize) if ctx.Written() { return } ctx.Data["Branches"] = branches ctx.Data["DefaultBranchBranch"] = defaultBranchBranch - pager := context.NewPagination(branchesCount, setting.Git.BranchesRangeSize, page, 5) + pager := context.NewPagination(branchesCount, pageSize, page, 5) pager.SetDefaultParams(ctx) ctx.Data["Page"] = pager @@ -165,7 +162,7 @@ func RestoreBranchPost(ctx *context.Context) { func redirect(ctx *context.Context) { ctx.JSON(http.StatusOK, map[string]interface{}{ - "redirect": ctx.Repo.RepoLink + "/branches", + "redirect": ctx.Repo.RepoLink + "/branches?page=" + url.QueryEscape(ctx.FormString("page")), }) } diff --git a/routers/web/user/notification.go b/routers/web/user/notification.go index e96b3dd27a95..e12b41e649e6 100644 --- a/routers/web/user/notification.go +++ b/routers/web/user/notification.go @@ -117,7 +117,7 @@ func getNotifications(ctx *context.Context) { return } notifications = notifications.Without(failures) - if err := repos.LoadAttributes(); err != nil { // TODO + if err := repos.LoadAttributes(ctx); err != nil { ctx.ServerError("LoadAttributes", err) return } diff --git a/routers/web/user/setting/profile.go b/routers/web/user/setting/profile.go index f0f053a514e0..f500be763233 100644 --- a/routers/web/user/setting/profile.go +++ b/routers/web/user/setting/profile.go @@ -27,9 +27,7 @@ import ( "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/modules/web/middleware" - "code.gitea.io/gitea/services/agit" "code.gitea.io/gitea/services/forms" - container_service "code.gitea.io/gitea/services/packages/container" user_service "code.gitea.io/gitea/services/user" ) @@ -57,45 +55,25 @@ func HandleUsernameChange(ctx *context.Context, user *user_model.User, newName s return fmt.Errorf(ctx.Tr("form.username_change_not_local_user")) } - // Check if user name has been changed - if user.LowerName != strings.ToLower(newName) { - if err := user_model.ChangeUserName(user, newName); err != nil { - switch { - case user_model.IsErrUserAlreadyExist(err): - ctx.Flash.Error(ctx.Tr("form.username_been_taken")) - case user_model.IsErrEmailAlreadyUsed(err): - ctx.Flash.Error(ctx.Tr("form.email_been_used")) - case db.IsErrNameReserved(err): - ctx.Flash.Error(ctx.Tr("user.form.name_reserved", newName)) - case db.IsErrNamePatternNotAllowed(err): - ctx.Flash.Error(ctx.Tr("user.form.name_pattern_not_allowed", newName)) - case db.IsErrNameCharsNotAllowed(err): - ctx.Flash.Error(ctx.Tr("user.form.name_chars_not_allowed", newName)) - default: - ctx.ServerError("ChangeUserName", err) - } - return err - } - } else { - if err := repo_model.UpdateRepositoryOwnerNames(user.ID, newName); err != nil { - ctx.ServerError("UpdateRepository", err) - return err + // rename user + if err := user_service.RenameUser(ctx, user, newName); err != nil { + switch { + case user_model.IsErrUserAlreadyExist(err): + ctx.Flash.Error(ctx.Tr("form.username_been_taken")) + case user_model.IsErrEmailAlreadyUsed(err): + ctx.Flash.Error(ctx.Tr("form.email_been_used")) + case db.IsErrNameReserved(err): + ctx.Flash.Error(ctx.Tr("user.form.name_reserved", newName)) + case db.IsErrNamePatternNotAllowed(err): + ctx.Flash.Error(ctx.Tr("user.form.name_pattern_not_allowed", newName)) + case db.IsErrNameCharsNotAllowed(err): + ctx.Flash.Error(ctx.Tr("user.form.name_chars_not_allowed", newName)) + default: + ctx.ServerError("ChangeUserName", err) } - } - - // update all agit flow pull request header - err := agit.UserNameChanged(user, newName) - if err != nil { - ctx.ServerError("agit.UserNameChanged", err) - return err - } - - if err := container_service.UpdateRepositoryNames(ctx, user, newName); err != nil { - ctx.ServerError("UpdateRepositoryNames", err) return err } - log.Trace("User name changed: %s -> %s", user.Name, newName) return nil } diff --git a/services/actions/commit_status.go b/services/actions/commit_status.go index 4f313493523e..84de106eeca3 100644 --- a/services/actions/commit_status.go +++ b/services/actions/commit_status.go @@ -21,35 +21,60 @@ func CreateCommitStatus(ctx context.Context, job *actions_model.ActionRunJob) er } run := job.Run - if run.Event != webhook_module.HookEventPush { - return nil - } + var ( + sha string + creatorID int64 + ) - payload, err := run.GetPushEventPayload() - if err != nil { - return fmt.Errorf("GetPushEventPayload: %w", err) - } + switch run.Event { + case webhook_module.HookEventPush: + payload, err := run.GetPushEventPayload() + if err != nil { + return fmt.Errorf("GetPushEventPayload: %w", err) + } - // Since the payload comes from json data, we should check if it's broken, or it will cause panic - switch { - case payload.Repo == nil: - return fmt.Errorf("repo is missing in event payload") - case payload.Pusher == nil: - return fmt.Errorf("pusher is missing in event payload") - case payload.HeadCommit == nil: - return fmt.Errorf("head commit is missing in event payload") - } + // Since the payload comes from json data, we should check if it's broken, or it will cause panic + switch { + case payload.Repo == nil: + return fmt.Errorf("repo is missing in event payload") + case payload.Pusher == nil: + return fmt.Errorf("pusher is missing in event payload") + case payload.HeadCommit == nil: + return fmt.Errorf("head commit is missing in event payload") + } - creator, err := user_model.GetUserByID(ctx, payload.Pusher.ID) - if err != nil { - return fmt.Errorf("GetUserByID: %w", err) + sha = payload.HeadCommit.ID + creatorID = payload.Pusher.ID + case webhook_module.HookEventPullRequest: + payload, err := run.GetPullRequestEventPayload() + if err != nil { + return fmt.Errorf("GetPullRequestEventPayload: %w", err) + } + + switch { + case payload.PullRequest == nil: + return fmt.Errorf("pull request is missing in event payload") + case payload.PullRequest.Head == nil: + return fmt.Errorf("head of pull request is missing in event payload") + case payload.PullRequest.Head.Repository == nil: + return fmt.Errorf("head repository of pull request is missing in event payload") + case payload.PullRequest.Head.Repository.Owner == nil: + return fmt.Errorf("owner of head repository of pull request is missing in evnt payload") + } + + sha = payload.PullRequest.Head.Sha + creatorID = payload.PullRequest.Head.Repository.Owner.ID + default: + return nil } repo := run.Repo - sha := payload.HeadCommit.ID ctxname := job.Name state := toCommitStatus(job.Status) - + creator, err := user_model.GetUserByID(ctx, creatorID) + if err != nil { + return fmt.Errorf("GetUserByID: %w", err) + } if statuses, _, err := git_model.GetLatestCommitStatus(ctx, repo.ID, sha, db.ListOptions{}); err == nil { for _, v := range statuses { if v.Context == ctxname { @@ -65,14 +90,14 @@ func CreateCommitStatus(ctx context.Context, job *actions_model.ActionRunJob) er if err := git_model.NewCommitStatus(ctx, git_model.NewCommitStatusOptions{ Repo: repo, - SHA: payload.HeadCommit.ID, + SHA: sha, Creator: creator, CommitStatus: &git_model.CommitStatus{ SHA: sha, TargetURL: run.Link(), Description: "", Context: ctxname, - CreatorID: payload.Pusher.ID, + CreatorID: creatorID, State: state, }, }); err != nil { diff --git a/services/agit/agit.go b/services/agit/agit.go index b61cb6f3f569..32fc3cba4a36 100644 --- a/services/agit/agit.go +++ b/services/agit/agit.go @@ -226,8 +226,8 @@ func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git. } // UserNameChanged handle user name change for agit flow pull -func UserNameChanged(user *user_model.User, newName string) error { - pulls, err := issues_model.GetAllUnmergedAgitPullRequestByPoster(user.ID) +func UserNameChanged(ctx context.Context, user *user_model.User, newName string) error { + pulls, err := issues_model.GetAllUnmergedAgitPullRequestByPoster(ctx, user.ID) if err != nil { return err } diff --git a/services/convert/convert.go b/services/convert/convert.go index 5f2100a03940..bce0e7ba214b 100644 --- a/services/convert/convert.go +++ b/services/convert/convert.go @@ -38,6 +38,17 @@ func ToEmail(email *user_model.EmailAddress) *api.Email { } } +// ToEmail convert models.EmailAddress to api.Email +func ToEmailSearch(email *user_model.SearchEmailResult) *api.Email { + return &api.Email{ + Email: email.Email, + Verified: email.IsActivated, + Primary: email.IsPrimary, + UserID: email.UID, + UserName: email.Name, + } +} + // ToBranch convert a git.Commit and git.Branch to an api.Branch func ToBranch(ctx context.Context, repo *repo_model.Repository, b *git.Branch, c *git.Commit, bp *git_model.ProtectedBranch, user *user_model.User, isRepoAdmin bool) (*api.Branch, error) { if bp == nil { diff --git a/services/forms/package_form.go b/services/forms/package_form.go index b22ed47c775a..699d0fe44f96 100644 --- a/services/forms/package_form.go +++ b/services/forms/package_form.go @@ -15,7 +15,7 @@ import ( type PackageCleanupRuleForm struct { ID int64 Enabled bool - Type string `binding:"Required;In(cargo,chef,composer,conan,conda,container,generic,helm,maven,npm,nuget,pub,pypi,rubygems,vagrant)"` + Type string `binding:"Required;In(cargo,chef,composer,conan,conda,container,generic,helm,maven,npm,nuget,pub,pypi,rubygems,swift,vagrant)"` KeepCount int `binding:"In(0,1,5,10,25,50,100)"` KeepPattern string `binding:"RegexPattern"` RemoveDays int `binding:"In(0,7,14,30,60,90,180)"` diff --git a/services/packages/packages.go b/services/packages/packages.go index 3abca7337c7d..dd5c63470b8b 100644 --- a/services/packages/packages.go +++ b/services/packages/packages.go @@ -361,6 +361,8 @@ func CheckSizeQuotaExceeded(ctx context.Context, doer, owner *user_model.User, p typeSpecificSize = setting.Packages.LimitSizePyPI case packages_model.TypeRubyGems: typeSpecificSize = setting.Packages.LimitSizeRubyGems + case packages_model.TypeSwift: + typeSpecificSize = setting.Packages.LimitSizeSwift case packages_model.TypeVagrant: typeSpecificSize = setting.Packages.LimitSizeVagrant } diff --git a/services/user/rename.go b/services/user/rename.go new file mode 100644 index 000000000000..af195d7d76a2 --- /dev/null +++ b/services/user/rename.go @@ -0,0 +1,41 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package user + +import ( + "context" + "fmt" + "strings" + + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/services/agit" + container_service "code.gitea.io/gitea/services/packages/container" +) + +func renameUser(ctx context.Context, u *user_model.User, newUserName string) error { + if u.IsOrganization() { + return fmt.Errorf("cannot rename organization") + } + + if err := user_model.ChangeUserName(ctx, u, newUserName); err != nil { + return err + } + + if err := agit.UserNameChanged(ctx, u, newUserName); err != nil { + return err + } + if err := container_service.UpdateRepositoryNames(ctx, u, newUserName); err != nil { + return err + } + + u.Name = newUserName + u.LowerName = strings.ToLower(newUserName) + if err := user_model.UpdateUser(ctx, u, false); err != nil { + return err + } + + log.Trace("User name changed: %s -> %s", u.Name, newUserName) + return nil +} diff --git a/services/user/user.go b/services/user/user.go index f0b8fe1c3174..d52a2f404bcf 100644 --- a/services/user/user.go +++ b/services/user/user.go @@ -27,6 +27,22 @@ import ( "code.gitea.io/gitea/services/packages" ) +// RenameUser renames a user +func RenameUser(ctx context.Context, u *user_model.User, newUserName string) error { + ctx, committer, err := db.TxContext(ctx) + if err != nil { + return err + } + defer committer.Close() + if err := renameUser(ctx, u, newUserName); err != nil { + return err + } + if err := committer.Commit(); err != nil { + return err + } + return err +} + // DeleteUser completely and permanently deletes everything of a user, // but issues/comments/pulls will be kept and shown as someone has been deleted, // unless the user is younger than USER_DELETE_WITH_COMMENTS_MAX_DAYS. diff --git a/templates/admin/auth/edit.tmpl b/templates/admin/auth/edit.tmpl index d64ee188af15..c798be02ff7f 100644 --- a/templates/admin/auth/edit.tmpl +++ b/templates/admin/auth/edit.tmpl @@ -433,7 +433,7 @@
-
{{.locale.Tr "admin.auths.delete"}}
+
diff --git a/templates/admin/config.tmpl b/templates/admin/config.tmpl index 8f572c839612..cc0580cc19dc 100644 --- a/templates/admin/config.tmpl +++ b/templates/admin/config.tmpl @@ -331,7 +331,19 @@
{{.Git.MaxGitDiffFiles}}
{{.locale.Tr "admin.config.git_gc_args"}}
{{.Git.GCArgs}}
+
+ +
{{.locale.Tr "admin.config.git_enable_reflogs"}}
+
{{if .Git.Reflog.Enabled}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}
+ + {{if .Git.Reflog.Enabled}} +
{{.locale.Tr "admin.config.git_reflog_expiry_time"}}
+
{{.locale.Tr "tool.days" .Git.Reflog.Expiration}}
+ {{end}} + +
+
{{.locale.Tr "admin.config.git_migrate_timeout"}}
{{.Git.Timeout.Migrate}} {{.locale.Tr "tool.raw_seconds"}}
{{.locale.Tr "admin.config.git_mirror_timeout"}}
diff --git a/templates/admin/emails/list.tmpl b/templates/admin/emails/list.tmpl index 091f5011f953..d8fa986cff3e 100644 --- a/templates/admin/emails/list.tmpl +++ b/templates/admin/emails/list.tmpl @@ -78,7 +78,7 @@ {{.locale.Tr "admin.emails.change_email_header"}}
-

{{.locale.Tr "admin.emails.change_email_text"}}

+

{{.locale.Tr "admin.emails.change_email_text"}}

{{$.CsrfTokenHtml}} @@ -93,11 +93,9 @@ -
-
{{$.locale.Tr "settings.cancel"}}
- +
+ {{template "base/delete_modal_actions" .}}
-
diff --git a/templates/admin/notice.tmpl b/templates/admin/notice.tmpl index a2c7ca2f6ae8..34bd83a21449 100644 --- a/templates/admin/notice.tmpl +++ b/templates/admin/notice.tmpl @@ -23,7 +23,7 @@
- +
{{.ID}} @@ -39,13 +39,11 @@ -
-
- {{.CsrfTokenHtml}} - -
-
- @@ -70,16 +61,7 @@ -
-
- {{svg "octicon-trash" 16 "gt-mr-2"}} - {{$.locale.Tr "modal.no"}} -
- -
+ {{template "base/delete_modal_actions" .}} diff --git a/templates/admin/user/edit.tmpl b/templates/admin/user/edit.tmpl index 5dd1f531fda9..73017e1b13f1 100644 --- a/templates/admin/user/edit.tmpl +++ b/templates/admin/user/edit.tmpl @@ -151,7 +151,7 @@
-
{{.locale.Tr "admin.users.delete_account"}}
+
@@ -189,7 +189,7 @@
- {{$.locale.Tr "settings.delete_current_avatar"}} + {{$.locale.Tr "settings.delete_current_avatar"}}{{/* TODO: Convert links without href to buttons for a11y */}}
@@ -213,16 +213,7 @@

{{.locale.Tr "admin.users.purge_help"}}

-
-
- {{svg "octicon-x"}} - {{.locale.Tr "modal.no"}} -
- -
+ {{template "base/delete_modal_actions" .}} {{template "base/footer" .}} diff --git a/templates/base/delete_modal_actions.tmpl b/templates/base/delete_modal_actions.tmpl index fb4d31270af5..29bf5f92fd53 100644 --- a/templates/base/delete_modal_actions.tmpl +++ b/templates/base/delete_modal_actions.tmpl @@ -1,10 +1,10 @@
-
+
-
+ +
+
diff --git a/templates/code/searchresults.tmpl b/templates/code/searchresults.tmpl index 74721a5a674d..684e2860bff4 100644 --- a/templates/code/searchresults.tmpl +++ b/templates/code/searchresults.tmpl @@ -11,15 +11,15 @@ {{range $result := .SearchResults}} {{$repo := (index $.RepoMaps .RepoID)}}
-

- +

+ {{$repo.FullName}} {{if $repo.IsArchived}} {{$.locale.Tr "repo.desc.archived"}} {{end}} - {{.Filename}} - {{$.locale.Tr "repo.diff.view_file"}} + {{$.locale.Tr "repo.diff.view_file"}}

diff --git a/templates/org/settings/delete.tmpl b/templates/org/settings/delete.tmpl index 669e393e1dec..69e226f410a7 100644 --- a/templates/org/settings/delete.tmpl +++ b/templates/org/settings/delete.tmpl @@ -19,9 +19,9 @@
-
+
+

diff --git a/templates/org/settings/labels.tmpl b/templates/org/settings/labels.tmpl index 5436bcba05ca..e04b39127162 100644 --- a/templates/org/settings/labels.tmpl +++ b/templates/org/settings/labels.tmpl @@ -11,7 +11,7 @@
-
{{.locale.Tr "repo.issues.new_label"}}
+
diff --git a/templates/package/content/swift.tmpl b/templates/package/content/swift.tmpl new file mode 100644 index 000000000000..3ff06483b83e --- /dev/null +++ b/templates/package/content/swift.tmpl @@ -0,0 +1,40 @@ +{{if eq .PackageDescriptor.Package.Type "swift"}} +

{{.locale.Tr "packages.installation"}}

+
+
+
+ +
swift package-registry set 
+
+
+ +
dependencies: [
+	.package(id: "{{.PackageDescriptor.Package.Name}}", from:"{{.PackageDescriptor.Version.Version}}")
+]
+
+
+ +
swift package resolve
+
+
+ +
+
+
+ + {{if .PackageDescriptor.Metadata.Description}} +

{{.locale.Tr "packages.about"}}

+
+ {{if .PackageDescriptor.Metadata.Description}}{{.PackageDescriptor.Metadata.Description}}{{end}} +
+ {{end}} + + {{if .PackageDescriptor.Metadata.Keywords}} +

{{.locale.Tr "packages.keywords"}}

+
+ {{range .PackageDescriptor.Metadata.Keywords}} + {{.}} + {{end}} +
+ {{end}} +{{end}} diff --git a/templates/package/metadata/swift.tmpl b/templates/package/metadata/swift.tmpl new file mode 100644 index 000000000000..8a9ab071fc59 --- /dev/null +++ b/templates/package/metadata/swift.tmpl @@ -0,0 +1,4 @@ +{{if eq .PackageDescriptor.Package.Type "swift"}} + {{if .PackageDescriptor.Metadata.Author.String}}
{{svg "octicon-person" 16 "mr-3"}} {{.PackageDescriptor.Metadata.Author}}
{{end}} + {{if .PackageDescriptor.Metadata.RepositoryURL}}
{{svg "octicon-link-external" 16 "mr-3"}} {{.locale.Tr "packages.details.project_site"}}
{{end}} +{{end}} diff --git a/templates/package/settings.tmpl b/templates/package/settings.tmpl index dc12fb8207dd..875bf852bb98 100644 --- a/templates/package/settings.tmpl +++ b/templates/package/settings.tmpl @@ -57,10 +57,7 @@
{{.CsrfTokenHtml}} -
-
{{.locale.Tr "cancel"}}
- -
+ {{template "base/delete_modal_actions" .}}
diff --git a/templates/package/view.tmpl b/templates/package/view.tmpl index 839d9cf21af1..b2a2fb1e5d57 100644 --- a/templates/package/view.tmpl +++ b/templates/package/view.tmpl @@ -33,6 +33,7 @@ {{template "package/content/pub" .}} {{template "package/content/pypi" .}} {{template "package/content/rubygems" .}} + {{template "package/content/swift" .}} {{template "package/content/vagrant" .}}
@@ -59,6 +60,7 @@ {{template "package/metadata/pub" .}} {{template "package/metadata/pypi" .}} {{template "package/metadata/rubygems" .}} + {{template "package/metadata/swift" .}} {{template "package/metadata/vagrant" .}}
{{svg "octicon-database" 16 "gt-mr-3"}} {{FileSize .PackageDescriptor.CalculateBlobSize}}
diff --git a/templates/projects/list.tmpl b/templates/projects/list.tmpl index 4a21c0fd28ce..89c52dee6808 100644 --- a/templates/projects/list.tmpl +++ b/templates/projects/list.tmpl @@ -84,15 +84,6 @@

{{.locale.Tr "repo.projects.deletion_desc"}}

-
-
- - {{.locale.Tr "modal.no"}} -
-
- - {{.locale.Tr "modal.yes"}} -
-
+ {{template "base/delete_modal_actions" .}} {{end}} diff --git a/templates/projects/view.tmpl b/templates/projects/view.tmpl index 6867309510f8..b776f89efa39 100644 --- a/templates/projects/view.tmpl +++ b/templates/projects/view.tmpl @@ -29,7 +29,7 @@
-
{{$.locale.Tr "settings.cancel"}}
+
@@ -127,7 +127,7 @@
-
{{$.locale.Tr "settings.cancel"}}
+
@@ -144,7 +144,7 @@
-
{{$.locale.Tr "settings.cancel"}}
+
@@ -158,8 +158,8 @@ {{$.locale.Tr "repo.projects.column.deletion_desc"}} -
-
{{$.locale.Tr "settings.cancel"}}
+
{{/* TODO: convert to base/delete_modal_actions.tmpl */}} +
@@ -265,15 +265,6 @@

{{.locale.Tr "repo.projects.deletion_desc"}}

-
-
- - {{.locale.Tr "modal.no"}} -
-
- - {{.locale.Tr "modal.yes"}} -
-
+ {{template "base/delete_modal_actions" .}} {{end}} diff --git a/templates/repo/actions/list.tmpl b/templates/repo/actions/list.tmpl index c5abff52513b..5e8313fa5e36 100644 --- a/templates/repo/actions/list.tmpl +++ b/templates/repo/actions/list.tmpl @@ -9,7 +9,17 @@ {{.locale.Tr "actions.runs.all_workflows"}}
{{range .workflows}} - {{.Name}} + {{.Entry.Name}} + {{if .IsInvalid}} + + + + {{else}} + + + + {{end}} + {{end}} diff --git a/templates/repo/actions/runs_list.tmpl b/templates/repo/actions/runs_list.tmpl index ffabe534c8bb..a28b9d71378b 100644 --- a/templates/repo/actions/runs_list.tmpl +++ b/templates/repo/actions/runs_list.tmpl @@ -1,14 +1,18 @@
{{range .Runs}} -
  • +
  • {{template "repo/actions/status" .Status}}
    -
    +
    +
    + {{if not $.CurWorkflow}}{{.WorkflowID}} {{end}}#{{.Index}}: {{$.locale.Tr "actions.runs.commit"}} + {{ShortSha .CommitSHA}}{{$.locale.Tr "actions.runs.pushed_by"}} {{.TriggerUser.GetDisplayName}} {{if .RefLink}} {{.PrettyRef}} @@ -17,10 +21,6 @@ {{end}}
    -
    - {{if not $.CurWorkflow}}{{.WorkflowID}} {{end}}#{{.Index}}: {{$.locale.Tr "actions.runs.commit"}} - {{ShortSha .CommitSHA}}  {{$.locale.Tr "actions.runs.pushed_by"}} {{.TriggerUser.GetDisplayName | Escape}} -
    {{TimeSinceUnix .Updated $.locale}}
    diff --git a/templates/repo/branch/list.tmpl b/templates/repo/branch/list.tmpl index a093c19deb8c..898be4d6bb98 100644 --- a/templates/repo/branch/list.tmpl +++ b/templates/repo/branch/list.tmpl @@ -81,9 +81,9 @@ {{if not .LatestPullRequest}} {{if .IsIncluded}} - + {{svg "octicon-git-pull-request"}} {{$.locale.Tr "repo.branch.included"}} - + {{else if and (not .IsDeleted) $.AllowsPulls (gt .CommitsAhead 0)}} @@ -123,13 +123,13 @@ {{end}} {{if and $.IsWriter (not $.IsMirror) (not $.Repository.IsArchived) (not .IsProtected)}} {{if .IsDeleted}} - {{else}} - {{end}} @@ -176,7 +176,7 @@
    -
    {{.locale.Tr "settings.cancel"}}
    +
    diff --git a/templates/repo/branch_dropdown.tmpl b/templates/repo/branch_dropdown.tmpl index 8e81373aec04..1ec4b7ef165d 100644 --- a/templates/repo/branch_dropdown.tmpl +++ b/templates/repo/branch_dropdown.tmpl @@ -1,6 +1,20 @@ -{{$release := .release}} -{{$defaultBranch := $.root.BranchName}}{{if and .root.IsViewTag (not .noTag)}}{{$defaultBranch = .root.TagName}}{{end}}{{if eq $defaultBranch ""}}{{$defaultBranch = $.root.Repository.DefaultBranch}}{{end}} -{{$type := ""}}{{if and .root.IsViewTag (not .noTag)}}{{$type = "tag"}}{{else if .root.IsViewBranch}}{{$type = "branch"}}{{else}}{{$type = "tree"}}{{end}} +{{$defaultBranch := $.root.BranchName}} +{{if and .root.IsViewTag (not .noTag)}} + {{$defaultBranch = .root.TagName}} +{{end}} +{{if eq $defaultBranch ""}} + {{$defaultBranch = $.root.Repository.DefaultBranch}} +{{end}} + +{{$type := ""}} +{{if and .root.IsViewTag (not .noTag)}} + {{$type = "tag"}} +{{else if .root.IsViewBranch}} + {{$type = "branch"}} +{{else}} + {{$type = "tree"}} +{{end}} + {{$showBranchesInDropdown := not .root.HideBranchesInDropdown}} -
    -
    +
    +
  • diff --git a/templates/repo/commit_page.tmpl b/templates/repo/commit_page.tmpl index f19a4d4223c7..ace5a410875e 100644 --- a/templates/repo/commit_page.tmpl +++ b/templates/repo/commit_page.tmpl @@ -96,7 +96,7 @@
    -
    {{.locale.Tr "settings.cancel"}}
    +
    @@ -121,7 +121,7 @@
    -
    {{.locale.Tr "settings.cancel"}}
    +
    diff --git a/templates/repo/commit_status.tmpl b/templates/repo/commit_status.tmpl index fbf064527da4..470869b381c0 100644 --- a/templates/repo/commit_status.tmpl +++ b/templates/repo/commit_status.tmpl @@ -1,6 +1,9 @@ {{if eq .State "pending"}} {{svg "octicon-dot-fill" 18 "commit-status icon text yellow"}} {{end}} +{{if eq .State "running"}} + {{svg "octicon-dot-fill" 18 "commit-status icon text yellow"}} +{{end}} {{if eq .State "success"}} {{svg "octicon-check" 18 "commit-status icon text green"}} {{end}} diff --git a/templates/repo/diff/box.tmpl b/templates/repo/diff/box.tmpl index afd471368fa8..e0c58896f0f0 100644 --- a/templates/repo/diff/box.tmpl +++ b/templates/repo/diff/box.tmpl @@ -107,8 +107,8 @@
    {{if $showFileViewToggle}}
    - {{svg "octicon-code"}} - {{svg "octicon-file"}} + +
    {{end}} {{if $file.IsProtected}} @@ -200,8 +200,8 @@ {{$.locale.Tr "loading"}}
    -
    {{.locale.Tr "repo.issues.cancel"}}
    -
    {{.locale.Tr "repo.issues.save"}}
    + +
    diff --git a/templates/repo/editor/edit.tmpl b/templates/repo/editor/edit.tmpl index 992ccee8e4ff..431033e18e8a 100644 --- a/templates/repo/editor/edit.tmpl +++ b/templates/repo/editor/edit.tmpl @@ -65,14 +65,14 @@

    {{.locale.Tr "repo.editor.commit_empty_file_text"}}

    -
    +
    -
    + +
    +
    diff --git a/templates/repo/editor/patch.tmpl b/templates/repo/editor/patch.tmpl index bbd5c2dbdef1..75a8b5d687d9 100644 --- a/templates/repo/editor/patch.tmpl +++ b/templates/repo/editor/patch.tmpl @@ -45,14 +45,14 @@

    {{.locale.Tr "repo.editor.commit_empty_file_text"}}

    -
    - +
    -
    - + +
    +
    diff --git a/templates/repo/issue/labels.tmpl b/templates/repo/issue/labels.tmpl index 82cfcd071204..0a25d9c87ff1 100644 --- a/templates/repo/issue/labels.tmpl +++ b/templates/repo/issue/labels.tmpl @@ -6,7 +6,7 @@ {{template "repo/issue/navbar" .}} {{if and (or .CanWriteIssues .CanWritePulls) (not .Repository.IsArchived)}}
    -
    {{.locale.Tr "repo.issues.new_label"}}
    +
    {{end}} diff --git a/templates/repo/issue/labels/edit_delete_label.tmpl b/templates/repo/issue/labels/edit_delete_label.tmpl index 450061e8357c..38a948172ffc 100644 --- a/templates/repo/issue/labels/edit_delete_label.tmpl +++ b/templates/repo/issue/labels/edit_delete_label.tmpl @@ -6,16 +6,7 @@

    {{.locale.Tr "repo.issues.label_deletion_desc"}}

    -
    -
    - - {{.locale.Tr "modal.no"}} -
    -
    - - {{.locale.Tr "modal.yes"}} -
    -
    + {{template "base/delete_modal_actions" .}}
    -
    +
    -
    + +
    +
    diff --git a/templates/repo/issue/labels/label_new.tmpl b/templates/repo/issue/labels/label_new.tmpl index 62f7155b745c..c937f28e8aa2 100644 --- a/templates/repo/issue/labels/label_new.tmpl +++ b/templates/repo/issue/labels/label_new.tmpl @@ -36,12 +36,15 @@ +
    -
    +
    -
    + +
    +
    diff --git a/templates/repo/issue/list.tmpl b/templates/repo/issue/list.tmpl index ca05264e77b6..36faf861136b 100644 --- a/templates/repo/issue/list.tmpl +++ b/templates/repo/issue/list.tmpl @@ -213,9 +213,9 @@ {{if not .Repository.IsArchived}} {{if .IsShowClosed}} -
    {{.locale.Tr "repo.issues.action_open"}}
    + {{else}} -
    {{.locale.Tr "repo.issues.action_close"}}
    + {{end}} diff --git a/templates/repo/issue/view_content/comments_delete_time.tmpl b/templates/repo/issue/view_content/comments_delete_time.tmpl index bc08d7fde78d..b79b7ae2be09 100644 --- a/templates/repo/issue/view_content/comments_delete_time.tmpl +++ b/templates/repo/issue/view_content/comments_delete_time.tmpl @@ -7,10 +7,7 @@ {{.ctxData.CsrfTokenHtml}}
    {{.ctxData.locale.Tr "repo.issues.del_time"}}
    -
    -
    {{.ctxData.locale.Tr "repo.issues.context.delete"}}
    -
    {{.ctxData.locale.Tr "repo.issues.add_time_cancel"}}
    -
    + {{template "base/delete_modal_actions" .}} diff --git a/templates/repo/issue/view_content/sidebar.tmpl b/templates/repo/issue/view_content/sidebar.tmpl index f888bac71e41..25ba884b2beb 100644 --- a/templates/repo/issue/view_content/sidebar.tmpl +++ b/templates/repo/issue/view_content/sidebar.tmpl @@ -346,8 +346,8 @@
    -
    {{.locale.Tr "repo.issues.add_time_short"}}
    -
    {{.locale.Tr "repo.issues.add_time_cancel"}}
    + +
    @@ -532,14 +532,14 @@ {{end}}

    -
    +
    -
    + +
    +
    {{end}} @@ -619,7 +619,7 @@ {{end}}
    -
    {{.locale.Tr "settings.cancel"}}
    +
    diff --git a/templates/repo/issue/view_content/update_branch_by_merge.tmpl b/templates/repo/issue/view_content/update_branch_by_merge.tmpl index 6d36a9b45f38..49e4467dc3f4 100644 --- a/templates/repo/issue/view_content/update_branch_by_merge.tmpl +++ b/templates/repo/issue/view_content/update_branch_by_merge.tmpl @@ -19,8 +19,8 @@ diff --git a/templates/repo/issue/view_title.tmpl b/templates/repo/issue/view_title.tmpl index f0ac1e021ec4..2a8381b0b47b 100644 --- a/templates/repo/issue/view_title.tmpl +++ b/templates/repo/issue/view_title.tmpl @@ -1,9 +1,7 @@
    {{if and (or .HasIssuesOrPullsWritePermission .IsIssuePoster) (not .Repository.IsArchived)}} -
    - -
    + {{end}}

    {{RenderIssueTitle $.Context .Issue.Title $.RepoLink $.Repository.ComposeMetas | RenderCodeBlock}} diff --git a/templates/repo/migrate/migrating.tmpl b/templates/repo/migrate/migrating.tmpl index a3552610c47d..cd3c5e754ecb 100644 --- a/templates/repo/migrate/migrating.tmpl +++ b/templates/repo/migrate/migrating.tmpl @@ -72,7 +72,7 @@

    -
    {{.locale.Tr "settings.cancel"}}
    +
    diff --git a/templates/repo/projects/list.tmpl b/templates/repo/projects/list.tmpl index f066f84ea2e8..6833b7d785a7 100644 --- a/templates/repo/projects/list.tmpl +++ b/templates/repo/projects/list.tmpl @@ -86,16 +86,7 @@

    {{.locale.Tr "repo.projects.deletion_desc"}}

    -
    -
    - - {{.locale.Tr "modal.no"}} -
    -
    - - {{.locale.Tr "modal.yes"}} -
    -
    + {{template "base/delete_modal_actions" .}}
    {{end}} {{template "base/footer" .}} diff --git a/templates/repo/projects/view.tmpl b/templates/repo/projects/view.tmpl index bef9cb9bf062..0248b9c6d2c7 100644 --- a/templates/repo/projects/view.tmpl +++ b/templates/repo/projects/view.tmpl @@ -33,7 +33,7 @@
    -
    {{$.locale.Tr "settings.cancel"}}
    +
    @@ -131,7 +131,7 @@
    -
    {{$.locale.Tr "settings.cancel"}}
    +
    @@ -148,7 +148,7 @@
    -
    {{$.locale.Tr "settings.cancel"}}
    +
    @@ -162,8 +162,8 @@ {{$.locale.Tr "repo.projects.column.deletion_desc"}} -
    -
    {{$.locale.Tr "settings.cancel"}}
    +
    {{/* TODO: Convert to base/delete_modal_actions.tmpl? */}} +
    @@ -276,16 +276,7 @@

    {{.locale.Tr "repo.projects.deletion_desc"}}

    -
    -
    - - {{.locale.Tr "modal.no"}} -
    -
    - - {{.locale.Tr "modal.yes"}} -
    -
    + {{template "base/delete_modal_actions" .}} {{end}} diff --git a/templates/repo/release/new.tmpl b/templates/repo/release/new.tmpl index d7c580fed969..8c4df98d1911 100644 --- a/templates/repo/release/new.tmpl +++ b/templates/repo/release/new.tmpl @@ -114,7 +114,7 @@ {{$.locale.Tr "repo.release.delete_release"}} {{if .IsDraft}} - + @@ -125,9 +125,9 @@ {{end}} {{else}} {{if not .tag_name}} - + {{end}} - + diff --git a/templates/repo/search.tmpl b/templates/repo/search.tmpl index 21f758e4a902..ff4e218e2def 100644 --- a/templates/repo/search.tmpl +++ b/templates/repo/search.tmpl @@ -39,9 +39,9 @@
    -
    {{.locale.Tr "settings.cancel"}}
    +
    @@ -958,7 +958,7 @@
    -
    {{.locale.Tr "settings.cancel"}}
    +
    @@ -988,10 +988,7 @@ {{.CsrfTokenHtml}} -
    -
    {{.locale.Tr "settings.cancel"}}
    - -
    + {{template "base/delete_modal_actions" .}} {{end}} diff --git a/templates/repo/settings/webhook/delete_modal.tmpl b/templates/repo/settings/webhook/delete_modal.tmpl index fdc49ada4e37..f455899663e8 100644 --- a/templates/repo/settings/webhook/delete_modal.tmpl +++ b/templates/repo/settings/webhook/delete_modal.tmpl @@ -6,14 +6,5 @@

    {{.locale.Tr "repo.settings.webhook_deletion_desc"}}

    -
    -
    - - {{.locale.Tr "modal.no"}} -
    -
    - - {{.locale.Tr "modal.yes"}} -
    -
    + {{template "base/delete_modal_actions" .}} diff --git a/templates/repo/unicode_escape_prompt.tmpl b/templates/repo/unicode_escape_prompt.tmpl index d55bd0150a1b..12eff6aebe3a 100644 --- a/templates/repo/unicode_escape_prompt.tmpl +++ b/templates/repo/unicode_escape_prompt.tmpl @@ -1,7 +1,7 @@ {{if .EscapeStatus}} {{if .EscapeStatus.HasInvisible}}
    - {{svg "octicon-x" 16 "close inside"}} +
    {{$.root.locale.Tr "repo.invisible_runes_header"}}
    @@ -12,7 +12,7 @@
    {{else if .EscapeStatus.HasAmbiguous}}
    - {{svg "octicon-x" 16 "close inside"}} +
    {{$.root.locale.Tr "repo.ambiguous_runes_header"}}
    diff --git a/templates/shared/actions/runner_list.tmpl b/templates/shared/actions/runner_list.tmpl index eabddbb30cdc..30c52c01b457 100644 --- a/templates/shared/actions/runner_list.tmpl +++ b/templates/shared/actions/runner_list.tmpl @@ -20,9 +20,9 @@
    -
    +
    +
    diff --git a/templates/shared/issuelist.tmpl b/templates/shared/issuelist.tmpl index 16bb3c1ec7fe..ae9cb55d44df 100644 --- a/templates/shared/issuelist.tmpl +++ b/templates/shared/issuelist.tmpl @@ -108,7 +108,7 @@ {{svg "octicon-calendar" 14 "gt-mr-2"}} - + {{end}} diff --git a/templates/shared/secrets/add_list.tmpl b/templates/shared/secrets/add_list.tmpl index 9105b7ad9bf4..4aa5f0ccd578 100644 --- a/templates/shared/secrets/add_list.tmpl +++ b/templates/shared/secrets/add_list.tmpl @@ -1,7 +1,7 @@

    {{.locale.Tr "secrets.secrets"}}
    -
    {{.locale.Tr "secrets.creation"}}
    +

    diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index cb88e175ea5f..9c89b21fcac4 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -138,6 +138,80 @@ } } }, + "/admin/emails": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "List all emails", + "operationId": "adminGetAllEmails", + "parameters": [ + { + "type": "integer", + "description": "page number of results to return (1-based)", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "page size of results", + "name": "limit", + "in": "query" + } + ], + "responses": { + "200": { + "$ref": "#/responses/EmailList" + }, + "403": { + "$ref": "#/responses/forbidden" + } + } + } + }, + "/admin/emails/search": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "Search all emails", + "operationId": "adminSearchEmails", + "parameters": [ + { + "type": "string", + "description": "keyword", + "name": "q", + "in": "query" + }, + { + "type": "integer", + "description": "page number of results to return (1-based)", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "page size of results", + "name": "limit", + "in": "query" + } + ], + "responses": { + "200": { + "$ref": "#/responses/EmailList" + }, + "403": { + "$ref": "#/responses/forbidden" + } + } + } + }, "/admin/hooks": { "get": { "produces": [ @@ -493,6 +567,12 @@ "name": "username", "in": "path", "required": true + }, + { + "type": "boolean", + "description": "purge the user from the system completely", + "name": "purge", + "in": "query" } ], "responses": { @@ -673,6 +753,46 @@ } } }, + "/admin/users/{username}/rename": { + "post": { + "produces": [ + "application/json" + ], + "tags": [ + "admin" + ], + "summary": "Rename a user", + "operationId": "adminRenameUser", + "parameters": [ + { + "type": "string", + "description": "existing username of user", + "name": "username", + "in": "path", + "required": true + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/RenameUserOption" + } + } + ], + "responses": { + "204": { + "$ref": "#/responses/empty" + }, + "403": { + "$ref": "#/responses/forbidden" + }, + "422": { + "$ref": "#/responses/validationError" + } + } + } + }, "/admin/users/{username}/repos": { "post": { "consumes": [ @@ -707,6 +827,9 @@ "201": { "$ref": "#/responses/Repository" }, + "400": { + "$ref": "#/responses/error" + }, "403": { "$ref": "#/responses/forbidden" }, @@ -1920,6 +2043,9 @@ "201": { "$ref": "#/responses/Repository" }, + "400": { + "$ref": "#/responses/error" + }, "403": { "$ref": "#/responses/forbidden" }, @@ -2114,6 +2240,7 @@ "pub", "pypi", "rubygems", + "swift", "vagrant" ], "type": "string", @@ -13375,6 +13502,9 @@ "201": { "$ref": "#/responses/Repository" }, + "400": { + "$ref": "#/responses/error" + }, "409": { "description": "The repository with the same name already exists." }, @@ -16943,6 +17073,15 @@ "type": "boolean", "x-go-name": "Primary" }, + "user_id": { + "type": "integer", + "format": "int64", + "x-go-name": "UserID" + }, + "username": { + "type": "string", + "x-go-name": "UserName" + }, "verified": { "type": "boolean", "x-go-name": "Verified" @@ -19089,6 +19228,22 @@ }, "x-go-package": "code.gitea.io/gitea/modules/structs" }, + "RenameUserOption": { + "description": "RenameUserOption options when renaming a user", + "type": "object", + "required": [ + "new_username" + ], + "properties": { + "new_username": { + "description": "New username for this user. This name cannot be in use yet by any other user.", + "type": "string", + "uniqueItems": true, + "x-go-name": "NewName" + } + }, + "x-go-package": "code.gitea.io/gitea/modules/structs" + }, "RepoCollaboratorPermission": { "description": "RepoCollaboratorPermission to get repository permission for a collaborator", "type": "object", diff --git a/templates/user/auth/grant.tmpl b/templates/user/auth/grant.tmpl index c906db3e0a17..060b67527300 100644 --- a/templates/user/auth/grant.tmpl +++ b/templates/user/auth/grant.tmpl @@ -23,7 +23,7 @@ - + Cancel
    diff --git a/templates/user/auth/webauthn_error.tmpl b/templates/user/auth/webauthn_error.tmpl index 447d289a2807..b6467de1aad8 100644 --- a/templates/user/auth/webauthn_error.tmpl +++ b/templates/user/auth/webauthn_error.tmpl @@ -17,6 +17,6 @@
    -
    {{.locale.Tr "cancel"}}
    +
    diff --git a/templates/user/dashboard/repolist.tmpl b/templates/user/dashboard/repolist.tmpl index 97234176bd21..0a8f427f9da1 100644 --- a/templates/user/dashboard/repolist.tmpl +++ b/templates/user/dashboard/repolist.tmpl @@ -1,181 +1,54 @@ -
    - -
    + + +
    diff --git a/templates/user/settings/account.tmpl b/templates/user/settings/account.tmpl index 9a57bd572267..53f7d021e0b6 100644 --- a/templates/user/settings/account.tmpl +++ b/templates/user/settings/account.tmpl @@ -151,9 +151,9 @@
    -
    +
    + {{.locale.Tr "auth.forgot_password"}}
    diff --git a/templates/user/settings/applications.tmpl b/templates/user/settings/applications.tmpl index b0cd37d44c47..18132c4a7534 100644 --- a/templates/user/settings/applications.tmpl +++ b/templates/user/settings/applications.tmpl @@ -276,15 +276,16 @@

    {{.locale.Tr "settings.access_token_deletion_desc"}}

    -
    -
    - + +
    {{/* TODO: Convert to base/delete_modal_actions.tmpl */}} +
    -
    - + +
    +
    diff --git a/templates/user/settings/keys_gpg.tmpl b/templates/user/settings/keys_gpg.tmpl index c80890940a44..93ca12a0880c 100644 --- a/templates/user/settings/keys_gpg.tmpl +++ b/templates/user/settings/keys_gpg.tmpl @@ -1,7 +1,7 @@

    {{.locale.Tr "settings.manage_gpg_keys"}}
    -
    {{.locale.Tr "settings.add_key"}}
    +

    diff --git a/templates/user/settings/keys_principal.tmpl b/templates/user/settings/keys_principal.tmpl index cc1152b739a6..8012b874cdcf 100644 --- a/templates/user/settings/keys_principal.tmpl +++ b/templates/user/settings/keys_principal.tmpl @@ -3,9 +3,9 @@ {{.locale.Tr "settings.manage_ssh_principals"}}
    {{if not .DisableSSH}} -
    {{.locale.Tr "settings.add_new_principal"}}
    + {{else}} -
    {{.locale.Tr "settings.ssh_disabled"}}
    + {{end}}
    diff --git a/templates/user/settings/keys_ssh.tmpl b/templates/user/settings/keys_ssh.tmpl index 891959d35145..1ff4dab34e31 100644 --- a/templates/user/settings/keys_ssh.tmpl +++ b/templates/user/settings/keys_ssh.tmpl @@ -2,11 +2,11 @@ {{.locale.Tr "settings.manage_ssh_keys"}}
    {{if not .DisableSSH}} -
    +
    + {{else}} -
    {{.locale.Tr "settings.ssh_disabled"}}
    + {{end}}
    diff --git a/templates/user/settings/repos.tmpl b/templates/user/settings/repos.tmpl index 902b3fb2f33b..2e107ca7fa1a 100644 --- a/templates/user/settings/repos.tmpl +++ b/templates/user/settings/repos.tmpl @@ -50,16 +50,7 @@ {{$.CsrfTokenHtml}} -
    -
    - - {{$.locale.Tr "modal.no"}} -
    - -
    + {{template "base/delete_modal_actions" .}}
    {{end}} @@ -77,16 +68,7 @@ {{$.CsrfTokenHtml}} -
    -
    - - {{$.locale.Tr "modal.no"}} -
    - -
    + {{template "base/delete_modal_actions" .}} {{end}} diff --git a/templates/user/settings/security/twofa.tmpl b/templates/user/settings/security/twofa.tmpl index a4da94762886..1a0a8a6432c0 100644 --- a/templates/user/settings/security/twofa.tmpl +++ b/templates/user/settings/security/twofa.tmpl @@ -13,7 +13,7 @@
    {{.CsrfTokenHtml}}

    {{.locale.Tr "settings.twofa_disable_note"}}

    -
    {{$.locale.Tr "settings.twofa_disable"}}
    +
    {{else}}

    {{.locale.Tr "settings.twofa_not_enrolled"}}

    diff --git a/tests/integration/api_packages_swift_test.go b/tests/integration/api_packages_swift_test.go new file mode 100644 index 000000000000..a3035ea60485 --- /dev/null +++ b/tests/integration/api_packages_swift_test.go @@ -0,0 +1,326 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package integration + +import ( + "archive/zip" + "bytes" + "fmt" + "io" + "mime/multipart" + "net/http" + "strings" + "testing" + + "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/models/packages" + "code.gitea.io/gitea/models/unittest" + user_model "code.gitea.io/gitea/models/user" + swift_module "code.gitea.io/gitea/modules/packages/swift" + "code.gitea.io/gitea/modules/setting" + swift_router "code.gitea.io/gitea/routers/api/packages/swift" + "code.gitea.io/gitea/tests" + + "github.com/stretchr/testify/assert" +) + +func TestPackageSwift(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + + packageScope := "test-scope" + packageName := "test_package" + packageID := packageScope + "." + packageName + packageVersion := "1.0.3" + packageAuthor := "KN4CK3R" + packageDescription := "Gitea Test Package" + packageRepositoryURL := "https://gitea.io/gitea/gitea" + contentManifest1 := "// swift-tools-version:5.7\n//\n// Package.swift" + contentManifest2 := "// swift-tools-version:5.6\n//\n// Package@swift-5.6.swift" + + url := fmt.Sprintf("/api/packages/%s/swift", user.Name) + + t.Run("CheckAcceptMediaType", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + for _, sub := range []string{ + "/scope/package", + "/scope/package.json", + "/scope/package/1.0.0", + "/scope/package/1.0.0.json", + "/scope/package/1.0.0.zip", + "/scope/package/1.0.0/Package.swift", + "/identifiers", + } { + req := NewRequest(t, "GET", url+sub) + req.Header.Add("Accept", "application/unknown") + resp := MakeRequest(t, req, http.StatusBadRequest) + + assert.Equal(t, "1", resp.Header().Get("Content-Version")) + assert.Equal(t, "application/problem+json", resp.Header().Get("Content-Type")) + } + + req := NewRequestWithBody(t, "PUT", url+"/scope/package/1.0.0", strings.NewReader("")) + req = AddBasicAuthHeader(req, user.Name) + req.Header.Add("Accept", "application/unknown") + resp := MakeRequest(t, req, http.StatusBadRequest) + + assert.Equal(t, "1", resp.Header().Get("Content-Version")) + assert.Equal(t, "application/problem+json", resp.Header().Get("Content-Type")) + }) + + t.Run("Upload", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + uploadPackage := func(t *testing.T, url string, expectedStatus int, sr io.Reader, metadata string) { + var body bytes.Buffer + mpw := multipart.NewWriter(&body) + + part, _ := mpw.CreateFormFile("source-archive", "source-archive.zip") + io.Copy(part, sr) + + if metadata != "" { + mpw.WriteField("metadata", metadata) + } + + mpw.Close() + + req := NewRequestWithBody(t, "PUT", url, &body) + req.Header.Add("Content-Type", mpw.FormDataContentType()) + req.Header.Add("Accept", swift_router.AcceptJSON) + req = AddBasicAuthHeader(req, user.Name) + MakeRequest(t, req, expectedStatus) + } + + createArchive := func(files map[string]string) *bytes.Buffer { + var buf bytes.Buffer + zw := zip.NewWriter(&buf) + for filename, content := range files { + w, _ := zw.Create(filename) + w.Write([]byte(content)) + } + zw.Close() + return &buf + } + + for _, triple := range []string{"/sc_ope/package/1.0.0", "/scope/pack~age/1.0.0", "/scope/package/1_0.0"} { + req := NewRequestWithBody(t, "PUT", url+triple, bytes.NewReader([]byte{})) + req = AddBasicAuthHeader(req, user.Name) + resp := MakeRequest(t, req, http.StatusBadRequest) + + assert.Equal(t, "1", resp.Header().Get("Content-Version")) + assert.Equal(t, "application/problem+json", resp.Header().Get("Content-Type")) + } + + uploadURL := fmt.Sprintf("%s/%s/%s/%s", url, packageScope, packageName, packageVersion) + + req := NewRequestWithBody(t, "PUT", uploadURL, bytes.NewReader([]byte{})) + MakeRequest(t, req, http.StatusUnauthorized) + + uploadPackage( + t, + uploadURL, + http.StatusCreated, + createArchive(map[string]string{ + "Package.swift": contentManifest1, + "Package@swift-5.6.swift": contentManifest2, + }), + `{"name":"`+packageName+`","version":"`+packageVersion+`","description":"`+packageDescription+`","codeRepository":"`+packageRepositoryURL+`","author":{"givenName":"`+packageAuthor+`"},"repositoryURLs":["`+packageRepositoryURL+`"]}`, + ) + + pvs, err := packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypeSwift) + assert.NoError(t, err) + assert.Len(t, pvs, 1) + + pd, err := packages.GetPackageDescriptor(db.DefaultContext, pvs[0]) + assert.NoError(t, err) + assert.NotNil(t, pd.SemVer) + assert.Equal(t, packageID, pd.Package.Name) + assert.Equal(t, packageVersion, pd.Version.Version) + assert.IsType(t, &swift_module.Metadata{}, pd.Metadata) + metadata := pd.Metadata.(*swift_module.Metadata) + assert.Equal(t, packageDescription, metadata.Description) + assert.Len(t, metadata.Manifests, 2) + assert.Equal(t, contentManifest1, metadata.Manifests[""].Content) + assert.Equal(t, contentManifest2, metadata.Manifests["5.6"].Content) + assert.Len(t, pd.VersionProperties, 1) + assert.Equal(t, packageRepositoryURL, pd.VersionProperties.GetByName(swift_module.PropertyRepositoryURL)) + + pfs, err := packages.GetFilesByVersionID(db.DefaultContext, pvs[0].ID) + assert.NoError(t, err) + assert.Len(t, pfs, 1) + assert.Equal(t, fmt.Sprintf("%s-%s.zip", packageName, packageVersion), pfs[0].Name) + assert.True(t, pfs[0].IsLead) + + uploadPackage( + t, + uploadURL, + http.StatusConflict, + createArchive(map[string]string{ + "Package.swift": contentManifest1, + }), + "", + ) + }) + + t.Run("Download", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + req := NewRequest(t, "GET", fmt.Sprintf("%s/%s/%s/%s.zip", url, packageScope, packageName, packageVersion)) + req = AddBasicAuthHeader(req, user.Name) + req.Header.Add("Accept", swift_router.AcceptZip) + resp := MakeRequest(t, req, http.StatusOK) + + assert.Equal(t, "1", resp.Header().Get("Content-Version")) + assert.Equal(t, "application/zip", resp.Header().Get("Content-Type")) + + pv, err := packages.GetVersionByNameAndVersion(db.DefaultContext, user.ID, packages.TypeSwift, packageID, packageVersion) + assert.NotNil(t, pv) + assert.NoError(t, err) + + pd, err := packages.GetPackageDescriptor(db.DefaultContext, pv) + assert.NoError(t, err) + assert.Equal(t, "sha256="+pd.Files[0].Blob.HashSHA256, resp.Header().Get("Digest")) + }) + + t.Run("EnumeratePackageVersions", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + req := NewRequest(t, "GET", fmt.Sprintf("%s/%s/%s", url, packageScope, packageName)) + req = AddBasicAuthHeader(req, user.Name) + req.Header.Add("Accept", swift_router.AcceptJSON) + resp := MakeRequest(t, req, http.StatusOK) + + versionURL := setting.AppURL + url[1:] + fmt.Sprintf("/%s/%s/%s", packageScope, packageName, packageVersion) + + assert.Equal(t, "1", resp.Header().Get("Content-Version")) + assert.Equal(t, fmt.Sprintf(`<%s>; rel="latest-version"`, versionURL), resp.Header().Get("Link")) + + body := resp.Body.String() + + var result *swift_router.EnumeratePackageVersionsResponse + DecodeJSON(t, resp, &result) + + assert.Len(t, result.Releases, 1) + assert.Contains(t, result.Releases, packageVersion) + assert.Equal(t, versionURL, result.Releases[packageVersion].URL) + + req = NewRequest(t, "GET", fmt.Sprintf("%s/%s/%s.json", url, packageScope, packageName)) + req = AddBasicAuthHeader(req, user.Name) + resp = MakeRequest(t, req, http.StatusOK) + + assert.Equal(t, body, resp.Body.String()) + }) + + t.Run("PackageVersionMetadata", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + req := NewRequest(t, "GET", fmt.Sprintf("%s/%s/%s/%s", url, packageScope, packageName, packageVersion)) + req = AddBasicAuthHeader(req, user.Name) + req.Header.Add("Accept", swift_router.AcceptJSON) + resp := MakeRequest(t, req, http.StatusOK) + + assert.Equal(t, "1", resp.Header().Get("Content-Version")) + + body := resp.Body.String() + + var result *swift_router.PackageVersionMetadataResponse + DecodeJSON(t, resp, &result) + + pv, err := packages.GetVersionByNameAndVersion(db.DefaultContext, user.ID, packages.TypeSwift, packageID, packageVersion) + assert.NotNil(t, pv) + assert.NoError(t, err) + + pd, err := packages.GetPackageDescriptor(db.DefaultContext, pv) + assert.NoError(t, err) + + assert.Equal(t, packageID, result.ID) + assert.Equal(t, packageVersion, result.Version) + assert.Len(t, result.Resources, 1) + assert.Equal(t, "source-archive", result.Resources[0].Name) + assert.Equal(t, "application/zip", result.Resources[0].Type) + assert.Equal(t, pd.Files[0].Blob.HashSHA256, result.Resources[0].Checksum) + assert.Equal(t, "SoftwareSourceCode", result.Metadata.Type) + assert.Equal(t, packageName, result.Metadata.Name) + assert.Equal(t, packageVersion, result.Metadata.Version) + assert.Equal(t, packageDescription, result.Metadata.Description) + assert.Equal(t, "Swift", result.Metadata.ProgrammingLanguage.Name) + assert.Equal(t, packageAuthor, result.Metadata.Author.GivenName) + + req = NewRequest(t, "GET", fmt.Sprintf("%s/%s/%s/%s.json", url, packageScope, packageName, packageVersion)) + req = AddBasicAuthHeader(req, user.Name) + resp = MakeRequest(t, req, http.StatusOK) + + assert.Equal(t, body, resp.Body.String()) + }) + + t.Run("DownloadManifest", func(t *testing.T) { + manifestURL := fmt.Sprintf("%s/%s/%s/%s/Package.swift", url, packageScope, packageName, packageVersion) + + t.Run("Default", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + req := NewRequest(t, "GET", manifestURL) + req = AddBasicAuthHeader(req, user.Name) + req.Header.Add("Accept", swift_router.AcceptSwift) + resp := MakeRequest(t, req, http.StatusOK) + + assert.Equal(t, "1", resp.Header().Get("Content-Version")) + assert.Equal(t, "text/x-swift", resp.Header().Get("Content-Type")) + assert.Equal(t, contentManifest1, resp.Body.String()) + }) + + t.Run("DifferentVersion", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + req := NewRequest(t, "GET", manifestURL+"?swift-version=5.6") + req = AddBasicAuthHeader(req, user.Name) + resp := MakeRequest(t, req, http.StatusOK) + + assert.Equal(t, "1", resp.Header().Get("Content-Version")) + assert.Equal(t, "text/x-swift", resp.Header().Get("Content-Type")) + assert.Equal(t, contentManifest2, resp.Body.String()) + + req = NewRequest(t, "GET", manifestURL+"?swift-version=5.6.0") + req = AddBasicAuthHeader(req, user.Name) + MakeRequest(t, req, http.StatusOK) + }) + + t.Run("Redirect", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + req := NewRequest(t, "GET", manifestURL+"?swift-version=1.0") + req = AddBasicAuthHeader(req, user.Name) + resp := MakeRequest(t, req, http.StatusSeeOther) + + assert.Equal(t, "1", resp.Header().Get("Content-Version")) + assert.Equal(t, setting.AppURL+url[1:]+fmt.Sprintf("/%s/%s/%s/Package.swift", packageScope, packageName, packageVersion), resp.Header().Get("Location")) + }) + }) + + t.Run("LookupPackageIdentifiers", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + req := NewRequest(t, "GET", url+"/identifiers") + req.Header.Add("Accept", swift_router.AcceptJSON) + resp := MakeRequest(t, req, http.StatusBadRequest) + + assert.Equal(t, "1", resp.Header().Get("Content-Version")) + assert.Equal(t, "application/problem+json", resp.Header().Get("Content-Type")) + + req = NewRequest(t, "GET", url+"/identifiers?url=https://unknown.host/") + MakeRequest(t, req, http.StatusNotFound) + + req = NewRequest(t, "GET", url+"/identifiers?url="+packageRepositoryURL) + req.Header.Add("Accept", swift_router.AcceptJSON) + resp = MakeRequest(t, req, http.StatusOK) + + var result *swift_router.LookupPackageIdentifiersResponse + DecodeJSON(t, resp, &result) + + assert.Len(t, result.Identifiers, 1) + assert.Equal(t, packageID, result.Identifiers[0]) + }) +} diff --git a/tests/test_utils.go b/tests/test_utils.go index e3e5becfbedf..102dd3d298fb 100644 --- a/tests/test_utils.go +++ b/tests/test_utils.go @@ -201,7 +201,7 @@ func PrepareTestEnv(t testing.TB, skip ...int) func() { lfsFixtures, err := storage.NewStorage("", storage.LocalStorageConfig{Path: path.Join(filepath.Dir(setting.AppPath), "tests/gitea-lfs-meta")}) assert.NoError(t, err) assert.NoError(t, storage.Clean(storage.LFS)) - assert.NoError(t, lfsFixtures.IterateObjects(func(path string, _ storage.Object) error { + assert.NoError(t, lfsFixtures.IterateObjects("", func(path string, _ storage.Object) error { _, err := storage.Copy(storage.LFS, path, lfsFixtures, path) return err })) @@ -258,7 +258,7 @@ func ResetFixtures(t *testing.T) { lfsFixtures, err := storage.NewStorage("", storage.LocalStorageConfig{Path: path.Join(filepath.Dir(setting.AppPath), "tests/gitea-lfs-meta")}) assert.NoError(t, err) assert.NoError(t, storage.Clean(storage.LFS)) - assert.NoError(t, lfsFixtures.IterateObjects(func(path string, _ storage.Object) error { + assert.NoError(t, lfsFixtures.IterateObjects("", func(path string, _ storage.Object) error { _, err := storage.Copy(storage.LFS, path, lfsFixtures, path) return err })) diff --git a/web_src/css/admin.css b/web_src/css/admin.css new file mode 100644 index 000000000000..00ed675e2d57 --- /dev/null +++ b/web_src/css/admin.css @@ -0,0 +1,110 @@ +.admin.hooks .list > .item:not(:first-child) { + border-top: 1px solid var(--color-secondary); + padding: 0.25rem 1rem; + margin: 12px -1rem -1rem; +} + +.admin .table.segment { + padding: 0; + font-size: 13px; + overflow-x: auto; +} + +.admin .table.segment:not(.striped) thead th:last-child { + padding-right: 5px !important; +} + +.admin .table.segment th { + padding-top: 5px; + padding-bottom: 5px; +} + +.admin .table.segment:not(.select) th:first-of-type, +.admin .table.segment:not(.select) td:first-of-type { + padding-left: 15px !important; +} + +.admin .table.segment form tbody button[type="submit"] { + padding: 5px 8px; +} + +.admin .settings .button.adopt, +.admin .settings .button.delete { + margin-top: -15px; + margin-bottom: -15px; +} + +.admin .settings .button.adopt .label, +.admin .settings .button.delete .label { + vertical-align: middle; +} + +.admin.user .email { + max-width: 200px; +} + +.admin dl.admin-dl-horizontal { + padding: 20px; + margin: 0; +} + +.admin dl.admin-dl-horizontal dd { + margin-left: 275px; +} + +@media (max-width: 767px) { + .admin dl.admin-dl-horizontal dd { + margin-left: 5%; + } +} + +.admin dl.admin-dl-horizontal dt { + font-weight: 600; + float: left; + width: 285px; + clear: left; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +@media (max-width: 767px) { + .admin dl.admin-dl-horizontal dt { + width: auto; + margin-right: 0.5em; + } +} + +.admin.config #test-mail-btn { + margin-left: 5px; +} + +.admin code, +.admin pre { + white-space: pre-wrap; + word-wrap: break-word; +} + +@media (max-width: 767px) { + .admin #notice-table .notice-description { + max-width: 80vw; + } +} + +@media (min-width: 768px) and (max-width: 991px) { + .admin #notice-table .notice-description { + max-width: 360px; + } +} + +@media (min-width: 992px) and (max-width: 1200px) { + .admin #notice-table .notice-description { + max-width: 510px; + } +} + +@media (min-width: 1201px) { + .admin #notice-table .notice-description { + max-width: 640px; + } +} diff --git a/web_src/less/animations.less b/web_src/css/animations.css similarity index 100% rename from web_src/less/animations.less rename to web_src/css/animations.css diff --git a/web_src/less/_base.less b/web_src/css/base.css similarity index 77% rename from web_src/less/_base.less rename to web_src/css/base.css index 1cf65e784cd4..225359b765ce 100644 --- a/web_src/less/_base.less +++ b/web_src/css/base.css @@ -7,8 +7,8 @@ --checkbox-mask-checked: url('data:image/svg+xml;utf8,'); --checkbox-mask-indeterminate: url('data:image/svg+xml;utf8,'); /* non-color variables */ - --border-radius: .28571429rem; - --opacity-disabled: .55; + --border-radius: 0.28571429rem; + --opacity-disabled: 0.55; --height-loading: 12rem; /* base colors */ --color-primary: #4183c4; @@ -183,7 +183,6 @@ --color-accent: var(--color-primary-light-1); --color-small-accent: var(--color-primary-light-6); --color-active-line: #fffbdd; - accent-color: var(--color-accent); color-scheme: light; } @@ -200,7 +199,7 @@ pre, code, kbd, samp { - font-size: .9em; /* compensate for monospace fonts being usually slightly larger */ + font-size: 0.9em; /* compensate for monospace fonts being usually slightly larger */ font-family: var(--fonts-monospace); } @@ -226,7 +225,7 @@ body { @supports (overflow: overlay) { body { - overflow: overlay; // stylelint-disable-line + overflow: overlay; /* stylelint-disable-line */ scrollbar-gutter: stable; } } @@ -253,12 +252,15 @@ progress { border: none; overflow: hidden; } + progress::-webkit-progress-bar { background: var(--color-secondary-dark-1); } + progress::-webkit-progress-value { background-color: var(--color-accent); } + progress::-moz-progress-bar { background-color: var(--color-accent); } @@ -272,17 +274,21 @@ progress::-moz-progress-bar { width: 10px; height: 10px; } + ::-webkit-scrollbar-thumb { box-shadow: inset 0 0 0 6px var(--color-primary); border: 2px solid transparent; border-radius: 5px !important; } + ::-webkit-scrollbar-thumb:window-inactive { box-shadow: inset 0 0 0 6px var(--color-primary); } + ::-webkit-scrollbar-thumb:hover { box-shadow: inset 0 0 0 6px var(--color-primary-dark-2); } + ::-webkit-scrollbar-corner { background: transparent; } @@ -293,6 +299,7 @@ progress::-moz-progress-bar { background: var(--color-light); border-radius: var(--border-radius); } + ::file-selector-button:hover { color: var(--color-text); background: var(--color-hover); @@ -310,6 +317,17 @@ progress::-moz-progress-bar { opacity: 1 !important; } +.unselectable, +.button, +.lines-num, +.lines-commit, +.lines-commit .blame-info, +.ellipsis-button { + -webkit-touch-callout: none; + -webkit-user-select: none; + user-select: none; +} + a, .ui.breadcrumb a { color: var(--color-primary); @@ -350,15 +368,18 @@ a.label, .ui.red.buttons .button { background: var(--color-red); } + .ui.red.button:hover, .ui.red.buttons .button:hover { background: var(--color-red-light); } + .ui.basic.red.buttons .button, .ui.basic.red.button { color: var(--color-red); border-color: var(--color-red); } + .ui.basic.red.buttons .button:hover, .ui.basic.red.button:hover { color: var(--color-red-light); @@ -371,15 +392,18 @@ a.label, .ui.orange.buttons .button { background: var(--color-orange); } + .ui.orange.button:hover, .ui.orange.buttons .button:hover { background: var(--color-orange-light); } + .ui.basic.orange.buttons .button, .ui.basic.orange.button { color: var(--color-orange); border-color: var(--color-orange); } + .ui.basic.orange.buttons .button:hover, .ui.basic.orange.button:hover { color: var(--color-orange-light); @@ -392,15 +416,18 @@ a.label, .ui.yellow.buttons .button { background: var(--color-yellow); } + .ui.yellow.button:hover, .ui.yellow.buttons .button:hover { background: var(--color-yellow-light); } + .ui.basic.yellow.buttons .button, .ui.basic.yellow.button { color: var(--color-yellow); border-color: var(--color-yellow); } + .ui.basic.yellow.buttons .button:hover, .ui.basic.yellow.button:hover { color: var(--color-yellow-light); @@ -413,15 +440,18 @@ a.label, .ui.olive.buttons .button { background: var(--color-olive); } + .ui.olive.button:hover, .ui.olive.buttons .button:hover { background: var(--color-olive-light); } + .ui.basic.olive.buttons .button, .ui.basic.olive.button { color: var(--color-olive); border-color: var(--color-olive); } + .ui.basic.olive.buttons .button:hover, .ui.basic.olive.button:hover { color: var(--color-olive-light); @@ -434,15 +464,18 @@ a.label, .ui.green.buttons .button { background: var(--color-green); } + .ui.green.button:hover, .ui.green.buttons .button:hover { background: var(--color-green-light); } + .ui.basic.green.buttons .button, .ui.basic.green.button { color: var(--color-green); border-color: var(--color-green); } + .ui.basic.green.buttons .button:hover, .ui.basic.green.button:hover { color: var(--color-green-light); @@ -455,15 +488,18 @@ a.label, .ui.teal.buttons .button { background: var(--color-teal); } + .ui.teal.button:hover, .ui.teal.buttons .button:hover { background: var(--color-teal-light); } + .ui.basic.teal.buttons .button, .ui.basic.teal.button { color: var(--color-teal); border-color: var(--color-teal); } + .ui.basic.teal.buttons .button:hover, .ui.basic.teal.button:hover { color: var(--color-teal-light); @@ -476,15 +512,18 @@ a.label, .ui.blue.buttons .button { background: var(--color-blue); } + .ui.blue.button:hover, .ui.blue.buttons .button:hover { background: var(--color-blue-light); } + .ui.basic.blue.buttons .button, .ui.basic.blue.button { color: var(--color-blue); border-color: var(--color-blue); } + .ui.basic.blue.buttons .button:hover, .ui.basic.blue.button:hover { color: var(--color-blue-light); @@ -497,15 +536,18 @@ a.label, .ui.violet.buttons .button { background: var(--color-violet); } + .ui.violet.button:hover, .ui.violet.buttons .button:hover { background: var(--color-violet-light); } + .ui.basic.violet.buttons .button, .ui.basic.violet.button { color: var(--color-violet); border-color: var(--color-violet); } + .ui.basic.violet.buttons .button:hover, .ui.basic.violet.button:hover { color: var(--color-violet-light); @@ -518,15 +560,18 @@ a.label, .ui.purple.buttons .button { background: var(--color-purple); } + .ui.purple.button:hover, .ui.purple.buttons .button:hover { background: var(--color-purple-light); } + .ui.basic.purple.buttons .button, .ui.basic.purple.button { color: var(--color-purple); border-color: var(--color-purple); } + .ui.basic.purple.buttons .button:hover, .ui.basic.purple.button:hover { color: var(--color-purple-light); @@ -539,15 +584,18 @@ a.label, .ui.pink.buttons .button { background: var(--color-pink); } + .ui.pink.button:hover, .ui.pink.buttons .button:hover { background: var(--color-pink-light); } + .ui.basic.pink.buttons .button, .ui.basic.pink.button { color: var(--color-pink); border-color: var(--color-pink); } + .ui.basic.pink.buttons .button:hover, .ui.basic.pink.button:hover { color: var(--color-pink-light); @@ -560,15 +608,18 @@ a.label, .ui.brown.buttons .button { background: var(--color-brown); } + .ui.brown.button:hover, .ui.brown.buttons .button:hover { background: var(--color-brown-light); } + .ui.basic.brown.buttons .button, .ui.basic.brown.button { color: var(--color-brown); border-color: var(--color-brown); } + .ui.basic.brown.buttons .button:hover, .ui.basic.brown.button:hover { color: var(--color-brown-light); @@ -581,15 +632,18 @@ a.label, .ui.grey.buttons .button { background: var(--color-grey); } + .ui.grey.button:hover, .ui.grey.buttons .button:hover { background: var(--color-grey-light); } + .ui.basic.grey.buttons .button, .ui.basic.grey.button { color: var(--color-grey); border-color: var(--color-grey); } + .ui.basic.grey.buttons .button:hover, .ui.basic.grey.button:hover { color: var(--color-grey-light); @@ -602,15 +656,18 @@ a.label, .ui.black.buttons .button { background: var(--color-black); } + .ui.black.button:hover, .ui.black.buttons .button:hover { background: var(--color-black-light); } + .ui.basic.black.buttons .button, .ui.basic.black.button { color: var(--color-black); border-color: var(--color-black); } + .ui.basic.black.buttons .button:hover, .ui.basic.black.button:hover { color: var(--color-black-light); @@ -664,21 +721,12 @@ a.label, background: var(--color-hover); } -.unselectable { - -webkit-touch-callout: none; - -webkit-user-select: none; - user-select: none; -} - -.button { - &:extend(.unselectable); -} - .issue-title code { padding: 2px 4px; border-radius: 6px; background-color: var(--color-markup-code-block); } + /* try to match button with no icons in height */ .icon-button { padding-top: 7.42px !important; @@ -720,10 +768,10 @@ a.label, /* currently used for search bar dropdowns in repo search and explore code */ .ui.action.input:not([class*="left action"]) > .ui.dropdown.selection { min-width: 10em; +} - &:not(:focus,:hover) { - border-right-color: transparent; - } +.ui.action.input:not([class*="left action"]) > .ui.dropdown.selection:not(:focus,:hover) { + border-right-color: transparent; } .ui.action.input:not([class*="left action"]) > input:focus { @@ -738,10 +786,11 @@ a.label, .ui.menu .item { color: var(--color-text); + user-select: auto; +} - > .svg { - margin-right: .35em; - } +.ui.menu .item > .svg { + margin-right: 0.35em; } .ui.menu .item > .label { @@ -812,11 +861,12 @@ a.label, /* fix misaligned images in webhook dropdown */ .ui.dropdown .menu > .item > img { - margin-top: -.25rem; - margin-bottom: -.25rem; + margin-top: -0.25rem; + margin-bottom: -0.25rem; } + .ui.dropdown .menu > .item > svg.img { - margin-right: .78571429rem; + margin-right: 0.78571429rem; } .ui.selection.dropdown .menu > .item { @@ -871,8 +921,8 @@ a.label, } .ui.secondary.menu.tight .item { - padding-left: .85714286em; - padding-right: .85714286em; + padding-left: 0.85714286em; + padding-right: 0.85714286em; } .ui.menu .dropdown.item .menu { @@ -1179,7 +1229,7 @@ a.ui.card:hover, } /* enable fluid page widths for medium size viewports */ -@media @mediaMdAndUp and @mediaLgAndDown { +@media (min-width: 768px) and (max-width: 1200px) { .ui.ui.ui.container:not(.fluid) { width: calc(100vw - 3em); } @@ -1189,83 +1239,79 @@ a.ui.card:hover, z-index: 900; left: 0; margin: 0 !important; +} - &.light { - background: var(--color-header-bar); - border-bottom: 1px solid var(--color-secondary); - } +.following.bar.light { + background: var(--color-header-bar); + border-bottom: 1px solid var(--color-secondary); +} - .column .menu { - margin-top: 0; - } +.following.bar .column .menu { + margin-top: 0; +} - .top.menu a.item.brand { - padding-left: 0; - } +.following.bar .top.menu a.item.brand { + padding-left: 0; +} - .top.menu a.item:hover, - .top.menu .dropdown.item:hover, - .top.menu .dropdown.item.active { - background-color: transparent; - } +.following.bar .top.menu a.item:hover, +.following.bar .top.menu .dropdown.item:hover, +.following.bar .top.menu .dropdown.item.active { + background-color: transparent; +} - .top.menu a.item:hover { - color: rgba(0, 0, 0, .45); - } +.following.bar .top.menu a.item:hover { + color: rgba(0, 0, 0, 0.45); +} - .top.menu .menu { - z-index: 900; - } +.following.bar .top.menu .menu { + z-index: 900; +} - .fitted .svg { - margin-right: 0; - vertical-align: middle; - } +.following.bar .fitted .svg { + margin-right: 0; + vertical-align: middle; +} - .searchbox { - background-color: var(--color-input-background) !important; - } +.following.bar .searchbox { + background-color: var(--color-input-background) !important; +} - .text .svg { - width: 16px; - text-align: center; - } +.following.bar .text .svg { + width: 16px; + text-align: center; +} - #navbar { - width: 100vw; - min-height: 52px; - padding: 0 .5rem; - } +.following.bar #navbar { + width: 100vw; + min-height: 52px; + padding: 0 0.5rem; +} - #navbar .brand { - margin: 0; - } +.following.bar #navbar .brand { + margin: 0; +} - #navbar .dropdown .avatar { - margin-right: 0 !important; - } +.following.bar #navbar .dropdown .avatar { + margin-right: 0 !important; +} - @media @mediaSm { - #navbar:not(.shown) > *:not(:first-child) { - display: none; - } +@media (max-width: 767px) { + .following.bar #navbar:not(.shown) > *:not(:first-child) { + display: none; } } .right.stackable.menu { - // responsive fix: this makes sure that the right menu when the page - // is on mobile view will have elements stacked on top of each other. - // no, stackable won't work on right menus. + /* responsive fix: this makes sure that the right menu when the page */ + /* is on mobile view will have elements stacked on top of each other. */ + /* no, stackable won't work on right menus. */ margin-left: auto; display: flex; align-items: inherit; flex-direction: inherit; } -.ui.dropdown .menu { - border-color: var(--color-secondary); -} - .ui.pagination.menu .active.item { color: var(--color-text); background: var(--color-active); @@ -1282,7 +1328,7 @@ a.ui.card:hover, .ui.loading.form > *, .ui.loading.segment > * { - opacity: .35; + opacity: 0.35; } .ui.form .fields.error .field textarea, @@ -1358,8 +1404,8 @@ a.ui.card:hover, border-color: var(--color-error-border) !important; } -// A fix for text visibility issue in Chrome autofill in dark mode. -// It's a problem from Formatic UI, and this rule overrides it. +/* A fix for text visibility issue in Chrome autofill in dark mode. */ +/* It's a problem from Formatic UI, and this rule overrides it. */ .ui.form .field.field input:-webkit-autofill { -webkit-text-fill-color: var(--color-black) !important; } @@ -1372,372 +1418,384 @@ a.ui.card:hover, visibility: hidden; } -.text.primary { color: var(--color-primary) !important; } -.text.red { color: var(--color-red) !important; } -.text.orange { color: var(--color-orange) !important; } -.text.yellow { color: var(--color-yellow) !important; } -.text.olive { color: var(--color-olive) !important; } -.text.green { color: var(--color-green) !important; } -.text.teal { color: var(--color-teal) !important; } -.text.blue { color: var(--color-blue) !important; } -.text.violet { color: var(--color-violet) !important; } -.text.purple { color: var(--color-purple) !important; } -.text.pink { color: var(--color-pink) !important; } -.text.brown { color: var(--color-brown) !important; } -.text.black { color: var(--color-text) !important; } -.text.grey { color: var(--color-text-light) !important; } -.text.light.grey { color: var(--color-grey-light) !important; } -.text.gold { color: var(--color-gold) !important; } - -.ui { - &.left:not(.action) { - float: left; - } +.text.primary { + color: var(--color-primary) !important; +} - &.right:not(.action) { - float: right; - } +.text.red { + color: var(--color-red) !important; +} - &.menu .item { - user-select: auto; - } +.text.orange { + color: var(--color-orange) !important; +} - &.container { - &.fluid { - &.padded { - padding: 0 10px; - } - } - } +.text.yellow { + color: var(--color-yellow) !important; +} - &.form { - .ui.button { - font-weight: normal; - } - } +.text.olive { + color: var(--color-olive) !important; +} - &.floating.label { - z-index: 10; - } +.text.green { + color: var(--color-green) !important; +} - &.transparent.label { - background-color: transparent; - } +.text.teal { + color: var(--color-teal) !important; +} - &.menu, - &.vertical.menu, - &.segment { - box-shadow: none; - } +.text.blue { + color: var(--color-blue) !important; +} - /* Override semantic selector '.ui.menu:not(.vertical) .item > .button' */ - /* This fixes the commit graph button on the commits page */ +.text.violet { + color: var(--color-violet) !important; +} - .menu:not(.vertical) .item > .button.compact { - padding: .58928571em 1.125em; - } +.text.purple { + color: var(--color-purple) !important; +} - .menu:not(.vertical) .item > .button.small { - font-size: .92857143rem; - } +.text.pink { + color: var(--color-pink) !important; +} - &.menu .ui.dropdown.item .menu .item { - width: 100%; - } +.text.brown { + color: var(--color-brown) !important; +} - &.dropdown .menu > .item > .floating.label { - z-index: 11; - } +.text.black { + color: var(--color-text) !important; +} - &.dropdown .menu .menu > .item > .floating.label { - z-index: 21; - } +.text.grey { + color: var(--color-text-light) !important; +} - &.dropdown .menu > .header { - font-size: .8em; - } +.text.light.grey { + color: var(--color-grey-light) !important; +} - .text { - &.left { - text-align: left !important; - } - - &.right { - text-align: right !important; - } - - &.small { - font-size: .75em; - } - - &.normal { - font-weight: normal; - } - - &.italic { - font-style: italic; - } - - &.truncate { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - display: inline-block; - } - - &.thin { - font-weight: normal; - } - - &.middle { - vertical-align: middle; - } - } +.text.gold { + color: var(--color-gold) !important; +} - .message { - text-align: center; - } +.ui.left:not(.action) { + float: left; +} - .message > ul { - margin-left: auto; - margin-right: auto; - display: table; - text-align: left; - } +.ui.right:not(.action) { + float: right; +} - .header > i + .content { - padding-left: .75rem; - vertical-align: middle; - } +.ui.container.fluid.padded { + padding: 0 10px; +} - .info { - &.segment { - &.top { - h3, - h4 { - margin-top: 0; - } - - h3:last-child { - margin-top: 4px; - } - - > :last-child { - margin-bottom: 0; - } - } - } - } +.ui.form .ui.button { + font-weight: normal; +} - .normal.header { - font-weight: normal; - } +.ui.floating.label { + z-index: 10; +} - .form { - .autofill-dummy { - position: absolute; - width: 1px; - height: 1px; - overflow: hidden; - z-index: -10000; - } - .sub.field { - margin-left: 25px; - } - } +.ui.transparent.label { + background-color: transparent; +} - .sha.label { - font-family: var(--fonts-monospace); - font-size: 13px; - padding: 6px 10px 4px; - font-weight: normal; - margin: 0 6px; - } +.ui.menu, +.ui.vertical.menu, +.ui.segment { + box-shadow: none; +} - .button.copy-commit-sha { - border: 1px solid var(--color-light-border); - margin-right: 3px; - padding: 6px 6px 4px; - background: var(--color-light); - } +/* Override semantic selector '.ui.menu:not(.vertical) .item > .button' */ +/* This fixes the commit graph button on the commits page */ +/* modal svg icons, copied from fomantic except width and height */ +/* center text in fomantic modal dialogs */ +.ui .menu:not(.vertical) .item > .button.compact { + padding: 0.58928571em 1.125em; +} - .button.truncate { - display: inline-block; - max-width: 100%; - overflow: hidden; - text-overflow: ellipsis; - vertical-align: top; - white-space: nowrap; - margin-right: 6px; - } +.ui .menu:not(.vertical) .item > .button.small { + font-size: 0.92857143rem; +} - &.status.buttons { - .svg { - margin-right: 4px; - } - } +.ui.menu .ui.dropdown.item .menu .item { + width: 100%; +} - &.inline.delete-button { - padding: 8px 15px; - font-weight: normal; - } +.ui.dropdown .menu > .item > .floating.label { + z-index: 11; +} - .background { - &.red { - background-color: var(--color-red) !important; - } +.ui.dropdown .menu .menu > .item > .floating.label { + z-index: 21; +} - &.blue { - background-color: var(--color-blue) !important; - } +.ui.dropdown .menu > .header { + font-size: 0.8em; +} - &.black { - background-color: var(--color-black) !important; - } +.ui .text.left { + text-align: left !important; +} - &.grey { - background-color: var(--color-grey) !important; - } +.ui .text.right { + text-align: right !important; +} - &.light.grey { - background-color: var(--color-grey) !important; - } +.ui .text.small { + font-size: 0.75em; +} - &.green { - background-color: var(--color-green) !important; - } +.ui .text.normal { + font-weight: normal; +} - &.purple { - background-color: var(--color-purple) !important; - } +.ui .text.italic { + font-style: italic; +} - &.yellow { - background-color: var(--color-yellow) !important; - } +.ui .text.truncate { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + display: inline-block; +} - &.orange { - background-color: var(--color-orange) !important; - } +.ui .text.thin { + font-weight: normal; +} - &.gold { - background-color: var(--color-gold) !important; - } - } +.ui .text.middle { + vertical-align: middle; +} - .migrate { - color: var(--color-text-light-2) !important; +.ui .message { + text-align: center; +} - a { - color: var(--color-text-light) !important; +.ui .message > ul { + margin-left: auto; + margin-right: auto; + display: table; + text-align: left; +} - &:hover { - color: var(--color-text) !important; - } - } - } +.ui .header > i + .content { + padding-left: 0.75rem; + vertical-align: middle; +} - .border { - border: 1px solid; - &.red { - border-color: var(--color-red) !important; - } +.ui .info.segment.top h3, +.ui .info.segment.top h4 { + margin-top: 0; +} - &.blue { - border-color: var(--color-blue) !important; - } +.ui .info.segment.top h3:last-child { + margin-top: 4px; +} - &.black { - border-color: var(--color-black) !important; - } +.ui .info.segment.top > :last-child { + margin-bottom: 0; +} - &.grey { - border-color: var(--color-grey) !important; - } +.ui .normal.header { + font-weight: normal; +} - &.light.grey { - border-color: var(--color-grey) !important; - } +.ui .form .autofill-dummy { + position: absolute; + width: 1px; + height: 1px; + overflow: hidden; + z-index: -10000; +} - &.green { - border-color: var(--color-green) !important; - } +.ui .form .sub.field { + margin-left: 25px; +} - &.purple { - border-color: var(--color-purple) !important; - } +.ui .sha.label { + font-family: var(--fonts-monospace); + font-size: 13px; + padding: 6px 10px 4px; + font-weight: normal; + margin: 0 6px; +} - &.yellow { - border-color: var(--color-yellow) !important; - } +.ui .button.copy-commit-sha { + border: 1px solid var(--color-light-border); + margin-right: 3px; + padding: 6px 6px 4px; + background: var(--color-light); +} - &.orange { - border-color: var(--color-orange) !important; - } +.ui .button.truncate { + display: inline-block; + max-width: 100%; + overflow: hidden; + text-overflow: ellipsis; + vertical-align: top; + white-space: nowrap; + margin-right: 6px; +} - &.gold { - border-color: var(--color-gold) !important; - } - } +.ui.status.buttons .svg { + margin-right: 4px; +} - .branch-tag-choice { - line-height: 20px; - } +.ui.inline.delete-button { + padding: 8px 15px; + font-weight: normal; +} - &.pagination.menu { - @media @mediaSm { - .item:not(.active,.navigation), - .item.navigation span.navigation_label { - display: none; - } - } - &.narrow .item { - padding-left: 8px; - padding-right: 8px; - min-width: 1em; - text-align: center; - .icon { - margin-right: 0; - } - } - } +.ui .background.red { + background-color: var(--color-red) !important; +} - /* modal svg icons, copied from fomantic except width and height */ - &.icon.header svg { - width: 3em; - height: 3em; - float: none; - display: block; - line-height: 1; - padding: 0; - margin: 0 auto .5rem; - opacity: 1; - } +.ui .background.blue { + background-color: var(--color-blue) !important; +} - /* center text in fomantic modal dialogs */ - &.modal > .content { - text-align: center; - } +.ui .background.black { + background-color: var(--color-black) !important; +} + +.ui .background.grey { + background-color: var(--color-grey) !important; +} + +.ui .background.light.grey { + background-color: var(--color-grey) !important; +} + +.ui .background.green { + background-color: var(--color-green) !important; +} + +.ui .background.purple { + background-color: var(--color-purple) !important; +} + +.ui .background.yellow { + background-color: var(--color-yellow) !important; } -.ui.floating.dropdown { - .overflow.menu { - .scrolling.menu.items { - border-radius: 0 !important; - box-shadow: none !important; - border-bottom: 1px solid var(--color-secondary); - } +.ui .background.orange { + background-color: var(--color-orange) !important; +} + +.ui .background.gold { + background-color: var(--color-gold) !important; +} + +.ui .migrate { + color: var(--color-text-light-2) !important; +} + +.ui .migrate a { + color: var(--color-text-light) !important; +} + +.ui .migrate a:hover { + color: var(--color-text) !important; +} + +.ui .border { + border: 1px solid; +} + +.ui .border.red { + border-color: var(--color-red) !important; +} + +.ui .border.blue { + border-color: var(--color-blue) !important; +} + +.ui .border.black { + border-color: var(--color-black) !important; +} + +.ui .border.grey { + border-color: var(--color-grey) !important; +} + +.ui .border.light.grey { + border-color: var(--color-grey) !important; +} + +.ui .border.green { + border-color: var(--color-green) !important; +} + +.ui .border.purple { + border-color: var(--color-purple) !important; +} + +.ui .border.yellow { + border-color: var(--color-yellow) !important; +} + +.ui .border.orange { + border-color: var(--color-orange) !important; +} + +.ui .border.gold { + border-color: var(--color-gold) !important; +} + +.ui .branch-tag-choice { + line-height: 20px; +} + +@media (max-width: 767px) { + .ui.pagination.menu .item:not(.active,.navigation), + .ui.pagination.menu .item.navigation span.navigation_label { + display: none; } } +.ui.pagination.menu.narrow .item { + padding-left: 8px; + padding-right: 8px; + min-width: 1em; + text-align: center; +} + +.ui.pagination.menu.narrow .item .icon { + margin-right: 0; +} + +.ui.icon.header svg { + width: 3em; + height: 3em; + float: none; + display: block; + line-height: 1; + padding: 0; + margin: 0 auto 0.5rem; + opacity: 1; +} + +.ui.floating.dropdown .overflow.menu .scrolling.menu.items { + border-radius: 0 !important; + box-shadow: none !important; + border-bottom: 1px solid var(--color-secondary); +} + .user-menu > .item { width: 100%; border-radius: 0 !important; } -.scrolling.menu { - .item.selected { - font-weight: 600 !important; - } +.scrolling.menu .item.selected { + font-weight: 600 !important; } .ui.dropdown .scrolling.menu { @@ -1746,10 +1804,10 @@ a.ui.card:hover, .color-preview { display: inline-block; - margin-left: .4em; - height: .67em; - width: .67em; - border-radius: .15em; + margin-left: 0.4em; + height: 0.67em; + width: 0.67em; + border-radius: 0.15em; } .attention-icon { @@ -1772,70 +1830,73 @@ footer { width: 100%; flex-basis: 40px; color: var(--color-text-light); +} - .container { - width: 100vw !important; - padding: 0 .5rem; - max-width: calc(100vw - 1rem) !important; +footer .container { + width: 100vw !important; + padding: 0 0.5rem; + max-width: calc(100vw - 1rem) !important; +} - .links > * { - border-left: 1px solid var(--color-secondary-dark-1); - padding-left: 8px; - margin-left: 5px; +footer .container .links > * { + border-left: 1px solid var(--color-secondary-dark-1); + padding-left: 8px; + margin-left: 5px; +} - &:first-child { - border-left: 0; - } - } - } +footer .container .links > *:first-child { + border-left: 0; +} - .ui.language { - .menu { - max-height: 500px; - overflow-y: auto; - margin-bottom: 7px; - } - - .svg { - margin-right: .15em; - vertical-align: top; - margin-top: calc(2em - 16px); - } - } +footer .ui.language .menu { + max-height: 500px; + overflow-y: auto; + margin-bottom: 7px; +} - .ui { - &.left, - &.right { - line-height: 39px; // there is a border-top on the footer, so make the line-height 1px less - } - } +footer .ui.language .svg { + margin-right: 0.15em; + vertical-align: top; + margin-top: calc(2em - 16px); +} + +footer .ui.left, +footer .ui.right { + line-height: 39px; /* there is a border-top on the footer, so make the line-height 1px less */ } .center:not(.popup) { text-align: center; } -// Conditional display -@media @mediaMdAndUp { +/* Conditional display */ +@media (min-width: 768px) { .mobile-only, .ui.button.mobile-only { display: none !important; } - // has the same behaviour of sr-only, hiding the content for - // non-screenreaders, but is shown on mobile devices. + /* has the same behaviour of sr-only, hiding the content for */ + /* non-screenreaders, but is shown on mobile devices. */ .sr-mobile-only { - .sr-only(); + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; } } -@media @mediaSm { +@media (max-width: 767px) { .not-mobile { display: none !important; } } -// Accessibility +/* Accessibility for screen readers */ .sr-only { position: absolute; width: 1px; @@ -1857,7 +1918,7 @@ footer { clip: auto; } -@media @mediaMd { +@media (min-width: 768px) and (max-width: 991px) { .ui.container { width: 95%; } @@ -1897,7 +1958,7 @@ footer { margin: 0 !important; } -@media @mediaSm { +@media (max-width: 767px) { .ui.menu.new-menu .item { width: auto !important; } @@ -1924,10 +1985,6 @@ footer { display: block; } -[v-cloak] { - display: none !important; -} - .repos-search { padding-bottom: 0 !important; } @@ -1937,7 +1994,6 @@ footer { border-bottom-width: 0 !important; margin-bottom: 2px !important; justify-content: space-evenly; - } .ui.secondary.pointing.menu.repos-filter .item { @@ -1952,19 +2008,19 @@ footer { flex: 1; word-break: break-all; color: var(--color-text-light); +} - .avatar { - width: 32px !important; - height: 32px !important; - } +.repo-title .avatar { + width: 32px !important; + height: 32px !important; +} - .labels { - margin-left: .5rem; +.repo-title .labels { + margin-left: 0.5rem; +} - > * + * { - margin-left: .5rem; - } - } +.repo-title .labels > * + * { + margin-left: 0.5rem; } .repo-icon { @@ -1992,16 +2048,16 @@ footer { .inline-grouped-list { display: inline-block; vertical-align: top; +} - > .ui { - display: block; - margin-top: 5px; - margin-bottom: 10px; +.inline-grouped-list > .ui { + display: block; + margin-top: 5px; + margin-bottom: 10px; +} - &:first-child { - margin-top: 1px; - } - } +.inline-grouped-list > .ui:first-child { + margin-top: 1px; } i.icons .icon:first-child { @@ -2013,7 +2069,7 @@ i.icon.centerlock { } .ui.label { - padding: .3em .5em; + padding: 0.3em 0.5em; background: var(--color-light); color: var(--color-text-light); } @@ -2026,7 +2082,7 @@ a.ui.label:hover { } .ui.label > .detail .icons { - margin-right: .25em; + margin-right: 0.25em; } .ui.label > .detail .icons .icon { @@ -2042,29 +2098,24 @@ a.ui.label:hover { } .lines-num { - &:extend(.unselectable); padding-left: 10px; padding-right: 10px; text-align: right !important; color: var(--color-text-light-1); width: 1%; font-family: var(--fonts-monospace); +} - span { - &.bottom-line { - &::after { - border-bottom: 1px solid var(--color-secondary); - } - } - - &::after { - content: attr(data-line-number); - line-height: 20px !important; - padding: 0 10px; - cursor: pointer; - display: block; - } - } +.lines-num span.bottom-line::after { + border-bottom: 1px solid var(--color-secondary); +} + +.lines-num span::after { + content: attr(data-line-number); + line-height: 20px !important; + padding: 0 10px; + cursor: pointer; + display: block; } .lines-type-marker { @@ -2079,19 +2130,24 @@ a.ui.label:hover { padding-top: 0; padding-bottom: 0; vertical-align: top; +} - pre, - ol { - background-color: inherit; - margin: 0; - padding: 0 !important; - - li { - display: block; - width: calc(100% - 1ch); - padding-left: 1ch; - } - } +.lines-num pre, +.lines-code pre, +.lines-num ol, +.lines-code ol { + background-color: inherit; + margin: 0; + padding: 0 !important; +} + +.lines-num pre li, +.lines-code pre li, +.lines-num ol li, +.lines-code ol li { + display: block; + width: calc(100% - 1ch); + padding-left: 1ch; } .lines-escape { @@ -2131,64 +2187,61 @@ a.ui.label:hover { } .lines-commit { - &:extend(.unselectable); vertical-align: top; color: var(--color-grey); padding: 0 !important; background: var(--color-code-sidebar-bg); width: 1%; +} - .blame-info { - &:extend(.unselectable); - width: 350px; - max-width: 350px; - display: block; - padding: 0 0 0 10px; - line-height: 20px; - box-sizing: content-box; - - .blame-data { - display: flex; - font-family: var(--fonts-regular); - - .blame-message { - flex-grow: 2; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - } - - .blame-time, - .blame-avatar { - flex-shrink: 0; - } - } - } +.lines-commit .blame-info { + width: 350px; + max-width: 350px; + display: block; + padding: 0 0 0 10px; + line-height: 20px; + box-sizing: content-box; +} - .ui.avatar { - height: 18px; - width: 18px; - display: block; - margin-top: 1px; - } +.lines-commit .blame-info .blame-data { + display: flex; + font-family: var(--fonts-regular); +} + +.lines-commit .blame-info .blame-data .blame-message { + flex-grow: 2; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +.lines-commit .blame-info .blame-data .blame-time, +.lines-commit .blame-info .blame-data .blame-avatar { + flex-shrink: 0; +} + +.lines-commit .ui.avatar { + height: 18px; + width: 18px; + display: block; + margin-top: 1px; } .top-line-blame { border-top: 1px solid var(--color-secondary); } -.lines-code, -.lines-commit { - .bottom-line { - border-bottom: 1px solid var(--color-secondary); - } +.lines-code .bottom-line, +.lines-commit .bottom-line { + border-bottom: 1px solid var(--color-secondary); } + .code-view table { width: 100%; } .octicon-tiny { - font-size: .85714286rem; + font-size: 0.85714286rem; } .ui.button { @@ -2362,16 +2415,16 @@ a.ui.basic.label:hover { height: 2.1666em !important; } -.svg { - span.green & { - color: var(--color-green); - } - span.red & { - color: var(--color-red); - } - span.purple & { - color: var(--color-purple); - } +span.green .svg { + color: var(--color-green); +} + +span.red .svg { + color: var(--color-red); +} + +span.purple .svg { + color: var(--color-purple); } .migrate .svg.gitea-git { @@ -2414,17 +2467,17 @@ a.ui.basic.label:hover { position: relative; background: var(--color-box-header); border-color: var(--color-secondary); +} - .right .button { - padding: 8px 10px; - font-weight: normal; - } +.ui.attached.header .right .button { + padding: 8px 10px; + font-weight: normal; } /* fix misaligned right buttons on box headers */ .ui.attached.header .right:not(.dropdown) { position: absolute; - right: .78571429rem; + right: 0.78571429rem; top: 0; bottom: 0; height: 30px; @@ -2461,25 +2514,25 @@ a.ui.basic.label:hover { border-radius: 1em; font-size: 10px; font-weight: 700; - line-height: .7; + line-height: 0.7; } -table th[data-sortt-asc], -table th[data-sortt-desc] { - &:hover { - background: rgba(0, 0, 0, .1) !important; - cursor: pointer !important; - } - .svg { - margin-left: .25rem; - } +table th[data-sortt-asc]:hover, +table th[data-sortt-desc]:hover { + background: rgba(0, 0, 0, 0.1) !important; + cursor: pointer !important; +} + +table th[data-sortt-asc] .svg, +table th[data-sortt-desc] .svg { + margin-left: 0.25rem; } .ui.dropdown .svg.dropdown.icon, .svg.dropdown.icon { - margin-top: 0 !important; // reset the "ui.selection.dropdown > .dropdown.icon {margin-top}", for the Issue Dependencies dropdown - margin-right: -.5rem !important; // fix up SVG dropdown triangles because Fomantic thinks they are icon fonts - height: auto; // reset the ".ui.dropdown > .dropdown.icon {height}", otherwise the icon would be too small + margin-top: 0 !important; /* reset the "ui.selection.dropdown > .dropdown.icon {margin-top}", for the Issue Dependencies dropdown */ + margin-right: -0.5rem !important; /* fix up SVG dropdown triangles because Fomantic thinks they are icon fonts */ + height: auto; /* reset the ".ui.dropdown > .dropdown.icon {height}", otherwise the icon would be too small */ } .ui.selection.dropdown > .search.icon, @@ -2487,6 +2540,7 @@ table th[data-sortt-desc] { .ui.selection.dropdown > .dropdown.icon { top: 0 !important; } + .ui.dropdown.no-text > .dropdown.icon { margin-left: 0 !important; margin-right: 0 !important; @@ -2515,17 +2569,19 @@ table th[data-sortt-desc] { line-height: 1; font-style: normal !important; font-weight: normal !important; - vertical-align: -.075em; - - @supports (-webkit-hyphens:none) { - body:not(.safari-above125) & { - font-size: inherit; - vertical-align: inherit; - img { - font-size: 1.25em; - vertical-align: -.225em !important; - } - } + vertical-align: -0.075em; +} + +@supports (-webkit-hyphens:none) { + body:not(.safari-above125) .emoji, + body:not(.safari-above125) .reaction { + font-size: inherit; + vertical-align: inherit; + } + body:not(.safari-above125) .emoji img, + body:not(.safari-above125) .reaction img { + font-size: 1.25em; + vertical-align: -0.225em !important; } } @@ -2535,7 +2591,7 @@ table th[data-sortt-desc] { margin: 0 !important; width: 1em !important; height: 1em !important; - vertical-align: -.15em; + vertical-align: -0.15em; } .minicolors-panel { @@ -2545,38 +2601,38 @@ table th[data-sortt-desc] { .labelspage { list-style: none; padding-top: 0; +} - .item { - margin-top: 0; - margin-right: -14px; - margin-left: -14px; - padding: 10px; - border-bottom: 1px solid var(--color-secondary); - border-top: none; - - a { - font-size: 12px; - padding-right: 10px; - color: var(--color-text-light); - - &:hover { - color: var(--color-primary-light-2); - } - - &.open-issues { - margin-right: 30px; - } - } - } +.labelspage .item { + margin-top: 0; + margin-right: -14px; + margin-left: -14px; + padding: 10px; + border-bottom: 1px solid var(--color-secondary); + border-top: none; +} - .item:last-child { - border-bottom: none; - padding-bottom: 0; - } +.labelspage .item a { + font-size: 12px; + padding-right: 10px; + color: var(--color-text-light); +} - .orglabel { - opacity: .7; - } +.labelspage .item a:hover { + color: var(--color-primary-light-2); +} + +.labelspage .item a.open-issues { + margin-right: 30px; +} + +.labelspage .item:last-child { + border-bottom: none; + padding-bottom: 0; +} + +.labelspage .orglabel { + opacity: 0.7; } /* https://github.com/go-gitea/gitea/pull/11486 */ @@ -2631,7 +2687,7 @@ table th[data-sortt-desc] { } .ui.header .ui.label { - margin-left: .25rem; + margin-left: 0.25rem; } .ui.header > .ui.label.compact { @@ -2654,7 +2710,6 @@ table th[data-sortt-desc] { } .ellipsis-button { - &:extend(.unselectable); padding: 0 5px 8px !important; display: inline-block !important; font-weight: 600 !important; @@ -2667,8 +2722,8 @@ table th[data-sortt-desc] { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; - margin-top: -.5em; - margin-bottom: -.5em; + margin-top: -0.5em; + margin-bottom: -0.5em; } .precolors { @@ -2676,32 +2731,29 @@ table th[data-sortt-desc] { padding-right: 0 !important; margin: 3px 10px auto !important; width: 120px !important; +} - .color { - float: left; - width: 15px; - height: 15px; - } +.precolors .color { + float: left; + width: 15px; + height: 15px; } -@media @mediaSm { +@media (max-width: 767px) { .ui.stackable.menu:not(.no-vertical-tabs) { overflow-y: hidden; overflow-x: auto; flex-direction: row; flex-wrap: nowrap !important; - - .item { - width: initial !important; - } - - > .dropdown.item { - position: initial; - } - - .menu { - flex-direction: row; - } + } + .ui.stackable.menu:not(.no-vertical-tabs) .item { + width: initial !important; + } + .ui.stackable.menu:not(.no-vertical-tabs) > .dropdown.item { + position: initial; + } + .ui.stackable.menu:not(.no-vertical-tabs) .menu { + flex-direction: row; } } diff --git a/web_src/less/chroma/base.less b/web_src/css/chroma/base.css similarity index 87% rename from web_src/less/chroma/base.less rename to web_src/css/chroma/base.css index 597ee2a72d05..bfd49db7a433 100644 --- a/web_src/less/chroma/base.less +++ b/web_src/css/chroma/base.css @@ -29,14 +29,14 @@ /* LineNumbersTable */ .chroma .lnt { - margin-right: .4em; - padding: 0 .4em; + margin-right: 0.4em; + padding: 0 0.4em; } /* LineNumbers */ .chroma .ln { - margin-right: .4em; - padding: 0 .4em; + margin-right: 0.4em; + padding: 0 0.4em; } /* GenericStrong */ diff --git a/web_src/less/chroma/dark.less b/web_src/css/chroma/dark.css similarity index 100% rename from web_src/less/chroma/dark.less rename to web_src/css/chroma/dark.css diff --git a/web_src/less/chroma/light.less b/web_src/css/chroma/light.css similarity index 100% rename from web_src/less/chroma/light.less rename to web_src/css/chroma/light.css diff --git a/web_src/less/code/linebutton.less b/web_src/css/code/linebutton.css similarity index 100% rename from web_src/less/code/linebutton.less rename to web_src/css/code/linebutton.css diff --git a/web_src/less/codemirror/base.less b/web_src/css/codemirror/base.css similarity index 71% rename from web_src/less/codemirror/base.less rename to web_src/css/codemirror/base.css index db0a93f4c74a..b435fb1342c0 100644 --- a/web_src/less/codemirror/base.less +++ b/web_src/css/codemirror/base.css @@ -1,5 +1,5 @@ .ui .field:not(:last-child) .EasyMDEContainer .editor-statusbar { - margin-bottom: -1em; // when there is a statusbar, the "margin-bottom: 1em" of the "field" is not needed, because the statusbar is likely a blank line + margin-bottom: -1em; /* when there is a statusbar, the "margin-bottom: 1em" of the "field" is not needed, because the statusbar is likely a blank line */ } .EasyMDEContainer .CodeMirror { @@ -7,15 +7,15 @@ background-color: var(--color-input-background); border-color: var(--color-secondary); font: 14px var(--fonts-monospace); +} - &.cm-s-default { - border-radius: var(--border-radius); - padding: 0 !important; - } +.EasyMDEContainer .CodeMirror.cm-s-default { + border-radius: var(--border-radius); + padding: 0 !important; +} - &.CodeMirror-fullscreen.CodeMirror-focused { - border-right: 1px solid var(--color-primary) !important; - } +.EasyMDEContainer .CodeMirror.CodeMirror-fullscreen.CodeMirror-focused { + border-right: 1px solid var(--color-primary) !important; } .CodeMirror-cursor { diff --git a/web_src/css/codemirror/dark.css b/web_src/css/codemirror/dark.css new file mode 100644 index 000000000000..8a20d1c00433 --- /dev/null +++ b/web_src/css/codemirror/dark.css @@ -0,0 +1,106 @@ +.CodeMirror.cm-s-default .cm-property, +.CodeMirror.cm-s-paper .cm-property { + color: #a0cc75; +} + +.CodeMirror.cm-s-default .cm-header, +.CodeMirror.cm-s-paper .cm-header { + color: #9daccc; +} + +.CodeMirror.cm-s-default .cm-quote, +.CodeMirror.cm-s-paper .cm-quote { + color: #009900; +} + +.CodeMirror.cm-s-default .cm-keyword, +.CodeMirror.cm-s-paper .cm-keyword { + color: #cc8a61; +} + +.CodeMirror.cm-s-default .cm-atom, +.CodeMirror.cm-s-paper .cm-atom { + color: #ef5e77; +} + +.CodeMirror.cm-s-default .cm-number, +.CodeMirror.cm-s-paper .cm-number { + color: #ff5656; +} + +.CodeMirror.cm-s-default .cm-def, +.CodeMirror.cm-s-paper .cm-def { + color: #e4e4e4; +} + +.CodeMirror.cm-s-default .cm-variable-2, +.CodeMirror.cm-s-paper .cm-variable-2 { + color: #00bdbf; +} + +.CodeMirror.cm-s-default .cm-variable-3, +.CodeMirror.cm-s-paper .cm-variable-3 { + color: #008855; +} + +.CodeMirror.cm-s-default .cm-comment, +.CodeMirror.cm-s-paper .cm-comment { + color: #8e9ab3; +} + +.CodeMirror.cm-s-default .cm-string, +.CodeMirror.cm-s-paper .cm-string { + color: #a77272; +} + +.CodeMirror.cm-s-default .cm-string-2, +.CodeMirror.cm-s-paper .cm-string-2 { + color: #ff5500; +} + +.CodeMirror.cm-s-default .cm-meta, +.CodeMirror.cm-s-paper .cm-meta, +.CodeMirror.cm-s-default .cm-qualifier, +.CodeMirror.cm-s-paper .cm-qualifier { + color: #ffb176; +} + +.CodeMirror.cm-s-default .cm-builtin, +.CodeMirror.cm-s-paper .cm-builtin { + color: #b7c951; +} + +.CodeMirror.cm-s-default .cm-bracket, +.CodeMirror.cm-s-paper .cm-bracket { + color: #999977; +} + +.CodeMirror.cm-s-default .cm-tag, +.CodeMirror.cm-s-paper .cm-tag { + color: #f1d273; +} + +.CodeMirror.cm-s-default .cm-attribute, +.CodeMirror.cm-s-paper .cm-attribute { + color: #bfcc70; +} + +.CodeMirror.cm-s-default .cm-hr, +.CodeMirror.cm-s-paper .cm-hr { + color: #999999; +} + +.CodeMirror.cm-s-default .cm-url, +.CodeMirror.cm-s-paper .cm-url { + color: #c5cfd0; +} + +.CodeMirror.cm-s-default .cm-link, +.CodeMirror.cm-s-paper .cm-link { + color: #d8c792; +} + +.CodeMirror.cm-s-default .cm-error, +.CodeMirror.cm-s-paper .cm-error { + color: #dbdbeb; +} diff --git a/web_src/less/codemirror/light.less b/web_src/css/codemirror/light.css similarity index 100% rename from web_src/less/codemirror/light.less rename to web_src/css/codemirror/light.css diff --git a/web_src/less/console/console.less b/web_src/css/console/console.css similarity index 98% rename from web_src/less/console/console.less rename to web_src/css/console/console.css index db25a35bacc8..b2d8439f8cae 100644 --- a/web_src/less/console/console.less +++ b/web_src/css/console/console.css @@ -1,4 +1,4 @@ -// Based on https://github.com/buildkite/terminal-to-html/blob/697ff23bd8dc48b9d23f11f259f5256dae2455f0/assets/terminal.css +/* Based on https://github.com/buildkite/terminal-to-html/blob/697ff23bd8dc48b9d23f11f259f5256dae2455f0/assets/terminal.css */ .console { background: var(--color-console-bg); diff --git a/web_src/css/dashboard.css b/web_src/css/dashboard.css new file mode 100644 index 000000000000..ced8b3a164aa --- /dev/null +++ b/web_src/css/dashboard.css @@ -0,0 +1,203 @@ +.dashboard.feeds .context.user.menu, +.dashboard.issues .context.user.menu { + z-index: 101; + min-width: 200px; +} + +.dashboard.feeds .context.user.menu .ui.header, +.dashboard.issues .context.user.menu .ui.header { + font-size: 1rem; + text-transform: none; +} + +.dashboard.feeds .filter.menu, +.dashboard.issues .filter.menu { + width: initial; +} + +.dashboard.feeds .filter.menu .item, +.dashboard.issues .filter.menu .item { + text-align: left; + display: flex; + align-items: center; + justify-content: space-between; +} + +.dashboard.feeds .filter.menu .item .text, +.dashboard.issues .filter.menu .item .text { + height: 16px; + vertical-align: middle; +} + +.dashboard.feeds .filter.menu .item .text.truncate, +.dashboard.issues .filter.menu .item .text.truncate { + width: 75%; +} + +.dashboard.feeds .filter.menu .item .floating.label, +.dashboard.issues .filter.menu .item .floating.label { + top: 7px; + left: 90%; + width: 15%; +} + +@media (max-width: 767px) { + .dashboard.feeds .filter.menu .item .floating.label, + .dashboard.issues .filter.menu .item .floating.label { + top: 10px; + left: auto; + width: auto; + right: 13px; + } +} + +/* Sort */ +.dashboard.feeds .filter.menu .jump.item, +.dashboard.issues .filter.menu .jump.item { + margin: 1px; + padding-right: 0; +} + +.dashboard.feeds .filter.menu .menu, +.dashboard.issues .filter.menu .menu { + max-height: 300px; + overflow-x: auto; + right: 0 !important; + left: auto !important; +} + +@media (max-width: 767px) { + .dashboard.feeds .filter.menu, + .dashboard.issues .filter.menu { + width: 100%; + } +} + +.dashboard.feeds .right.stackable.menu > .item.active, +.dashboard.issues .right.stackable.menu > .item.active { + color: var(--color-red); +} + +.dashboard .dashboard-repos, +.dashboard .dashboard-orgs { + margin: 0 1px; /* Accommodate for Semantic's 1px hacks on .attached elements */ +} + +.dashboard .dashboard-navbar { + width: 100vw; + padding-left: 0.5rem; + padding-right: 0.5rem; +} + +.dashboard .dashboard-navbar .org-visibility .label { + margin-left: 5px; +} + +.dashboard .dashboard-navbar .ui.dropdown { + max-width: 100%; +} + +@media (max-width: 767px) { + .dashboard .dashboard-navbar .ui.dropdown > .menu { + position: static; + } +} + +.feeds .news li { + display: flex; + align-items: baseline; + margin-top: 0.5rem; + margin-bottom: 0.5rem; +} + +.feeds .news li img { + align-self: flex-start; +} + +.feeds .news li > * + * { + margin-left: 0.35rem; +} + +.feeds .news > .ui.grid { + margin-left: auto; + margin-right: auto; +} + +.feeds .news .left .ui.avatar { + margin-top: 13px; +} + +.feeds .news .time-since { + font-size: 13px; +} + +.feeds .news .issue.title { + width: 80%; + margin: 0 0 1em; +} + +.feeds .news .push.news .content ul { + line-height: 18px; + font-size: 13px; + list-style: none; + padding-left: 10px; +} + +.feeds .news .push.news .content ul .text.truncate { + width: 80%; +} + +.feeds .news .commit-id { + font-family: var(--fonts-monospace); +} + +.feeds .news code { + padding: 2px 4px; + border-radius: 3px; + background-color: var(--color-markup-code-block); + word-break: break-all; +} + +.feeds .news:last-of-type .divider { + display: none !important; +} + +.feeds .list ul { + list-style: none; + margin: 0; + padding-left: 0; +} + +.feeds .list ul li:not(:last-child) { + border-bottom: 1px solid var(--color-secondary); +} + +.feeds .list ul li.private { + background-color: var(--color-box-body-highlight); +} + +.feeds .list ul li .repo-list-link { + padding: 6px 1em; + display: block; +} + +.feeds .list ul li .repo-list-link .svg { + color: var(--color-text-light-2); +} + +.feeds .list ul li .repo-list-link .star-num { + font-size: 12px; +} + +.feeds .list #privateFilterCheckbox .svg { + color: var(--color-grey); + margin-right: 0.25rem; +} + +.feeds .list .repo-owner-name-list .item-name { + min-width: 0; +} + +.feeds .list .repo-owner-name-list .item-name svg { + min-width: 16px; +} diff --git a/web_src/less/_editor.less b/web_src/css/editor.css similarity index 100% rename from web_src/less/_editor.less rename to web_src/css/editor.css diff --git a/web_src/css/explore.css b/web_src/css/explore.css new file mode 100644 index 000000000000..854370225247 --- /dev/null +++ b/web_src/css/explore.css @@ -0,0 +1,88 @@ +.explore .navbar { + justify-content: center; + margin-bottom: 15px !important; + background-color: var(--color-navbar) !important; + border-width: 1px !important; +} + +.explore .navbar .svg { + width: 16px; + text-align: center; + margin-right: 5px; +} + +.ui.repository.list .item { + padding-bottom: 1.5rem; +} + +.ui.repository.list .item:not(:first-child) { + border-top: 1px solid var(--color-secondary); + padding-top: 1.5rem; +} + +.ui.repository.list .item .ui.header { + font-size: 1.5rem; + margin-bottom: 0.5rem; +} + +.ui.repository.list .item .ui.header .name { + word-break: break-all; +} + +.ui.repository.list .item .ui.header .metas { + font-size: 14px; +} + +.ui.repository.list .item .time { + font-size: 12px; +} + +.ui.repository.list .item .ui.tags { + margin-bottom: 0.5rem; +} + +.ui.repository.branches .info { + font-size: 12px; + color: var(--color-text-light); + display: flex; + white-space: pre; +} + +.ui.repository.branches .info .commit-message { + max-width: 72em; + overflow: hidden; + text-overflow: ellipsis; +} + +.ui.repository.branches .overflow-visible { + overflow: visible; +} + +/* fix alignment of PR popup in branches table */ +.ui.repository.branches table .ui.popup { + text-align: left; +} + +.ui.user.list .item { + padding-bottom: 25px; + display: flex; +} + +.ui.user.list .item:not(:first-child) { + border-top: 1px solid var(--color-secondary); + padding-top: 25px; +} + +.ui.user.list .item img.ui.avatar { + width: 40px; + height: 40px; + margin-right: 10px; +} + +.ui.user.list .item .description { + margin-top: 5px; +} + +.ui.user.list .item .description .svg:not(:first-child) { + margin-left: 5px; +} diff --git a/web_src/less/features/codeeditor.less b/web_src/css/features/codeeditor.css similarity index 100% rename from web_src/less/features/codeeditor.less rename to web_src/css/features/codeeditor.css diff --git a/web_src/less/features/dropzone.less b/web_src/css/features/dropzone.css similarity index 75% rename from web_src/less/features/dropzone.less rename to web_src/css/features/dropzone.css index ee7a5f1b65d4..0ce067ef30ec 100644 --- a/web_src/less/features/dropzone.less +++ b/web_src/css/features/dropzone.css @@ -1,15 +1,14 @@ -.ui .field { - .dropzone { - border: 2px dashed var(--color-secondary); - background: none; - box-shadow: none; - padding: 0; - border-radius: 4px; - min-height: 0; - .dz-message { - margin: 10px 0; - } - } +.ui .field .dropzone { + border: 2px dashed var(--color-secondary); + background: none; + box-shadow: none; + padding: 0; + border-radius: 4px; + min-height: 0; +} + +.ui .field .dropzone .dz-message { + margin: 10px 0; } .dropzone .dz-button { @@ -50,5 +49,5 @@ } .dropzone .dz-preview:hover .dz-image img { - filter: opacity(.5) !important; + filter: opacity(0.5) !important; } diff --git a/web_src/css/features/gitgraph.css b/web_src/css/features/gitgraph.css new file mode 100644 index 000000000000..f7477997fe0f --- /dev/null +++ b/web_src/css/features/gitgraph.css @@ -0,0 +1,317 @@ +#git-graph-container { + overflow-x: auto; + width: 100%; + min-height: 350px; +} + +#git-graph-container > .ui.segment.loading { + border: 0; + z-index: 1; + min-height: 246px; +} + +#git-graph-container h2 { + display: flex; + justify-content: space-between; + align-items: center; +} + +#git-graph-container .color-buttons { + margin-right: 0; +} + +#git-graph-container .ui.header.dividing { + padding-bottom: 10px; +} + +#git-graph-container #flow-select-refs-dropdown { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + min-width: 250px; + border-right: none; +} + +#git-graph-container #flow-select-refs-dropdown .ui.label { + max-width: 180px; + display: inline-flex !important; + align-items: center; +} + +#git-graph-container #flow-select-refs-dropdown .ui.label .truncate { + display: inline-block; + max-width: 140px; + overflow: hidden; + text-overflow: ellipsis; + vertical-align: top; + white-space: nowrap; +} + +#git-graph-container #flow-select-refs-dropdown .dropdown.icon { + display: none; +} + +#git-graph-container #flow-select-refs-dropdown .default.text { + padding-top: 4px; + padding-bottom: 4px; +} + +#git-graph-container #flow-select-refs-dropdown input.search { + position: relative; + top: 1px; +} + +#git-graph-container li { + list-style-type: none; + height: 24px; + line-height: 24px; + white-space: nowrap; + display: flex; + align-items: center; +} + +#git-graph-container li .node-relation { + font-family: var(--fonts-monospace); +} + +#git-graph-container li .author { + color: var(--color-text-light); +} + +#git-graph-container li .time { + color: var(--color-text-light-3); + font-size: 80%; +} + +#git-graph-container li a:not(.ui):hover { + text-decoration: underline; +} + +#git-graph-container li a em { + color: var(--color-red); + border-bottom: 1px dotted var(--color-secondary); + text-decoration: none; + font-style: normal; +} + +#git-graph-container #rel-container { + max-width: 30%; + overflow-x: auto; + float: left; +} + +#git-graph-container #rev-container { + width: 100%; +} + +#git-graph-container #rev-list { + margin: 0; + padding: 0; + width: 100%; +} + +#git-graph-container #rev-list li.highlight.hover { + background-color: var(--color-secondary-alpha-30); +} + +#git-graph-container #rev-list .tags a.button { + padding: 2px 4px; +} + +#git-graph-container #rev-list .sha.label { + padding-top: 5px; + padding-bottom: 3px; +} + +#git-graph-container #rev-list .sha.label .shortsha { + padding-top: 0; +} + +#git-graph-container #rev-list .sha.label .shortsha-pad { + padding-right: 10px; +} + +#git-graph-container #rev-list .sha.label .ui.detail.icon.button { + padding-top: 3px; + margin-top: -5px; + padding-bottom: 1px; +} + +#git-graph-container #rev-list .author img.ui.avatar { + width: auto; + height: 18px; + max-width: none; +} + +#git-graph-container #graph-raw-list { + margin: 0; +} + +#git-graph-container.monochrome #rel-container .flow-group { + stroke: var(--color-secondary-dark-5); + fill: var(--color-secondary-dark-5); +} + +#git-graph-container.monochrome #rel-container .flow-group.highlight { + stroke: var(--color-secondary-dark-12); + fill: var(--color-secondary-dark-12); +} + +#git-graph-container:not(.monochrome) #rel-container .flow-group.flow-color-16-1 { + stroke: #499a37; + fill: #499a37; +} + +#git-graph-container:not(.monochrome) #rel-container .flow-group.flow-color-16-2 { + stroke: #ce4751; + fill: #ce4751; +} + +#git-graph-container:not(.monochrome) #rel-container .flow-group.flow-color-16-3 { + stroke: #8f9121; + fill: #8f9121; +} + +#git-graph-container:not(.monochrome) #rel-container .flow-group.flow-color-16-4 { + stroke: #ac32a6; + fill: #ac32a6; +} + +#git-graph-container:not(.monochrome) #rel-container .flow-group.flow-color-16-5 { + stroke: #7445e9; + fill: #7445e9; +} + +#git-graph-container:not(.monochrome) #rel-container .flow-group.flow-color-16-6 { + stroke: #c67d28; + fill: #c67d28; +} + +#git-graph-container:not(.monochrome) #rel-container .flow-group.flow-color-16-7 { + stroke: #4db392; + fill: #4db392; +} + +#git-graph-container:not(.monochrome) #rel-container .flow-group.flow-color-16-8 { + stroke: #aa4d30; + fill: #aa4d30; +} + +#git-graph-container:not(.monochrome) #rel-container .flow-group.flow-color-16-9 { + stroke: #2a6f84; + fill: #2a6f84; +} + +#git-graph-container:not(.monochrome) #rel-container .flow-group.flow-color-16-10 { + stroke: #c45327; + fill: #c45327; +} + +#git-graph-container:not(.monochrome) #rel-container .flow-group.flow-color-16-11 { + stroke: #3d965c; + fill: #3d965c; +} + +#git-graph-container:not(.monochrome) #rel-container .flow-group.flow-color-16-12 { + stroke: #792a93; + fill: #792a93; +} + +#git-graph-container:not(.monochrome) #rel-container .flow-group.flow-color-16-13 { + stroke: #439d73; + fill: #439d73; +} + +#git-graph-container:not(.monochrome) #rel-container .flow-group.flow-color-16-14 { + stroke: #103aad; + fill: #103aad; +} + +#git-graph-container:not(.monochrome) #rel-container .flow-group.flow-color-16-15 { + stroke: #982e85; + fill: #982e85; +} + +#git-graph-container:not(.monochrome) #rel-container .flow-group.flow-color-16-0 { + stroke: #7db233; + fill: #7db233; +} + +#git-graph-container:not(.monochrome) #rel-container .flow-group.highlight.flow-color-16-1 { + stroke: #5ac144; + fill: #5ac144; +} + +#git-graph-container:not(.monochrome) #rel-container .flow-group.highlight.flow-color-16-2 { + stroke: #ed5a8b; + fill: #ed5a8b; +} + +#git-graph-container:not(.monochrome) #rel-container .flow-group.highlight.flow-color-16-3 { + stroke: #ced049; + fill: #ced048; +} + +#git-graph-container:not(.monochrome) #rel-container .flow-group.highlight.flow-color-16-4 { + stroke: #db61d7; + fill: #db62d6; +} + +#git-graph-container:not(.monochrome) #rel-container .flow-group.highlight.flow-color-16-5 { + stroke: #8455f9; + fill: #8455f9; +} + +#git-graph-container:not(.monochrome) #rel-container .flow-group.highlight.flow-color-16-6 { + stroke: #e6a151; + fill: #e6a151; +} + +#git-graph-container:not(.monochrome) #rel-container .flow-group.highlight.flow-color-16-7 { + stroke: #44daaa; + fill: #44daaa; +} + +#git-graph-container:not(.monochrome) #rel-container .flow-group.highlight.flow-color-16-8 { + stroke: #dd7a5c; + fill: #dd7a5c; +} + +#git-graph-container:not(.monochrome) #rel-container .flow-group.highlight.flow-color-16-9 { + stroke: #38859c; + fill: #38859c; +} + +#git-graph-container:not(.monochrome) #rel-container .flow-group.highlight.flow-color-16-10 { + stroke: #d95520; + fill: #d95520; +} + +#git-graph-container:not(.monochrome) #rel-container .flow-group.highlight.flow-color-16-11 { + stroke: #42ae68; + fill: #42ae68; +} + +#git-graph-container:not(.monochrome) #rel-container .flow-group.highlight.flow-color-16-12 { + stroke: #9126b5; + fill: #9126b5; +} + +#git-graph-container:not(.monochrome) #rel-container .flow-group.highlight.flow-color-16-13 { + stroke: #4ab080; + fill: #4ab080; +} + +#git-graph-container:not(.monochrome) #rel-container .flow-group.highlight.flow-color-16-14 { + stroke: #284fb8; + fill: #284fb8; +} + +#git-graph-container:not(.monochrome) #rel-container .flow-group.highlight.flow-color-16-15 { + stroke: #971c80; + fill: #971c80; +} + +#git-graph-container:not(.monochrome) #rel-container .flow-group.highlight.flow-color-16-0 { + stroke: #87ca28; + fill: #87ca28; +} diff --git a/web_src/css/features/heatmap.css b/web_src/css/features/heatmap.css new file mode 100644 index 000000000000..d0cd2b5734a5 --- /dev/null +++ b/web_src/css/features/heatmap.css @@ -0,0 +1,68 @@ +#user-heatmap { + width: 100%; + font-size: 9px; + position: relative; + min-height: 125px; +} + +#user-heatmap text { + fill: currentcolor !important; +} + +/* for the "Less" and "More" legend */ +#user-heatmap .vch__legend .vch__legend { + display: flex; + font-size: 11px; + align-items: center; + justify-content: right; +} + +#user-heatmap .vch__legend .vch__legend div:first-child, +#user-heatmap .vch__legend .vch__legend div:last-child { + display: inline-block; + padding: 0 5px; +} + +/* move the "? contributions in the last ? months" text from top to bottom */ +#user-heatmap .total-contributions { + font-size: 11px; + position: absolute; + bottom: 0; + left: 25px; +} + +@media (max-width: 1200px) { + #user-heatmap { + min-height: 105px; + } + #user-heatmap .total-contributions { + left: 21px; + } +} + +@media (max-width: 1000px) { + #user-heatmap { + min-height: 80px; + } + #user-heatmap .total-contributions { + font-size: 10px; + left: 17px; + bottom: -4px; + } +} + +.user.profile #user-heatmap { + min-height: 135px; +} + +@media (max-width: 1200px) { + .user.profile #user-heatmap { + min-height: 115px; + } +} + +@media (max-width: 1000px) { + .user.profile #user-heatmap { + min-height: 90px; + } +} diff --git a/web_src/css/features/imagediff.css b/web_src/css/features/imagediff.css new file mode 100644 index 000000000000..f796bc19aea2 --- /dev/null +++ b/web_src/css/features/imagediff.css @@ -0,0 +1,107 @@ +.image-diff-container { + text-align: center; + padding: 1em 0; +} + +.image-diff-container img { + border: 1px solid var(--color-primary-light-7); + background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAG0lEQVQYlWN4+vTpf3SMDTAMBYXYBLFpHgoKAeiOf0SGE9kbAAAAAElFTkSuQmCC") right bottom var(--color-primary-light-7); +} + +.image-diff-container .before-container { + border: 1px solid var(--color-red); + display: block; +} + +.image-diff-container .after-container { + border: 1px solid var(--color-green); + display: block; +} + +.image-diff-container .diff-side-by-side .side { + display: inline-block; + line-height: 0; + vertical-align: top; + margin: 0 1em; +} + +.image-diff-container .diff-side-by-side .side .side-header { + font-weight: bold; +} + +.image-diff-container .diff-swipe { + margin: auto; +} + +.image-diff-container .diff-swipe .swipe-frame { + position: absolute; +} + +.image-diff-container .diff-swipe .swipe-frame .before-container { + position: absolute; +} + +.image-diff-container .diff-swipe .swipe-frame .swipe-container { + position: absolute; + right: 0; + display: block; + border-left: 2px solid var(--color-secondary-dark-8); + height: 100%; + overflow: hidden; +} + +.image-diff-container + .diff-swipe + .swipe-frame + .swipe-container + .after-container { + position: absolute; + right: 0; +} + +.image-diff-container .diff-swipe .swipe-frame .swipe-bar { + position: absolute; + height: 100%; + top: 0; + left: 0; +} + +.image-diff-container .diff-swipe .swipe-frame .swipe-bar .handle { + background: var(--color-secondary-dark-8); + left: -5px; + height: 12px; + width: 12px; + position: absolute; + transform: rotate(45deg); + box-sizing: border-box; + display: flex; + justify-content: center; + align-items: center; + cursor: pointer; +} + +.image-diff-container .diff-swipe .swipe-frame .swipe-bar .top-handle { + top: -12px; +} + +.image-diff-container .diff-swipe .swipe-frame .swipe-bar .bottom-handle { + bottom: -14px; +} + +.image-diff-container .diff-overlay { + margin: 0 auto; +} + +.image-diff-container .diff-overlay .overlay-frame { + margin: 0 auto; + position: relative; +} + +.image-diff-container .diff-overlay .before-container, +.image-diff-container .diff-overlay .after-container { + position: absolute; +} + +.image-diff-container .diff-overlay input { + max-width: 300px; +} diff --git a/web_src/less/features/projects.less b/web_src/css/features/projects.css similarity index 67% rename from web_src/less/features/projects.less rename to web_src/css/features/projects.css index cbdb1a3c9f75..2bc68ccf0dc1 100644 --- a/web_src/less/features/projects.less +++ b/web_src/css/features/projects.css @@ -3,14 +3,14 @@ flex-direction: row; flex-wrap: nowrap; overflow-x: auto; - margin: 0 .5em; + margin: 0 0.5em; } .board-column { background-color: var(--color-project-board-bg) !important; border: 1px solid var(--color-secondary) !important; - margin: 0 .5rem !important; - padding: .5rem !important; + margin: 0 0.5rem !important; + padding: 0.5rem !important; width: 320px; height: calc(100vh - 450px); min-height: 60vh; @@ -24,21 +24,22 @@ .board-column-header { display: flex; justify-content: space-between; +} - &.dark-label { - color: var(--color-project-board-dark-label) !important; +.board-column-header.dark-label { + color: var(--color-project-board-dark-label) !important; +} - .board-label { - color: var(--color-project-board-dark-label) !important; - } - } - &.light-label { - color: var(--color-project-board-light-label) !important; +.board-column-header.dark-label .board-label { + color: var(--color-project-board-dark-label) !important; +} + +.board-column-header.light-label { + color: var(--color-project-board-light-label) !important; +} - .board-label { - color: var(--color-project-board-light-label) !important; - } - } +.board-column-header.light-label .board-label { + color: var(--color-project-board-light-label) !important; } .board-label { @@ -81,7 +82,7 @@ border-radius: 5px !important; cursor: move; width: calc(100% - 4px) !important; - padding: .5rem !important; + padding: 0.5rem !important; min-height: auto !important; } @@ -124,24 +125,23 @@ .color-field .minicolors.minicolors-theme-default { display: block; +} - .minicolors-input { - height: 38px; - padding-left: 2rem; - } +.color-field .minicolors.minicolors-theme-default .minicolors-input { + height: 38px; + padding-left: 2rem; +} - .minicolors-swatch { - top: 10px; - } +.color-field .minicolors.minicolors-theme-default .minicolors-swatch { + top: 10px; } -.edit-project-board, -.new-board-modal { - .color.picker.column { - display: flex; +.edit-project-board .color.picker.column, +.new-board-modal .color.picker.column { + display: flex; +} - .minicolors { - flex: 1; - } - } +.edit-project-board .color.picker.column .minicolors, +.new-board-modal .color.picker.column .minicolors { + flex: 1; } diff --git a/web_src/css/font_i18n.css b/web_src/css/font_i18n.css new file mode 100644 index 000000000000..e3de90653202 --- /dev/null +++ b/web_src/css/font_i18n.css @@ -0,0 +1,393 @@ +:root :lang(ja) { + --fonts-override: var(--fonts-default-override-ja); +} + +:root :lang(zh-CN) { + --fonts-override: var(--fonts-default-override-zh-cn); +} + +:root :lang(zh-TW) { + --fonts-override: var(--fonts-default-override-zh-tw); +} + +:root :lang(zh-HK) { + --fonts-override: var(--fonts-default-override-zh-hk); +} + +:root :lang(ko) { + --fonts-override: var(--fonts-default-override-ko); +} + +[lang] { + font-family: var(--fonts-regular); +} + +:root { + --fonts-default-override-ja: system-ui-ja, var(--fonts-proportional); + --fonts-default-override-zh-cn: system-ui-zh-cn, var(--fonts-proportional); + --fonts-default-override-zh-tw: system-ui-zh-tw, var(--fonts-proportional); + --fonts-default-override-zh-hk: system-ui-zh-hk, var(--fonts-proportional); + --fonts-default-override-ko: system-ui-ko, var(--fonts-proportional); +} + +/* Special handling for Firefox on Windows/Linux */ +@supports (-moz-appearance: none) { + :root { + --fonts-default-override-ja: var(--fonts-proportional), system-ui-ja; + --fonts-default-override-zh-cn: var(--fonts-proportional), system-ui-zh-cn; + --fonts-default-override-zh-tw: var(--fonts-proportional), system-ui-zh-tw; + --fonts-default-override-zh-hk: var(--fonts-proportional), system-ui-zh-hk; + --fonts-default-override-ko: var(--fonts-proportional), system-ui-ko; + } +} + +@font-face { + font-family: system-ui-ja; + src: local("HiraKakuProN-W3"), local("Hiragino Kaku Gothic ProN W3"), + local("HiraginoSans-W2"), local("Source Han Sans JP Light"), + local("SourceHanSansJP-Light"), local("Source Han Sans J Light"), + local("SourceHanSansJ-Light"), local("Noto Sans CJK JP Light"), + local("NotoSansCJKJP-Light"), local("Source Han Sans Light"), + local("SourceHanSans-Light"), local("Yu Gothic Regular"), + local("YuGothic Regular"), local("Droid Sans Japanese"), local("Meiryo"), + local("MS PGothic"); + font-weight: 300; + unicode-range: U+11??, U+2E80-4DBF, U+4E00-9FFF, U+A960-A97F, U+AC00-D7FF, + U+F900-FAFF, U+FE00-FE6F, U+FF00-FFEF, U+1F2??, U+2????; +} + +@font-face { + font-family: system-ui-ja; + src: local("HiraKakuProN-W3"), local("Hiragino Kaku Gothic ProN W3"), + local("HiraginoSans-W4"), local("Source Han Sans JP Regular"), + local("SourceHanSansJP-Regular"), local("Source Han Sans J Regular"), + local("SourceHanSansJ-Regular"), local("Noto Sans CJK JP Regular"), + local("NotoSansCJKJP-Regular"), local("Source Han Sans Regular"), + local("SourceHanSans-Regular"), local("Yu Gothic Medium"), + local("YuGothic Medium"), local("Droid Sans Japanese"), local("Meiryo"), + local("MS PGothic"); + font-weight: 400; + unicode-range: U+11??, U+2E80-4DBF, U+4E00-9FFF, U+A960-A97F, U+AC00-D7FF, + U+F900-FAFF, U+FE00-FE6F, U+FF00-FFEF, U+1F2??, U+2????; +} + +@font-face { + font-family: system-ui-ja; + src: local("HiraKakuProN-W3"), local("Hiragino Kaku Gothic ProN W3"), + local("HiraginoSans-W5"), local("Source Han Sans JP Medium"), + local("SourceHanSansJP-Medium"), local("Source Han Sans J Medium"), + local("SourceHanSansJ-Medium"), local("Noto Sans CJK JP Medium"), + local("NotoSansCJKJP-Medium"), local("Source Han Sans Medium"), + local("SourceHanSans-Medium"), local("Yu Gothic Medium"), + local("YuGothic Medium"), local("Droid Sans Japanese"), local("Meiryo"), + local("MS PGothic"); + font-weight: 500; + unicode-range: U+11??, U+2E80-4DBF, U+4E00-9FFF, U+A960-A97F, U+AC00-D7FF, + U+F900-FAFF, U+FE00-FE6F, U+FF00-FFEF, U+1F2??, U+2????; +} + +@font-face { + font-family: system-ui-ja; + src: local("HiraKakuProN-W6"), local("Hiragino Kaku Gothic ProN W6"), + local("HiraginoSans-W6"), local("Source Han Sans JP Bold"), + local("SourceHanSansJP-Bold"), local("Source Han Sans J Bold"), + local("SourceHanSansJ-Bold"), local("Noto Sans CJK JP Bold"), + local("NotoSansCJKJP-Bold"), local("Source Han Sans Bold"), + local("SourceHanSans-Bold"), local("Yu Gothic Bold"), local("YuGothic Bold"), + local("Droid Sans Japanese"), local("Meiryo Bold"), local("MS PGothic"); + font-weight: 700; + unicode-range: U+11??, U+2E80-4DBF, U+4E00-9FFF, U+A960-A97F, U+AC00-D7FF, + U+F900-FAFF, U+FE00-FE6F, U+FF00-FFEF, U+1F2??, U+2????; +} + +/* Safari on macOS/iOS */ +@font-face { + font-family: system-ui-ja; + src: local("HelveticaNeue"); + unicode-range: U+A0; +} + +/* Other browsers on macOS/iOS */ +@supports not (-webkit-hyphens: none) { + @font-face { + font-family: system-ui-ja; + src: local("HelveticaNeue"); + unicode-range: U+20; + } +} + +@font-face { + font-family: system-ui-zh-cn; + src: local("PingFangSC-Light"), local("Source Han Sans CN Light"), + local("SourceHanSansCN-Light"), local("Source Han Sans SC Light"), + local("SourceHanSansSC-Light"), local("Noto Sans CJK SC Light"), + local("NotoSansCJKSC-Light"), local("HiraginoSansGB-W3"), + local("Hiragino Sans GB W3"), local("Microsoft YaHei Light"), + local("Heiti SC Light"), local("SimHei"); + font-weight: 300; + unicode-range: U+11??, U+2E80-4DBF, U+4E00-9FFF, U+A960-A97F, U+AC00-D7FF, + U+F900-FAFF, U+FE00-FE6F, U+FF00-FFEF, U+1F2??, U+2????; +} + +@font-face { + font-family: system-ui-zh-cn; + src: local("PingFangSC-Regular"), local("Source Han Sans CN Regular"), + local("SourceHanSansCN-Regular"), local("Source Han Sans SC Regular"), + local("SourceHanSansSC-Regular"), local("Noto Sans CJK SC Regular"), + local("NotoSansCJKSC-Regular"), local("HiraginoSansGB-W3"), + local("Hiragino Sans GB W3"), local("Microsoft YaHei"), + local("Heiti SC Light"), local("SimHei"); + font-weight: 400; + unicode-range: U+11??, U+2E80-4DBF, U+4E00-9FFF, U+A960-A97F, U+AC00-D7FF, + U+F900-FAFF, U+FE00-FE6F, U+FF00-FFEF, U+1F2??, U+2????; +} + +@font-face { + font-family: system-ui-zh-cn; + src: local("PingFangSC-Medium"), local("Source Han Sans CN Medium"), + local("SourceHanSansCN-Medium"), local("Source Han Sans SC Medium"), + local("SourceHanSansSC-Medium"), local("Noto Sans CJK SC Medium"), + local("NotoSansCJKSC-Medium"), local("HiraginoSansGB-W3"), + local("Hiragino Sans GB W3"), local("Microsoft YaHei"), + local("Heiti SC Light"), local("SimHei"); + font-weight: 500; + unicode-range: U+11??, U+2E80-4DBF, U+4E00-9FFF, U+A960-A97F, U+AC00-D7FF, + U+F900-FAFF, U+FE00-FE6F, U+FF00-FFEF, U+1F2??, U+2????; +} + +@font-face { + font-family: system-ui-zh-cn; + src: local("PingFangSC-Semibold"), local("Source Han Sans CN Bold"), + local("SourceHanSansCN-Bold"), local("Source Han Sans SC Bold"), + local("SourceHanSansSC-Bold"), local("Noto Sans CJK SC Bold"), + local("NotoSansCJKSC-Bold"), local("HiraginoSansGB-W6"), + local("Hiragino Sans GB W6"), local("Microsoft YaHei Bold"), + local("Heiti SC Medium"), local("SimHei"); + font-weight: 700; + unicode-range: U+11??, U+2E80-4DBF, U+4E00-9FFF, U+A960-A97F, U+AC00-D7FF, + U+F900-FAFF, U+FE00-FE6F, U+FF00-FFEF, U+1F2??, U+2????; +} + +/* Safari on macOS/iOS */ +@font-face { + font-family: system-ui-zh-cn; + src: local("HelveticaNeue"); + unicode-range: U+A0; +} + +/* Other browsers on macOS/iOS */ +@supports not (-webkit-hyphens: none) { + @font-face { + font-family: system-ui-zh-cn; + src: local("HelveticaNeue"); + unicode-range: U+20; + } +} + +@font-face { + font-family: system-ui-zh-tw; + src: local("PingFangTC-Light"), local("Source Han Sans TW Light"), + local("SourceHanSansTW-Light"), local("Source Han Sans TC Light"), + local("SourceHanSansTC-Light"), local("Noto Sans CJK TC Light"), + local("NotoSansCJKTC-Light"), local("HiraginoSansTC-W3"), + local("Hiragino Sans TC W3"), local("Microsoft JhengHei Light"), + local("Heiti TC Light"), local("PMingLiU"); + font-weight: 300; + unicode-range: U+11??, U+2E80-4DBF, U+4E00-9FFF, U+A960-A97F, U+AC00-D7FF, + U+F900-FAFF, U+FE00-FE6F, U+FF00-FFEF, U+1F2??, U+2????; +} + +@font-face { + font-family: system-ui-zh-tw; + src: local("PingFangTC-Regular"), local("Source Han Sans TW Regular"), + local("SourceHanSansTW-Regular"), local("Source Han Sans TC Regular"), + local("SourceHanSansTC-Regular"), local("Noto Sans CJK TC Regular"), + local("NotoSansCJKTC-Regular"), local("HiraginoSansTC-W3"), + local("Hiragino Sans TC W3"), local("Microsoft JhengHei"), + local("Heiti TC Light"), local("PMingLiU"); + font-weight: 400; + unicode-range: U+11??, U+2E80-4DBF, U+4E00-9FFF, U+A960-A97F, U+AC00-D7FF, + U+F900-FAFF, U+FE00-FE6F, U+FF00-FFEF, U+1F2??, U+2????; +} + +@font-face { + font-family: system-ui-zh-tw; + src: local("PingFangTC-Medium"), local("Source Han Sans TW Medium"), + local("SourceHanSansTW-Medium"), local("Source Han Sans TC Medium"), + local("SourceHanSansTC-Medium"), local("Noto Sans CJK TC Medium"), + local("NotoSansCJKTC-Medium"), local("HiraginoSansTC-W3"), + local("Hiragino Sans TC W3"), local("Microsoft JhengHei"), + local("Heiti TC Light"), local("PMingLiU"); + font-weight: 500; + unicode-range: U+11??, U+2E80-4DBF, U+4E00-9FFF, U+A960-A97F, U+AC00-D7FF, + U+F900-FAFF, U+FE00-FE6F, U+FF00-FFEF, U+1F2??, U+2????; +} + +@font-face { + font-family: system-ui-zh-tw; + src: local("PingFangTC-Semibold"), local("Source Han Sans TW Bold"), + local("SourceHanSansTW-Bold"), local("Source Han Sans TC Bold"), + local("SourceHanSansTC-Bold"), local("Noto Sans CJK TC Bold"), + local("NotoSansCJKTC-Bold"), local("HiraginoSansTC-W6"), + local("Hiragino Sans TC W6"), local("Microsoft JhengHei Bold"), + local("Heiti TC Medium"), local("PMingLiU"); + font-weight: 700; + unicode-range: U+11??, U+2E80-4DBF, U+4E00-9FFF, U+A960-A97F, U+AC00-D7FF, + U+F900-FAFF, U+FE00-FE6F, U+FF00-FFEF, U+1F2??, U+2????; +} + +/* Safari on macOS/iOS */ +@font-face { + font-family: system-ui-zh-tw; + src: local("HelveticaNeue"); + unicode-range: U+A0; +} + +/* Other browsers on macOS/iOS */ +@supports not (-webkit-hyphens: none) { + @font-face { + font-family: system-ui-zh-tw; + src: local("HelveticaNeue"); + unicode-range: U+20; + } +} + +@font-face { + font-family: system-ui-zh-hk; + src: local("PingFangHK-Light"), local("Source Han Sans HK Light"), + local("SourceHanSansHK-Light"), local("Source Han Sans HC Light"), + local("SourceHanSansHC-Light"), local("Noto Sans CJK HK Light"), + local("NotoSansCJKHK-Light"), local("Source Han Sans TC Light"), + local("SourceHanSansTC-Light"), local("Noto Sans CJK TC Light"), + local("NotoSansCJKTC-Light"), local("HiraginoSansTC-W3"), + local("Hiragino Sans TC W3"), local("Microsoft JhengHei Light"), + local("Heiti TC Light"), local("PMingLiU_HKSCS"), local("PMingLiU"); + font-weight: 300; + unicode-range: U+11??, U+2E80-4DBF, U+4E00-9FFF, U+A960-A97F, U+AC00-D7FF, + U+F900-FAFF, U+FE00-FE6F, U+FF00-FFEF, U+1F2??, U+2????; +} + +@font-face { + font-family: system-ui-zh-hk; + src: local("PingFangHK-Regular"), local("Source Han Sans HK Regular"), + local("SourceHanSansHK-Regular"), local("Source Han Sans HC Regular"), + local("SourceHanSansHC-Regular"), local("Noto Sans CJK HK Regular"), + local("NotoSansCJKHK-Regular"), local("Source Han Sans TC Regular"), + local("SourceHanSansTC-Regular"), local("Noto Sans CJK TC Regular"), + local("NotoSansCJKTC-Regular"), local("HiraginoSansTC-W3"), + local("Hiragino Sans TC W3"), local("Microsoft JhengHei"), + local("Heiti TC Light"), local("PMingLiU_HKSCS"), local("PMingLiU"); + font-weight: 400; + unicode-range: U+11??, U+2E80-4DBF, U+4E00-9FFF, U+A960-A97F, U+AC00-D7FF, + U+F900-FAFF, U+FE00-FE6F, U+FF00-FFEF, U+1F2??, U+2????; +} + +@font-face { + font-family: system-ui-zh-hk; + src: local("PingFangHK-Medium"), local("Source Han Sans HK Medium"), + local("SourceHanSansHK-Medium"), local("Source Han Sans HC Medium"), + local("SourceHanSansHC-Medium"), local("Noto Sans CJK HK Medium"), + local("NotoSansCJKHK-Medium"), local("Source Han Sans TC Medium"), + local("SourceHanSansTC-Medium"), local("Noto Sans CJK TC Medium"), + local("NotoSansCJKTC-Medium"), local("HiraginoSansTC-W3"), + local("Hiragino Sans TC W3"), local("Microsoft JhengHei"), + local("Heiti TC Light"), local("PMingLiU_HKSCS"), local("PMingLiU"); + font-weight: 500; + unicode-range: U+11??, U+2E80-4DBF, U+4E00-9FFF, U+A960-A97F, U+AC00-D7FF, + U+F900-FAFF, U+FE00-FE6F, U+FF00-FFEF, U+1F2??, U+2????; +} + +@font-face { + font-family: system-ui-zh-hk; + src: local("PingFangHK-Semibold"), local("Source Han Sans HK Bold"), + local("SourceHanSansHK-Bold"), local("Source Han Sans HC Bold"), + local("SourceHanSansHC-Bold"), local("Noto Sans CJK HK Bold"), + local("NotoSansCJKHK-Bold"), local("Source Han Sans TC Bold"), + local("SourceHanSansTC-Bold"), local("Noto Sans CJK TC Bold"), + local("NotoSansCJKTC-Bold"), local("HiraginoSansTC-W6"), + local("Hiragino Sans TC W6"), local("Microsoft JhengHei Bold"), + local("Heiti TC Medium"), local("PMingLiU_HKSCS"), local("PMingLiU"); + font-weight: 700; + unicode-range: U+11??, U+2E80-4DBF, U+4E00-9FFF, U+A960-A97F, U+AC00-D7FF, + U+F900-FAFF, U+FE00-FE6F, U+FF00-FFEF, U+1F2??, U+2????; +} + +/* Safari on macOS/iOS */ +@font-face { + font-family: system-ui-zh-hk; + src: local("HelveticaNeue"); + unicode-range: U+A0; +} + +/* Other browsers on macOS/iOS */ +@supports not (-webkit-hyphens: none) { + @font-face { + font-family: system-ui-zh-hk; + src: local("HelveticaNeue"); + unicode-range: U+20; + } +} + +@font-face { + font-family: system-ui-ko; + src: local("AppleSDGothicNeo-Light"), local("Source Han Sans KR Light"), + local("SourceHanSansKR-Light"), local("Source Han Sans K Light"), + local("SourceHanSansK-Light"), local("Noto Sans CJK KR Light"), + local("NotoSansCJKKR-Light"), local("NanumBarunGothic Light"), + local("Malgun Gothic Semilight"), local("Nanum Gothic"), local("Dotum"); + font-weight: 300; + unicode-range: U+11??, U+2E80-4DBF, U+4E00-9FFF, U+A960-A97F, U+AC00-D7FF, + U+F900-FAFF, U+FE00-FE6F, U+FF00-FFEF, U+1F2??, U+2????; +} + +@font-face { + font-family: system-ui-ko; + src: local("AppleSDGothicNeo-Regular"), local("Source Han Sans KR Regular"), + local("SourceHanSansKR-Regular"), local("Source Han Sans K Regular"), + local("SourceHanSansK-Regular"), local("Noto Sans CJK KR Regular"), + local("NotoSansCJKKR-Regular"), local("NanumBarunGothic"), + local("Malgun Gothic"), local("Nanum Gothic"), local("Dotum"); + font-weight: 400; + unicode-range: U+11??, U+2E80-4DBF, U+4E00-9FFF, U+A960-A97F, U+AC00-D7FF, + U+F900-FAFF, U+FE00-FE6F, U+FF00-FFEF, U+1F2??, U+2????; +} + +@font-face { + font-family: system-ui-ko; + src: local("AppleSDGothicNeo-Medium"), local("Source Han Sans KR Medium"), + local("SourceHanSansKR-Medium"), local("Source Han Sans K Medium"), + local("SourceHanSansK-Medium"), local("Noto Sans CJK KR Medium"), + local("NotoSansCJKKR-Medium"), local("NanumBarunGothic"), + local("Malgun Gothic"), local("Nanum Gothic"), local("Dotum"); + font-weight: 500; + unicode-range: U+11??, U+2E80-4DBF, U+4E00-9FFF, U+A960-A97F, U+AC00-D7FF, + U+F900-FAFF, U+FE00-FE6F, U+FF00-FFEF, U+1F2??, U+2????; +} + +@font-face { + font-family: system-ui-ko; + src: local("AppleSDGothicNeo-SemiBold"), local("Source Han Sans KR Bold"), + local("SourceHanSansKR-Bold"), local("Source Han Sans K Bold"), + local("SourceHanSansK-Bold"), local("Noto Sans CJK KR Bold"), + local("NotoSansCJKKR-Bold"), local("NanumBarunGothic Bold"), + local("Malgun Gothic Bold"), local("Nanum Gothic Bold"), local("Dotum"); + font-weight: 700; + unicode-range: U+11??, U+2E80-4DBF, U+4E00-9FFF, U+A960-A97F, U+AC00-D7FF, + U+F900-FAFF, U+FE00-FE6F, U+FF00-FFEF, U+1F2??, U+2????; +} + +/* Safari on macOS/iOS */ +@font-face { + font-family: system-ui-ko; + src: local("HelveticaNeue"); + unicode-range: U+A0; +} + +/* Other browsers on macOS/iOS */ +@supports not (-webkit-hyphens: none) { + @font-face { + font-family: system-ui-ko; + src: local("HelveticaNeue"); + unicode-range: U+20; + } +} diff --git a/web_src/css/form.css b/web_src/css/form.css new file mode 100644 index 000000000000..e325a377f8d8 --- /dev/null +++ b/web_src/css/form.css @@ -0,0 +1,547 @@ +input, +textarea, +.ui.input > input, +.ui.form input:not([type]), +.ui.form select, +.ui.form textarea, +.ui.form input[type="date"], +.ui.form input[type="datetime-local"], +.ui.form input[type="email"], +.ui.form input[type="file"], +.ui.form input[type="number"], +.ui.form input[type="password"], +.ui.form input[type="search"], +.ui.form input[type="tel"], +.ui.form input[type="text"], +.ui.form input[type="time"], +.ui.form input[type="url"], +.ui.selection.dropdown, +.ui.checkbox label::before, +.ui.checkbox input:checked ~ label::before, +.ui.checkbox input:not([type="radio"]):indeterminate ~ label::before { + background: var(--color-input-background); + border-color: var(--color-input-border); + color: var(--color-input-text); +} + +input:hover, +textarea:hover, +.ui.input input:hover, +.ui.form input:not([type]):hover, +.ui.form select:hover, +.ui.form textarea:hover, +.ui.form input[type="date"]:hover, +.ui.form input[type="datetime-local"]:hover, +.ui.form input[type="email"]:hover, +.ui.form input[type="file"]:hover, +.ui.form input[type="number"]:hover, +.ui.form input[type="password"]:hover, +.ui.form input[type="search"]:hover, +.ui.form input[type="tel"]:hover, +.ui.form input[type="text"]:hover, +.ui.form input[type="time"]:hover, +.ui.form input[type="url"]:hover, +.ui.selection.dropdown:hover, +.ui.checkbox label:hover::before, +.ui.checkbox label:active::before, +.ui.radio.checkbox label::after, +.ui.radio.checkbox input:focus ~ label::before, +.ui.radio.checkbox input:checked ~ label::before { + background: var(--color-input-background); + border-color: var(--color-input-border-hover); + color: var(--color-input-text); +} + +input:focus, +textarea:focus, +.ui.input input:focus, +.ui.form input:not([type]):focus, +.ui.form select:focus, +.ui.form textarea:focus, +.ui.form input[type="date"]:focus, +.ui.form input[type="datetime-local"]:focus, +.ui.form input[type="email"]:focus, +.ui.form input[type="file"]:focus, +.ui.form input[type="number"]:focus, +.ui.form input[type="password"]:focus, +.ui.form input[type="search"]:focus, +.ui.form input[type="tel"]:focus, +.ui.form input[type="text"]:focus, +.ui.form input[type="time"]:focus, +.ui.form input[type="url"]:focus, +.ui.selection.dropdown:focus, +.ui.checkbox input:focus ~ label::before, +.ui.checkbox input:not([type="radio"]):indeterminate:focus ~ label::before, +.ui.checkbox input:checked:focus ~ label::before, +.ui.radio.checkbox input:focus:checked ~ label::before { + background: var(--color-input-background); + border-color: var(--color-primary); + color: var(--color-input-text); +} + +.ui.form .field > label, +.ui.form .inline.fields > label, +.ui.form .inline.fields .field > label, +.ui.form .inline.fields .field > p, +.ui.form .inline.field > label, +.ui.form .inline.field > p, +.ui.checkbox label, +.ui.checkbox + label, +.ui.checkbox label:hover, +.ui.checkbox + label:hover, +.ui.checkbox input:focus ~ label, +.ui.checkbox input:active ~ label { + color: var(--color-text); +} + +.ui.input, +.ui.checkbox input:focus ~ label::after, +.ui.checkbox input:checked ~ label::after, +.ui.checkbox label:active::after, +.ui.checkbox input:not([type="radio"]):indeterminate ~ label::after, +.ui.checkbox input:not([type="radio"]):indeterminate:focus ~ label::after, +.ui.checkbox input:checked:focus ~ label::after, +.ui.disabled.checkbox label, +.ui.checkbox input[disabled] ~ label { + color: var(--color-input-text); +} + +.ui.radio.checkbox input:focus ~ label::after, +.ui.radio.checkbox input:checked ~ label::after, +.ui.radio.checkbox input:focus:checked ~ label::after { + background: var(--color-input-text); +} + +.ui.toggle.checkbox label::before { + background: var(--color-input-toggle-background); +} + +.ui.toggle.checkbox label, +.ui.toggle.checkbox input:checked ~ label, +.ui.toggle.checkbox input:focus:checked ~ label { + color: var(--color-text) !important; +} + +.ui.toggle.checkbox input:checked ~ label::before, +.ui.toggle.checkbox input:focus:checked ~ label::before { + background: var(--color-primary) !important; +} + +/* match */ +.ui.form select { + padding: 0.67857143em 1em; +} + +.form .help { + color: var(--color-secondary-dark-5); + padding-bottom: 0.6em; + display: inline-block; +} + +#create-page-form form { + margin: auto; +} + +#create-page-form form .ui.message { + text-align: center; +} + +@media (min-width: 768px) { + #create-page-form form { + width: 800px !important; + } + #create-page-form form .header { + padding-left: 280px !important; + } + #create-page-form form .inline.field > label, + #create-page-form form .inline.field.captcha-field > span { + text-align: right; + width: 250px !important; + word-wrap: break-word; + } + #create-page-form form .help { + margin-left: 265px !important; + } + #create-page-form form .optional .title { + margin-left: 250px !important; + } + #create-page-form form .inline.field > input, + #create-page-form form .inline.field > textarea { + width: 50%; + } +} + +@media (max-width: 767px) { + #create-page-form form .optional .title { + margin-left: 15px; + } + #create-page-form form .inline.field > label { + display: block; + } +} + +.signin .oauth2 div { + display: inline-block; +} + +.signin .oauth2 div p { + margin: 10px 5px 0 0; + float: left; +} + +.signin .oauth2 a { + margin-right: 3px; +} + +.signin .oauth2 a:last-child { + margin-right: 0; +} + +.signin .oauth2 img { + width: 32px; + height: 32px; +} + +.signin .oauth2 img.openidConnect { + width: auto; +} + +@media (min-width: 768px) { + .g-recaptcha-style, + .h-captcha-style { + margin: 0 auto !important; + width: 304px; + padding-left: 30px; + } + .g-recaptcha-style iframe, + .h-captcha-style iframe { + border-radius: 5px !important; + width: 302px !important; + height: 76px !important; + } +} + +@media (max-height: 575px) { + #rc-imageselect, + .g-recaptcha-style, + .h-captcha-style { + transform: scale(0.77); + transform-origin: 0 0; + } +} + +.user.activate form, +.user.forgot.password form, +.user.reset.password form, +.user.link-account form, +.user.signin form, +.user.signup form { + margin: auto; + width: 700px !important; +} + +.user.activate form .ui.message, +.user.forgot.password form .ui.message, +.user.reset.password form .ui.message, +.user.link-account form .ui.message, +.user.signin form .ui.message, +.user.signup form .ui.message { + text-align: center; +} + +@media (min-width: 768px) { + .user.activate form, + .user.forgot.password form, + .user.reset.password form, + .user.link-account form, + .user.signin form, + .user.signup form { + width: 800px !important; + } + .user.activate form .header, + .user.forgot.password form .header, + .user.reset.password form .header, + .user.link-account form .header, + .user.signin form .header, + .user.signup form .header { + padding-left: 280px !important; + } + .user.activate form .inline.field > label, + .user.forgot.password form .inline.field > label, + .user.reset.password form .inline.field > label, + .user.link-account form .inline.field > label, + .user.signin form .inline.field > label, + .user.signup form .inline.field > label, + .user.activate form .inline.field.captcha-field > span, + .user.forgot.password form .inline.field.captcha-field > span, + .user.reset.password form .inline.field.captcha-field > span, + .user.link-account form .inline.field.captcha-field > span, + .user.signin form .inline.field.captcha-field > span, + .user.signup form .inline.field.captcha-field > span { + text-align: right; + width: 250px !important; + word-wrap: break-word; + } + .user.activate form .help, + .user.forgot.password form .help, + .user.reset.password form .help, + .user.link-account form .help, + .user.signin form .help, + .user.signup form .help { + margin-left: 265px !important; + } + .user.activate form .optional .title, + .user.forgot.password form .optional .title, + .user.reset.password form .optional .title, + .user.link-account form .optional .title, + .user.signin form .optional .title, + .user.signup form .optional .title { + margin-left: 250px !important; + } + .user.activate form .inline.field > input, + .user.forgot.password form .inline.field > input, + .user.reset.password form .inline.field > input, + .user.link-account form .inline.field > input, + .user.signin form .inline.field > input, + .user.signup form .inline.field > input, + .user.activate form .inline.field > textarea, + .user.forgot.password form .inline.field > textarea, + .user.reset.password form .inline.field > textarea, + .user.link-account form .inline.field > textarea, + .user.signin form .inline.field > textarea, + .user.signup form .inline.field > textarea { + width: 50%; + } +} + +@media (max-width: 767px) { + .user.activate form .optional .title, + .user.forgot.password form .optional .title, + .user.reset.password form .optional .title, + .user.link-account form .optional .title, + .user.signin form .optional .title, + .user.signup form .optional .title { + margin-left: 15px; + } + .user.activate form .inline.field > label, + .user.forgot.password form .inline.field > label, + .user.reset.password form .inline.field > label, + .user.link-account form .inline.field > label, + .user.signin form .inline.field > label, + .user.signup form .inline.field > label { + display: block; + } +} + +.user.activate form .header, +.user.forgot.password form .header, +.user.reset.password form .header, +.user.link-account form .header, +.user.signin form .header, +.user.signup form .header { + padding-left: 0 !important; + text-align: center; +} + +.user.activate form .inline.field > label, +.user.forgot.password form .inline.field > label, +.user.reset.password form .inline.field > label, +.user.link-account form .inline.field > label, +.user.signin form .inline.field > label, +.user.signup form .inline.field > label { + width: 200px; +} + +@media (max-width: 767px) { + .user.activate form .inline.field > label, + .user.forgot.password form .inline.field > label, + .user.reset.password form .inline.field > label, + .user.link-account form .inline.field > label, + .user.signin form .inline.field > label, + .user.signup form .inline.field > label, + .user.activate form input, + .user.forgot.password form input, + .user.reset.password form input, + .user.link-account form input, + .user.signin form input, + .user.signup form input { + width: 100% !important; + } +} + +.user.activate form input[type="number"], +.user.forgot.password form input[type="number"], +.user.reset.password form input[type="number"], +.user.link-account form input[type="number"], +.user.signin form input[type="number"], +.user.signup form input[type="number"] { + -moz-appearance: textfield; +} + +.user.activate form input::-webkit-outer-spin-button, +.user.forgot.password form input::-webkit-outer-spin-button, +.user.reset.password form input::-webkit-outer-spin-button, +.user.link-account form input::-webkit-outer-spin-button, +.user.signin form input::-webkit-outer-spin-button, +.user.signup form input::-webkit-outer-spin-button, +.user.activate form input::-webkit-inner-spin-button, +.user.forgot.password form input::-webkit-inner-spin-button, +.user.reset.password form input::-webkit-inner-spin-button, +.user.link-account form input::-webkit-inner-spin-button, +.user.signin form input::-webkit-inner-spin-button, +.user.signup form input::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +.user.signin.webauthn-prompt { + margin-top: 15px; +} + +.repository.new.repo form, +.repository.new.migrate form, +.repository.new.fork form { + margin: auto; +} + +.repository.new.repo form .ui.message, +.repository.new.migrate form .ui.message, +.repository.new.fork form .ui.message { + text-align: center; +} + +@media (min-width: 768px) { + .repository.new.repo form, + .repository.new.migrate form, + .repository.new.fork form { + width: 800px !important; + } + .repository.new.repo form .header, + .repository.new.migrate form .header, + .repository.new.fork form .header { + padding-left: 280px !important; + } + .repository.new.repo form .inline.field > label, + .repository.new.migrate form .inline.field > label, + .repository.new.fork form .inline.field > label, + .repository.new.repo form .inline.field.captcha-field > span, + .repository.new.migrate form .inline.field.captcha-field > span, + .repository.new.fork form .inline.field.captcha-field > span { + text-align: right; + width: 250px !important; + word-wrap: break-word; + } + .repository.new.repo form .help, + .repository.new.migrate form .help, + .repository.new.fork form .help { + margin-left: 265px !important; + } + .repository.new.repo form .optional .title, + .repository.new.migrate form .optional .title, + .repository.new.fork form .optional .title { + margin-left: 250px !important; + } + .repository.new.repo form .inline.field > input, + .repository.new.migrate form .inline.field > input, + .repository.new.fork form .inline.field > input, + .repository.new.repo form .inline.field > textarea, + .repository.new.migrate form .inline.field > textarea, + .repository.new.fork form .inline.field > textarea { + width: 50%; + } +} + +@media (max-width: 767px) { + .repository.new.repo form .optional .title, + .repository.new.migrate form .optional .title, + .repository.new.fork form .optional .title { + margin-left: 15px; + } + .repository.new.repo form .inline.field > label, + .repository.new.migrate form .inline.field > label, + .repository.new.fork form .inline.field > label { + display: block; + } +} + +.repository.new.repo form .dropdown .text, +.repository.new.migrate form .dropdown .text, +.repository.new.fork form .dropdown .text { + margin-right: 0 !important; +} + +.repository.new.repo form .header, +.repository.new.migrate form .header, +.repository.new.fork form .header { + padding-left: 0 !important; + text-align: center; +} + +.repository.new.repo form .selection.dropdown, +.repository.new.migrate form .selection.dropdown, +.repository.new.fork form .selection.dropdown { + vertical-align: middle; + width: 50% !important; +} + +@media (max-width: 767px) { + .repository.new.repo form label, + .repository.new.migrate form label, + .repository.new.fork form label, + .repository.new.repo form input, + .repository.new.migrate form input, + .repository.new.fork form input, + .repository.new.repo form .selection.dropdown, + .repository.new.migrate form .selection.dropdown, + .repository.new.fork form .selection.dropdown { + width: 100% !important; + } + .repository.new.repo form .field button, + .repository.new.migrate form .field button, + .repository.new.fork form .field button, + .repository.new.repo form .field a, + .repository.new.migrate form .field a, + .repository.new.fork form .field a { + margin-bottom: 1em; + width: 100%; + } +} + +@media (min-width: 768px) { + .repository.new.repo .ui.form #auto-init { + margin-left: 265px !important; + } +} + +.repository.new.repo .ui.form .selection.dropdown:not(.owner) { + width: 50% !important; +} + +@media (max-width: 767px) { + .repository.new.repo .ui.form .selection.dropdown:not(.owner) { + width: 100% !important; + } +} + +.new.webhook form .help { + margin-left: 25px; +} + +.new.webhook .events.fields .column { + padding-left: 40px; +} + +.githook textarea { + font-family: var(--fonts-monospace); +} + +@media (max-width: 767px) { + .new.org .ui.form .field button, + .new.org .ui.form .field a { + margin-bottom: 1em; + width: 100%; + } + .new.org .ui.form .field input { + width: 100% !important; + } +} diff --git a/web_src/less/helpers.less b/web_src/css/helpers.css similarity index 99% rename from web_src/less/helpers.less rename to web_src/css/helpers.css index 08589fdaab9f..9e974b9ea1b0 100644 --- a/web_src/less/helpers.less +++ b/web_src/css/helpers.css @@ -3,6 +3,7 @@ .gt-dif { display: inline-flex !important; } .gt-dib { display: inline-block !important; } .gt-ac { align-items: center !important; } +.gt-ab { align-items: baseline !important; } .gt-tc { text-align: center !important; } .gt-tl { text-align: left !important; } .gt-tdn { text-decoration: none !important; } @@ -195,7 +196,7 @@ .gt-content-center { align-content: center !important; } -@media @mediaSm { +@media (max-width: 767px) { .gt-db-small { display: block !important; } .gt-w-100-small { width: 100% !important; } .gt-js-small { justify-content: flex-start !important; } diff --git a/web_src/css/home.css b/web_src/css/home.css new file mode 100644 index 000000000000..5d36da594cc9 --- /dev/null +++ b/web_src/css/home.css @@ -0,0 +1,53 @@ +.home .logo { + max-width: 220px; +} + +@media (max-width: 767px) { + .home .hero h1 { + font-size: 3.5em; + } + .home .hero h2 { + font-size: 2em; + } +} + +@media (min-width: 768px) { + .home .hero h1 { + font-size: 5.5em; + } + .home .hero h2 { + font-size: 3em; + } +} + +.home .hero .svg { + color: var(--color-green); + height: 40px; + width: 50px; + vertical-align: bottom; +} + +.home .hero.header { + font-size: 20px; +} + +.home p.large { + font-size: 16px; +} + +.home .stackable { + padding-top: 30px; +} + +.home a { + color: var(--color-green); +} + +@media (max-width: 880px) { + footer .ui.container .left, + footer .ui.container .right { + display: block; + text-align: center; + float: none; + } +} diff --git a/web_src/css/index.css b/web_src/css/index.css new file mode 100644 index 000000000000..dd5f73937926 --- /dev/null +++ b/web_src/css/index.css @@ -0,0 +1,40 @@ +@import "font-awesome/css/font-awesome.css"; + +@import "./animations.css"; +@import "./shared/issuelist.css"; +@import "./features/dropzone.css"; +@import "./features/gitgraph.css"; +@import "./features/heatmap.css"; +@import "./features/imagediff.css"; +@import "./features/codeeditor.css"; +@import "./features/projects.css"; +@import "./modules/tippy.css"; +@import "./code/linebutton.css"; +@import "./markup/content.css"; +@import "./markup/codecopy.css"; +@import "./markup/asciicast.css"; + +@import "./chroma/base.css"; +@import "./chroma/light.css"; +@import "./codemirror/base.css"; +@import "./codemirror/light.css"; +@import "./console/console.css"; + +@import "./svg.css"; +@import "./tribute.css"; +@import "./font_i18n.css"; +@import "./base.css"; +@import "./home.css"; +@import "./install.css"; +@import "./form.css"; +@import "./repository.css"; +@import "./editor.css"; +@import "./organization.css"; +@import "./user.css"; +@import "./dashboard.css"; +@import "./admin.css"; +@import "./explore.css"; +@import "./review.css"; +@import "./package.css"; +@import "./runner.css"; +@import "./helpers.css"; diff --git a/web_src/css/install.css b/web_src/css/install.css new file mode 100644 index 000000000000..b936ba66fd64 --- /dev/null +++ b/web_src/css/install.css @@ -0,0 +1,65 @@ +.page-content.install { + padding-top: 45px; +} + +.page-content.install form.ui.form .inline.field > label { + text-align: right; + width: 30%; + padding-right: 10px; + margin-right: 0; +} + +.page-content.install form.ui.form .inline.field > .ui.checkbox:first-child { + margin-left: 30%; + padding-left: 5px; +} + +.page-content.install form.ui.form .inline.field > .ui.checkbox:first-child label { + width: auto; +} + +.page-content.install form.ui.form .title { + margin-left: 30%; + padding-left: 5px; +} + +.page-content.install form.ui.form input { + width: 60%; +} + +.page-content.install form.ui.form details.optional.field[open] { + border-bottom: 1px solid var(--color-secondary); + padding-bottom: 10px; +} + +.page-content.install form.ui.form details.optional.field[open] summary { + margin-bottom: 10px; +} + +.page-content.install form.ui.form details.optional.field * { + box-sizing: border-box; +} + +.page-content.install form.ui.form .field { + text-align: left; +} + +.page-content.install form.ui.form .field .help { + margin-left: 30%; + padding-left: 5px; + width: 60%; +} + +.page-content.install .ui .reinstall-message { + width: 70%; + margin: 20px auto; + color: var(--color-red); + text-align: left; + font-weight: bold; +} + +.page-content.install .ui .reinstall-confirm { + width: 70%; + text-align: left; + margin: 10px auto; +} diff --git a/web_src/less/markup/asciicast.less b/web_src/css/markup/asciicast.css similarity index 100% rename from web_src/less/markup/asciicast.less rename to web_src/css/markup/asciicast.css diff --git a/web_src/less/markup/codecopy.less b/web_src/css/markup/codecopy.css similarity index 92% rename from web_src/less/markup/codecopy.less rename to web_src/css/markup/codecopy.css index f6f9894fc14b..e3017ae962ec 100644 --- a/web_src/less/markup/codecopy.less +++ b/web_src/css/markup/codecopy.css @@ -9,7 +9,7 @@ right: 6px; padding: 9px; visibility: hidden; - animation: fadeout .2s both; + animation: fadeout 0.2s both; } /* adjustments for comment content having only 14px font size */ @@ -23,6 +23,7 @@ .markup .code-copy:hover { background: var(--color-secondary) !important; } + .markup .code-copy:active { background: var(--color-secondary-dark-1) !important; } @@ -30,5 +31,5 @@ .markup .code-block:hover .code-copy, .markup .mermaid-block:hover .code-copy { visibility: visible; - animation: fadein .2s both; + animation: fadein 0.2s both; } diff --git a/web_src/css/markup/content.css b/web_src/css/markup/content.css new file mode 100644 index 000000000000..00283dd0a254 --- /dev/null +++ b/web_src/css/markup/content.css @@ -0,0 +1,559 @@ +.markup { + overflow: hidden; + font-size: 16px; + line-height: 1.5 !important; + word-wrap: break-word; +} + +.markup.ui.segment { + padding: 3em; +} + +.markup.file-view { + padding: 2em !important; +} + +.markup > *:first-child { + margin-top: 0 !important; +} + +.markup > *:last-child { + margin-bottom: 0 !important; +} + +.markup a:not([href]) { + color: inherit; + text-decoration: none; +} + +.markup .absent { + color: var(--color-red); +} + +.markup .anchor { + padding-right: 4px; + margin-left: -20px; + line-height: 1; + color: inherit; +} + +.markup .anchor .svg { + vertical-align: middle; +} + +.markup .anchor:focus { + outline: none; +} + +.markup h1 .anchor .svg, +.markup h2 .anchor .svg, +.markup h3 .anchor .svg, +.markup h4 .anchor .svg, +.markup h5 .anchor .svg, +.markup h6 .anchor .svg { + visibility: hidden; +} + +.markup h1:hover .anchor .svg, +.markup h2:hover .anchor .svg, +.markup h3:hover .anchor .svg, +.markup h4:hover .anchor .svg, +.markup h5:hover .anchor .svg, +.markup h6:hover .anchor .svg { + visibility: visible; +} + +.markup h2 .anchor .svg, +.markup h3 .anchor .svg, +.markup h4 .anchor .svg { + position: relative; + top: -2px; +} + +.markup h1, +.markup h2, +.markup h3, +.markup h4, +.markup h5, +.markup h6 { + margin-top: 24px; + margin-bottom: 16px; + font-weight: 600; + line-height: 1.25; +} + +.markup h1 tt, +.markup h1 code, +.markup h2 tt, +.markup h2 code, +.markup h3 tt, +.markup h3 code, +.markup h4 tt, +.markup h4 code, +.markup h5 tt, +.markup h5 code, +.markup h6 tt, +.markup h6 code { + font-size: inherit; +} + +.markup h1 { + padding-bottom: 0.3em; + font-size: 2em; + border-bottom: 1px solid var(--color-secondary); +} + +.markup h2 { + padding-bottom: 0.3em; + font-size: 1.5em; + border-bottom: 1px solid var(--color-secondary); +} + +.markup h3 { + font-size: 1.25em; +} + +.markup h4 { + font-size: 1em; +} + +.markup h5 { + font-size: 0.875em; +} + +.markup h6 { + font-size: 0.85em; + color: var(--color-text-light-2); +} + +.markup p, +.markup blockquote, +.markup details, +.markup ul, +.markup ol, +.markup dl, +.markup table, +.markup pre { + margin-top: 0; + margin-bottom: 16px; +} + +.markup hr { + height: 4px; + padding: 0; + margin: 16px 0; + background-color: var(--color-secondary); + border: 0; +} + +.markup ul, +.markup ol { + padding-left: 2em; +} + +.markup ul.no-list, +.markup ol.no-list { + padding: 0; + list-style-type: none; +} + +.markup .task-list-item { + list-style-type: none; + position: relative; + line-height: 1.5rem; + min-height: 1.5rem; /* // to render a checkbox list without content `- [ ]`, we need this min-height to make sure the
  • can be visible */ +} + +.markup .task-list-item input[type="checkbox"] { + position: absolute; + top: 0.25em; + left: -1.6em; +} + +.markup .task-list-item p { + line-height: 1.5rem; +} + +.markup .task-list-item + .task-list-item { + margin-top: 3px; +} + +.markup input[type="checkbox"] { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + position: relative; + border: 1px solid var(--color-secondary); + border-radius: 2px; + background: var(--color-input-background); + height: 14px; + width: 14px; + opacity: 1 !important; /* override fomantic on edit preview */ + pointer-events: auto !important; /* override fomantic on edit preview */ + vertical-align: middle !important; /* override fomantic on edit preview */ + -webkit-print-color-adjust: exact; + color-adjust: exact; +} + +.markup input[type="checkbox"]:not([disabled]):hover, +.markup input[type="checkbox"]:not([disabled]):active { + border-color: var(--color-primary); +} + +.markup input[type="checkbox"]::after { + position: absolute; + left: 0; + top: 0; + bottom: 0; + right: 0; + pointer-events: none; + background: var(--color-text); + mask-size: cover; + -webkit-mask-size: cover; +} + +.markup input[type="checkbox"]:checked::after { + content: ""; + mask-image: var(--checkbox-mask-checked); + -webkit-mask-image: var(--checkbox-mask-checked); + -webkit-print-color-adjust: exact; + color-adjust: exact; +} + +.markup input[type="checkbox"]:indeterminate::after { + content: ""; + mask-image: var(--checkbox-mask-indeterminate); + -webkit-mask-image: var(--checkbox-mask-indeterminate); +} + +.markup ul ul, +.markup ul ol, +.markup ol ol, +.markup ol ul { + margin-top: 0; + margin-bottom: 0; +} + +.markup ol ol, +.markup ul ol { + list-style-type: lower-roman; +} + +.markup li > p { + margin-top: 16px; +} + +.markup li + li { + margin-top: 0.25em; +} + +.markup dl { + padding: 0; +} + +.markup dl dt { + padding: 0; + margin-top: 16px; + font-size: 1em; + font-style: italic; + font-weight: 600; +} + +.markup dl dd { + padding: 0 16px; + margin-bottom: 16px; +} + +.markup blockquote { + margin-left: 0; + padding: 0 15px; + color: var(--color-text-light-2); + border-left: 4px solid var(--color-secondary); +} + +.markup blockquote > :first-child { + margin-top: 0; +} + +.markup blockquote > :last-child { + margin-bottom: 0; +} + +.markup table { + display: block; + width: 100%; + width: max-content; + max-width: 100%; + overflow: auto; +} + +.markup table th { + font-weight: 600; +} + +.markup table th, +.markup table td { + padding: 6px 13px !important; + border: 1px solid var(--color-secondary) !important; +} + +.markup table tr { + border-top: 1px solid var(--color-secondary); +} + +.markup table tr:nth-child(2n) { + background-color: var(--color-markup-table-row); +} + +.markup img { + max-width: 100%; + box-sizing: initial; +} + +.markup img[align="right"] { + padding-left: 20px; +} + +.markup img[align="left"] { + padding-right: 20px; +} + +.markup .emoji { + max-width: none; + vertical-align: text-top; +} + +.markup span.frame { + display: block; + overflow: hidden; +} + +.markup span.frame > span { + display: block; + float: left; + width: auto; + padding: 7px; + margin: 13px 0 0; + overflow: hidden; + border: 1px solid var(--color-secondary); +} + +.markup span.frame span img { + display: block; + float: left; +} + +.markup span.frame span span { + display: block; + padding: 5px 0 0; + clear: both; + color: var(--color-text); +} + +.markup span.align-center { + display: block; + overflow: hidden; + clear: both; +} + +.markup span.align-center > span { + display: block; + margin: 13px auto 0; + overflow: hidden; + text-align: center; +} + +.markup span.align-center span img { + margin: 0 auto; + text-align: center; +} + +.markup span.align-right { + display: block; + overflow: hidden; + clear: both; +} + +.markup span.align-right > span { + display: block; + margin: 13px 0 0; + overflow: hidden; + text-align: right; +} + +.markup span.align-right span img { + margin: 0; + text-align: right; +} + +.markup span.float-left { + display: block; + float: left; + margin-right: 13px; + overflow: hidden; +} + +.markup span.float-left span { + margin: 13px 0 0; +} + +.markup span.float-right { + display: block; + float: right; + margin-left: 13px; + overflow: hidden; +} + +.markup span.float-right > span { + display: block; + margin: 13px auto 0; + overflow: hidden; + text-align: right; +} + +.markup code, +.markup tt { + padding: 0.2em 0.4em; + margin: 0; + font-size: 85%; + white-space: break-spaces; + background-color: var(--color-markup-code-block); + border-radius: 4px; +} + +.markup code br, +.markup tt br { + display: none; +} + +.markup del code { + text-decoration: inherit; +} + +.markup pre > code { + padding: 0; + margin: 0; + font-size: 100%; + white-space: pre-wrap; + word-break: break-all; + overflow-wrap: break-word; + background: transparent; + border: 0; +} + +.markup .highlight { + margin-bottom: 16px; +} + +.markup .highlight pre, +.markup pre { + padding: 16px; + font-size: 85%; + line-height: 1.45; + background-color: var(--color-markup-code-block); + border-radius: 4px; +} + +.markup .highlight pre { + margin-bottom: 0; + word-break: normal; +} + +.markup pre { + word-wrap: normal; +} + +.markup pre code, +.markup pre tt { + display: inline; + max-width: initial; + padding: 0; + margin: 0; + overflow: initial; + line-height: inherit; + word-wrap: normal; + background-color: transparent; + border: 0; +} + +.markup pre code::before, +.markup pre code::after, +.markup pre tt::before, +.markup pre tt::after { + content: normal; +} + +.markup kbd { + display: inline-block; + padding: 3px 5px; + font-size: 11px; + line-height: 10px; + color: var(--color-text-light); + vertical-align: middle; + background-color: var(--color-markup-code-block); + border: 1px solid var(--color-secondary); + border-radius: 3px; + box-shadow: inset 0 -1px 0 var(--color-secondary); +} + +.markup .ui.list .list, +.markup ol.ui.list ol, +.markup ul.ui.list ul { + padding-left: 2em; +} + +.repository.wiki.revisions .ui.container > .ui.stackable.grid { + -ms-flex-direction: row-reverse; + flex-direction: row-reverse; +} + +.repository.wiki.revisions .ui.container > .ui.stackable.grid > .header { + margin-top: 0; +} + +.repository.wiki.revisions .ui.container > .ui.stackable.grid > .header .sub.header { + padding-left: 52px; + word-break: break-word; +} + +.file-revisions-btn { + display: block; + float: left; + margin-bottom: 2px !important; + padding: 11px !important; + margin-right: 10px !important; +} + +.file-revisions-btn i { + -webkit-touch-callout: none; + -webkit-user-select: none; + user-select: none; +} + +.markup-render { + display: block; + border: none; + width: 100%; + height: var(--height-loading); /* actual height is set in JS after loading */ + overflow: hidden; + color-scheme: normal; /* match the value inside the iframe to allow it to become transparent */ +} + +.markup-block-error { + border: 1px solid var(--color-error-border) !important; + margin-bottom: 0 !important; + border-bottom-left-radius: 0 !important; + border-bottom-right-radius: 0 !important; + box-shadow: none !important; + font-size: 85% !important; + white-space: pre-wrap !important; + padding: 0.5rem 1rem !important; + text-align: left !important; +} + +.markup-block-error + pre { + border-top: none !important; + margin-top: 0 !important; + border-top-left-radius: 0 !important; + border-top-right-radius: 0 !important; +} diff --git a/web_src/less/modules/tippy.less b/web_src/css/modules/tippy.css similarity index 96% rename from web_src/less/modules/tippy.less rename to web_src/css/modules/tippy.css index 68d6eb7fa3a8..a026f9c6b633 100644 --- a/web_src/less/modules/tippy.less +++ b/web_src/css/modules/tippy.css @@ -1,6 +1,6 @@ /* styles are based on node_modules/tippy.js/dist/tippy.css */ -// class to hide tippy target elements on page load +/* class to hide tippy target elements on page load */ .tippy-target { display: none !important; } @@ -40,7 +40,7 @@ } .tippy-box[data-theme="tooltip"] .tippy-content { - padding: .5rem 1rem; + padding: 0.5rem 1rem; } .tippy-box[data-theme="menu"] .tippy-content { diff --git a/web_src/css/organization.css b/web_src/css/organization.css new file mode 100644 index 000000000000..0a7cd26513db --- /dev/null +++ b/web_src/css/organization.css @@ -0,0 +1,250 @@ +#create-page-form form { + margin: auto; +} + +#create-page-form form .ui.message { + text-align: center; +} + +@media (min-width: 768px) { + #create-page-form form { + width: 800px !important; + } + #create-page-form form .header { + padding-left: 280px !important; + } + #create-page-form form .inline.field > label, + #create-page-form form .inline.field.captcha-field > span { + text-align: right; + width: 250px !important; + word-wrap: break-word; + } + #create-page-form form .help { + margin-left: 265px !important; + } + #create-page-form form .optional .title { + margin-left: 250px !important; + } + #create-page-form form .inline.field > input, + #create-page-form form .inline.field > textarea { + width: 50%; + } +} + +@media (max-width: 767px) { + #create-page-form form .optional .title { + margin-left: 15px; + } + #create-page-form form .inline.field > label { + display: block; + } +} + +.organization .head .ui.header .text { + vertical-align: middle; + font-size: 1.6rem; + margin-left: 15px; +} + +.organization .head .ui.header .org-visibility .label { + margin-left: 5px; + margin-top: 5px; +} + +.organization .head .ui.header .ui.right { + margin-top: 5px; +} + +.organization .ui.secondary.stackable.pointing.menu { + flex-wrap: wrap; + margin-top: 5px; + margin-bottom: 10px; +} + +.organization.new.org form { + margin: auto; +} + +.organization.new.org form .ui.message { + text-align: center; +} + +@media (min-width: 768px) { + .organization.new.org form { + width: 800px !important; + } + .organization.new.org form .header { + padding-left: 280px !important; + } + .organization.new.org form .inline.field > label, + .organization.new.org form .inline.field.captcha-field > span { + text-align: right; + width: 250px !important; + word-wrap: break-word; + } + .organization.new.org form .help { + margin-left: 265px !important; + } + .organization.new.org form .optional .title { + margin-left: 250px !important; + } + .organization.new.org form .inline.field > input, + .organization.new.org form .inline.field > textarea { + width: 50%; + } +} + +@media (max-width: 767px) { + .organization.new.org form .optional .title { + margin-left: 15px; + } + .organization.new.org form .inline.field > label { + display: block; + } +} + +.organization.new.org form .header { + padding-left: 0 !important; + text-align: center; +} + +.organization.options input { + min-width: 300px; +} + +.organization.profile .org-avatar { + width: 100px; + height: 100px; + margin-right: 15px; +} + +.organization.profile #org-info { + overflow-wrap: anywhere; +} + +.organization.profile #org-info .ui.header { + display: flex; + align-items: center; + font-size: 36px; + margin-bottom: 0; +} + +.organization.profile #org-info .ui.header .org-visibility .label { + margin-left: 5px; + margin-top: 2px; +} + +.organization.profile #org-info .desc { + font-size: 16px; + margin-bottom: 10px; +} + +.organization.profile #org-info .meta .item { + display: inline-block; + margin-right: 10px; +} + +.organization.profile #org-info .meta .item .icon { + margin-right: 5px; +} + +.organization.profile .ui.top.header .ui.right { + margin-top: 0; +} + +.organization.profile .teams .item { + padding: 10px 15px; +} + +.organization.teams .members a:hover, +.organization.profile .members a:hover { + text-decoration: none; +} + +.organization.teams .members .ui.avatar, +.organization.profile .members .ui.avatar { + width: 48px; + height: 48px; + margin-right: 5px; + margin-bottom: 5px; +} + +.organization.invite #invite-box { + margin: 50px auto auto; + width: 500px !important; +} + +.organization.invite #invite-box #search-user-box input { + margin-left: 0; + width: 300px; +} + +.organization.invite #invite-box .ui.button { + margin-left: 5px; + margin-top: -3px; +} + +.organization.invite .ui.avatar { + width: 100%; + height: 100%; +} + +.organization.members .list .item { + margin-left: 0; + margin-right: 0; + border-bottom: 1px solid var(--color-secondary); +} + +.organization.members .list .item .ui.avatar { + width: 48px; + height: auto; + margin-right: 1rem; + align-self: flex-start; +} + +.organization.members .list .item .meta { + line-height: 24px; + word-break: break-word; + min-width: 2em; +} + +.organization.teams .detail .item { + padding: 10px 15px; +} + +.organization.teams .detail .item:not(:last-child) { + border-bottom: 1px solid var(--color-secondary); +} + +.organization.teams .repositories .item, +.organization.teams .members .item { + padding: 10px 20px; + line-height: 32px; +} + +.organization.teams .repositories .item:not(:last-child), +.organization.teams .members .item:not(:last-child) { + border-bottom: 1px solid var(--color-secondary); +} + +.organization.teams .repositories .item .button, +.organization.teams .members .item .button { + padding: 9px 10px; +} + +.organization.teams #add-repo-form input, +.organization.teams #repo-multiple-form input, +.organization.teams #add-member-form input { + margin-left: 0; +} + +.organization.teams #add-repo-form .ui.button, +.organization.teams #repo-multiple-form .ui.button, +.organization.teams #add-member-form .ui.button { + margin-left: 5px; + margin-top: -3px; +} + +.organization.teams #repo-top-segment { + height: 60px; +} diff --git a/web_src/css/package.css b/web_src/css/package.css new file mode 100644 index 000000000000..c229e176f520 --- /dev/null +++ b/web_src/css/package.css @@ -0,0 +1,7 @@ +.container-labels td:nth-child(1) { + vertical-align: top; +} + +.container-labels td:nth-child(2) { + overflow-wrap: anywhere; +} diff --git a/web_src/css/repository.css b/web_src/css/repository.css new file mode 100644 index 000000000000..ad2ac49b9984 --- /dev/null +++ b/web_src/css/repository.css @@ -0,0 +1,3629 @@ +.repository .data-table .line-num, +.repository .diff-file-box .file-body.file-code .lines-num, +.repository .diff-file-box .code-diff tbody tr .lines-type-marker, +.repository .repository-summary .segment.language-stats { + -webkit-touch-callout: none; + -webkit-user-select: none; + user-select: none; +} + +.repository .repo-header .ui.compact.menu { + margin-left: 1rem; +} + +.repository .repo-header .ui.header { + margin-top: 0; +} + +.repository .repo-header .fork-flag { + font-size: 12px; + margin-top: 2px; +} + +.repository .repo-header .repo-buttons .svg { + margin: 0 0.42857143em 0 -0.21428571em; +} + +.repository .repo-header .button { + margin-top: 2px; + margin-bottom: 2px; +} + +.repository .tabs .navbar { + justify-content: initial; +} + +.repository .navbar { + display: flex; + justify-content: space-between; +} + +.repository .navbar .ui.label { + margin-left: 7px; + padding: 3px 5px; +} + +.repository .owner.dropdown { + min-width: 40% !important; +} + +.repository .unicode-escaped .escaped-code-point[data-escaped]::before { + visibility: visible; + content: attr(data-escaped); + font-family: var(--fonts-monospace); + color: var(--color-red); +} + +.repository .unicode-escaped .escaped-code-point .char { + display: none; +} + +.repository .broken-code-point { + font-family: var(--fonts-monospace); + color: var(--color-blue); +} + +.repository .unicode-escaped .ambiguous-code-point { + border: 1px var(--color-yellow) solid; +} + +.repository .metas .menu { + overflow-x: auto; + max-height: 500px; +} + +.repository .metas .ui.list.assignees .icon { + line-height: 2em; +} + +.repository .metas .ui.list.assignees .teamavatar { + margin-top: 0.125rem; + margin-left: 6.75px; + margin-right: 8.75px; +} + +.repository .metas .ui.list .dependency { + padding: 0; + white-space: nowrap; +} + +.repository .metas .ui.list .title { + max-width: 200px; + overflow: hidden; + text-overflow: ellipsis; +} + +@media (max-width: 1200px) { + .repository .metas .ui.list .title { + max-width: 150px; + } +} + +@media (max-width: 1000px) { + .repository .metas .ui.list .title { + max-width: 100px; + } +} + +.repository .metas #deadlineForm input { + width: 12.8rem; + border-radius: 4px 0 0 4px; + border-right: 0; + white-space: nowrap; +} + +.repository .header-wrapper { + background-color: var(--color-navbar); +} + +.repository .header-wrapper .ui.tabs.divider { + border-bottom: 0; +} + +.repository .header-wrapper .ui.tabular .svg { + margin-right: 5px; +} + +.repository .filter.menu.labels .label-filter .menu .info { + display: inline-block; + padding: 0.5rem 0.25rem; + border-bottom: 1px solid var(--color-secondary); + font-size: 12px; + width: 100%; + white-space: nowrap; + text-align: center; +} + +.repository .filter.menu.labels .label-filter .menu .info code { + border: 1px solid var(--color-secondary); + border-radius: 3px; + padding: 1px 2px; + font-size: 11px; +} + +.repository .filter.menu .menu { + max-height: 500px; + overflow-x: auto; + right: 0 !important; + left: auto !important; +} + +.repository .select-label .desc { + padding-left: 23px; +} + +.repository .ui.tabs.container { + margin-top: 14px; + margin-bottom: 0; +} + +.repository .ui.tabs.container .ui.menu { + border-bottom: 0; +} + +.repository .ui.tabs.divider { + margin-top: 0; + margin-bottom: 20px; +} + +.repository #clone-panel #repo-clone-url { + width: 320px; +} + +@media (min-width: 768px) and (max-width: 991px) { + .repository #clone-panel #repo-clone-url { + width: 200px; + } +} + +@media (max-width: 767px) { + .repository #clone-panel #repo-clone-url { + width: 200px; + } +} + +.repository #clone-panel #repo-clone-https, +.repository #clone-panel #repo-clone-ssh { + border-right: none; +} + +.repository #clone-panel #more-btn { + border-left: none; +} + +.repository #clone-panel button:first-of-type { + border-radius: var(--border-radius) 0 0 var(--border-radius) !important; +} + +.repository #clone-panel button:last-of-type { + border-radius: 0 var(--border-radius) var(--border-radius) 0 !important; +} + +.repository #clone-panel .dropdown .menu { + right: 0 !important; + left: auto !important; +} + +.repository.file.list .repo-description { + display: flex; + justify-content: space-between; + align-items: center; +} + +.repository.file.list #repo-desc { + font-size: 1.2em; +} + +.repository.file.list .repo-path .section, +.repository.file.list .repo-path .divider { + display: inline; +} + +.repository.file.list #repo-files-table { + table-layout: fixed; +} + +.repository.file.list #repo-files-table thead th { + padding-top: 8px; + padding-bottom: 5px; + font-weight: normal; +} + +.repository.file.list #repo-files-table thead .ui.avatar { + margin-bottom: 5px; +} + +.repository.file.list #repo-files-table tbody .svg { + margin-left: 3px; + margin-right: 5px; +} + +.repository.file.list #repo-files-table tbody .svg.octicon-reply { + margin-right: 10px; +} + +.repository.file.list #repo-files-table tbody .svg.octicon-file-directory-fill, +.repository.file.list #repo-files-table tbody .svg.octicon-file-submodule { + color: var(--color-primary); +} + +.repository.file.list #repo-files-table tbody .svg.octicon-file, +.repository.file.list #repo-files-table tbody .svg.octicon-file-symlink-file { + color: var(--color-secondary-dark-7); +} + +.repository.file.list #repo-files-table td { + padding-top: 0; + padding-bottom: 0; + overflow: initial; +} + +.repository.file.list #repo-files-table td.name { + width: 33%; + max-width: calc(100vw - 140px); +} + +@media (min-width: 1201px) { + .repository.file.list #repo-files-table td.name { + max-width: 150px; + } +} + +@media (min-width: 992px) and (max-width: 1200px) { + .repository.file.list #repo-files-table td.name { + max-width: 200px; + } +} + +@media (min-width: 768px) and (max-width: 991px) { + .repository.file.list #repo-files-table td.name { + max-width: 300px; + } +} + +.repository.file.list #repo-files-table td.message { + color: var(--color-text-light-1); + width: 66%; +} + +@media (min-width: 1201px) { + .repository.file.list #repo-files-table td.message { + max-width: 400px; + } +} + +@media (min-width: 992px) and (max-width: 1200px) { + .repository.file.list #repo-files-table td.message { + max-width: 350px; + } +} + +@media (min-width: 768px) and (max-width: 991px) { + .repository.file.list #repo-files-table td.message { + max-width: 250px; + } +} + +.repository.file.list #repo-files-table td.age { + width: 120px; + color: var(--color-text-light-1); +} + +.repository.file.list #repo-files-table td .truncate { + display: inline-block; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + width: 100%; + padding-top: 8px; + padding-bottom: 8px; +} + +.repository.file.list #repo-files-table td a { + padding-top: 8px; + padding-bottom: 8px; +} + +.repository.file.list #repo-files-table td .at { + margin-left: 3px; + margin-right: 3px; +} + +.repository.file.list #repo-files-table td > * { + vertical-align: middle; +} + +.repository.file.list #repo-files-table td.message .isSigned { + cursor: default; +} + +.repository.file.list #repo-files-table tr:last-of-type td:first-child { + border-bottom-left-radius: var(--border-radius); +} + +.repository.file.list #repo-files-table tr:last-of-type td:last-child { + border-bottom-right-radius: var(--border-radius); +} + +.repository.file.list #repo-files-table tr:hover { + background-color: var(--color-hover); +} + +.repository.file.list #repo-files-table tr.has-parent a { + display: inline-block; + padding-top: 8px; + padding-bottom: 8px; + width: calc(100% - 1.25rem); +} + +.repository.file.list .non-diff-file-content .header .icon { + font-size: 1em; +} + +.repository.file.list .non-diff-file-content .header .small.icon { + font-size: 0.75em; +} + +.repository.file.list .non-diff-file-content .header .tiny.icon { + font-size: 0.5em; +} + +.repository.file.list .non-diff-file-content .header .file-actions .btn-octicon { + line-height: 1; + padding: 10px 8px; + vertical-align: middle; + color: var(--color-text); +} + +.repository.file.list .non-diff-file-content .header .file-actions .btn-octicon:hover { + color: var(--color-primary); +} + +.repository.file.list .non-diff-file-content .header .file-actions .btn-octicon-danger:hover { + color: var(--color-red); +} + +.repository.file.list .non-diff-file-content .header .file-actions .btn-octicon.disabled { + color: inherit; + opacity: var(--opacity-disabled); + cursor: default; +} + +.repository.file.list .non-diff-file-content .view-raw { + padding: 5px; +} + +.repository.file.list .non-diff-file-content .view-raw > * { + max-width: 100%; + border: 1px solid var(--color-secondary); +} + +.repository.file.list .non-diff-file-content .view-raw img { + margin: 1rem 0; + border-radius: 0; + object-fit: contain; +} + +.repository.file.list .non-diff-file-content .view-raw img[src$=".svg" i] { + max-height: 600px !important; + max-width: 600px !important; +} + +.repository.file.list .non-diff-file-content .plain-text { + padding: 1em 2em; +} + +.repository.file.list .non-diff-file-content .plain-text pre { + word-break: break-word; + white-space: pre-wrap; +} + +.repository.file.list .non-diff-file-content .csv { + overflow-x: auto; + padding: 0 !important; +} + +.repository.file.list .non-diff-file-content pre { + overflow: auto; +} + +.repository.file.list .non-diff-file-content .asciicast { + padding: 5px !important; +} + +.repository.file.list .sidebar { + padding-left: 0; +} + +.repository.file.list .sidebar .svg { + width: 16px; +} + +.repository.file.editor .treepath { + width: 100%; +} + +.repository.file.editor .treepath input { + vertical-align: middle; + box-shadow: rgba(0, 0, 0, 0.0745098) 0 1px 2px inset; + width: inherit; + padding: 7px 8px; + margin-right: 5px; +} + +.repository.file.editor .tabular.menu .svg { + margin-right: 5px; +} + +.repository.file.editor .commit-form-wrapper { + padding-left: 64px; +} + +.repository.file.editor .commit-form-wrapper .commit-avatar { + float: left; + margin-left: -64px; + width: 3em; + height: auto; +} + +.repository.file.editor .commit-form-wrapper .commit-form { + position: relative; + padding: 15px; + margin-bottom: 10px; + border: 1px solid var(--color-secondary); + background: var(--color-box-body); + border-radius: 3px; +} + +.repository.file.editor .commit-form-wrapper .commit-form::before, +.repository.file.editor .commit-form-wrapper .commit-form::after { + right: 100%; + top: 20px; + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; +} + +.repository.file.editor .commit-form-wrapper .commit-form::before { + border-right-color: var(--color-secondary); + border-width: 9px; + margin-top: -9px; +} + +.repository.file.editor .commit-form-wrapper .commit-form::after { + border-right-color: var(--color-box-body); + border-width: 8px; + margin-top: -8px; +} + +.repository.file.editor .commit-form-wrapper .commit-form .quick-pull-choice .branch-name { + display: inline-block; + padding: 2px 4px; + font: 12px var(--fonts-monospace); + color: var(--color-text); + background: var(--color-secondary); + border-radius: 3px; + margin: 0 2px; +} + +.repository.file.editor .commit-form-wrapper .commit-form .quick-pull-choice .new-branch-name-input { + position: relative; + margin-left: 25px; +} + +.repository.file.editor .commit-form-wrapper .commit-form .quick-pull-choice .new-branch-name-input input { + width: 240px !important; + padding-left: 26px !important; +} + +.repository.file.editor .commit-form-wrapper .commit-form .quick-pull-choice .octicon-git-branch { + position: absolute; + top: 9px; + left: 10px; + color: var(--color-grey); +} + +.repository.options #interval { + width: 100px !important; + min-width: 100px; +} + +.repository.options .danger .item { + padding: 20px 15px; +} + +.repository.options .danger .ui.divider { + margin: 0; +} + +.repository .comment textarea { + max-height: none !important; +} + +.repository.new.issue .comment.form .comment .avatar { + width: 3em; +} + +.repository.new.issue .comment.form .content { + margin-left: 4em; +} + +.repository.new.issue .comment.form .content::before, +.repository.new.issue .comment.form .content::after { + right: 100%; + top: 20px; + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; +} + +.repository.new.issue .comment.form .content::before { + border-right-color: var(--color-secondary); + border-width: 9px; + margin-top: -9px; +} + +.repository.new.issue .comment.form .content::after { + border-right-color: var(--color-box-body); + border-width: 8px; + margin-top: -8px; +} + +.repository.new.issue .comment.form .content .markup { + font-size: 14px; +} + +.repository.new.issue .comment.form .metas { + min-width: 220px; +} + +.repository.new.issue .comment.form .metas .filter.menu { + max-height: 500px; + overflow-x: auto; +} + +.repository.view.issue .instruct-toggle { + display: inline-block; +} + +.repository.view.issue .title { + padding-bottom: 0 !important; +} + +.repository.view.issue .title .issue-title { + margin-bottom: 0.5rem; +} + +.repository.view.issue .title .issue-title.edit-active { + display: flex; + align-items: center; +} + +.repository.view.issue .title .issue-title.edit-active h1 { + display: flex; + width: 100%; +} + +@media (max-width: 767px) { + .repository.view.issue .title .issue-title.edit-active { + flex-direction: column; + } + .repository.view.issue .title .issue-title.edit-active h1 { + margin-right: 0; + margin-bottom: 1rem; + padding-right: 0; + } + .repository.view.issue .title .issue-title.edit-active h1 .ui.input input { + width: calc(100% - 2rem); + } + .repository.view.issue .title .issue-title.edit-active .edit-buttons { + padding-bottom: 1rem; + width: 100%; + } + .repository.view.issue .title .issue-title.edit-active .edit-buttons .button { + width: 100%; + margin-right: 0.5rem; + } + .repository.view.issue .title .issue-title.edit-active .edit-buttons .button:last-child { + margin-right: 0; + } +} + +.repository.view.issue .title .issue-title h1 { + font-weight: 300; + font-size: 2.3rem; + margin: 0; + padding-right: 0.5rem; +} + +.repository.view.issue .title .issue-title h1 .ui.input { + font-size: 0.5em; + width: 100%; +} + +.repository.view.issue .title .issue-title h1 .ui.input input { + font-size: 1.5em; + padding: 6px 1rem; +} + +.repository.view.issue .title .issue-title .edit-button { + float: right; + padding-left: 1rem; +} + +.repository.view.issue .title .issue-title .edit-buttons { + display: flex; +} + +.repository.view.issue .title .issue-title .index { + color: var(--color-text-light-2); +} + +.repository.view.issue .title .issue-title .label { + margin-right: 10px; +} + +.repository.view.issue .title .issue-title .edit-zone { + margin-top: 10px; +} + +.repository.view.issue .pull-desc code { + color: var(--color-primary); +} + +.repository.view.issue .pull-desc a[data-clipboard-text] { + cursor: pointer; +} + +.repository.view.issue .pull-desc a[data-clipboard-text] svg { + vertical-align: middle; + position: relative; + top: -2px; + right: 1px; +} + +.repository.view.issue .pull.tabular.menu { + margin-bottom: 1rem; +} + +.repository.view.issue .pull.tabular.menu .svg { + margin-right: 5px; +} + +.repository.view.issue .pull .merge.box .avatar { + margin-left: 10px; + margin-top: 10px; +} + +.repository.view.issue .pull .merge.box .branch-update.grid .row { + padding-bottom: 1rem; +} + +.repository.view.issue .pull .merge.box .branch-update.grid .row .icon { + margin-top: 1.1rem; +} + +.repository.view.issue .pull .review-item { + display: flex; + justify-content: space-between; + align-items: center; +} + +.repository.view.issue .pull .review-item .review-item-left, +.repository.view.issue .pull .review-item .review-item-right { + display: flex; + align-items: center; +} + +.repository.view.issue .pull .review-item .text { + margin: 0.3em 0 0.5em 0.5em; +} + +.repository.view.issue .pull .review-item .type-icon { + align-self: flex-start; + margin-right: 1em; +} + +.repository.view.issue .pull .review-item .type-icon i { + line-height: 1.8em; +} + +.repository.view.issue .pull .review-item .divider { + margin: 0.5rem 0; +} + +.repository.view.issue .pull .review-item .review-content { + padding: 1em 0 1em 3.8em; +} + +.repository.view.issue .comment-list:not(.prevent-before-timeline)::before { + display: block; + content: ""; + position: absolute; + margin-top: 12px; + margin-bottom: 14px; + top: 0; + bottom: 0; + left: 96px; + width: 2px; + background-color: var(--color-timeline); + z-index: -1; +} + +.repository.view.issue .comment-list .timeline { + position: relative; + display: block; + margin-left: 40px; + padding-left: 16px; +} + +.repository.view.issue .comment-list .timeline::before { /* ciara */ + display: block; + content: ""; + position: absolute; + margin-top: 12px; + margin-bottom: 14px; + top: 0; + bottom: 0; + left: 30px; + width: 2px; + background-color: var(--color-timeline); + z-index: -1; +} + +.repository.view.issue .comment-list .timeline-item, +.repository.view.issue .comment-list .timeline-item-group { + padding: 12px 0; +} + +.repository.view.issue .comment-list .timeline-item-group .timeline-item { + padding-top: 8px; + padding-bottom: 8px; +} + +.repository.view.issue .comment-list .timeline-item { + margin-left: 16px; + position: relative; +} + +.repository.view.issue .comment-list .timeline-item .timeline-avatar { + position: absolute; + left: -68px; +} + +.repository.view.issue .comment-list .timeline-item .timeline-avatar img { + width: 40px !important; + height: 40px !important; +} + +/* Don't show the mobile oriented avatar ".inline-timeline-avatar" on desktop. Desktop uses the avatar with class ".timeline-avatar" */ +.repository.view.issue .comment-list .timeline-item .inline-timeline-avatar { + display: none; +} + +.repository.view.issue .comment-list .timeline-item img.avatar, +.repository.view.issue .comment-list .timeline-item .avatar img { + width: 20px; + height: 20px; + vertical-align: middle; +} + +.repository.view.issue .comment-list .timeline-item:first-child:not(.commit) { + padding-top: 0 !important; +} + +.repository.view.issue .comment-list .timeline-item:last-child:not(.commit) { + padding-bottom: 0 !important; +} + +.repository.view.issue .comment-list .timeline-item .badge.badge-commit { + border-color: transparent; + background: radial-gradient(var(--color-body) 40%, transparent 40%) no-repeat; +} + +.repository.view.issue .comment-list .timeline-item .badge { + width: 34px; + height: 34px; + background-color: var(--color-timeline); + border-radius: 50%; + display: flex; + float: left; + margin-left: -33px; + margin-right: 8px; + color: var(--color-text); + align-items: center; + justify-content: center; +} + +.repository.view.issue .comment-list .timeline-item .badge .svg { + width: 22px; + height: 22px; + padding: 3px; +} + +.repository.view.issue .comment-list .timeline-item .badge .svg.octicon-comment { + margin-top: 2px; +} + +.repository.view.issue .comment-list .timeline-item.comment > .content { + margin-left: -16px; +} + +.repository.view.issue .comment-list .timeline-item.event > .text { + line-height: 32px; + vertical-align: middle; +} + +.repository.view.issue .comment-list .timeline-item.commits-list { + padding-left: 15px; + padding-top: 0; +} + +.repository.view.issue .comment-list .timeline-item.commits-list .singular-commit { + line-height: 34px; /* this must be same as .badge height, to avoid overflow */ + clear: both; /* reset the "float right shabox", in the future, use flexbox instead */ +} + +.repository.view.issue .comment-list .timeline-item.commits-list .singular-commit > img.avatar, +.repository.view.issue .comment-list .timeline-item.commits-list .singular-commit > .avatar img { + position: relative; + top: -2px; +} + +.repository.view.issue .comment-list .timeline-item.commits-list .singular-commit .shabox .sha.label { + margin: 0; + border: 1px solid var(--color-light-border); +} + +.repository.view.issue .comment-list .timeline-item.commits-list .singular-commit .shabox .sha.label.isSigned.isWarning { + border: 1px solid var(--color-red-badge); + background: var(--color-red-badge-bg); +} + +.repository.view.issue .comment-list .timeline-item.commits-list .singular-commit .shabox .sha.label.isSigned.isWarning .shortsha { + display: inline-block; + padding-top: 1px; +} + +.repository.view.issue .comment-list .timeline-item.commits-list .singular-commit .shabox .sha.label.isSigned.isWarning:hover { + background: var(--color-red-badge-hover-bg) !important; +} + +.repository.view.issue .comment-list .timeline-item.commits-list .singular-commit .shabox .sha.label.isSigned.isVerified { + border: 1px solid var(--color-green-badge); + background: var(--color-green-badge-bg); +} + +.repository.view.issue .comment-list .timeline-item.commits-list .singular-commit .shabox .sha.label.isSigned.isVerified .shortsha { + display: inline-block; + padding-top: 1px; +} + +.repository.view.issue .comment-list .timeline-item.commits-list .singular-commit .shabox .sha.label.isSigned.isVerified:hover { + background: var(--color-green-badge-hover-bg) !important; +} + +.repository.view.issue .comment-list .timeline-item.commits-list .singular-commit .shabox .sha.label.isSigned.isVerifiedUntrusted { + border: 1px solid var(--color-yellow-badge); + background: var(--color-yellow-badge-bg); +} + +.repository.view.issue .comment-list .timeline-item.commits-list .singular-commit .shabox .sha.label.isSigned.isVerifiedUntrusted .shortsha { + display: inline-block; + padding-top: 1px; +} + +.repository.view.issue .comment-list .timeline-item.commits-list .singular-commit .shabox .sha.label.isSigned.isVerifiedUntrusted:hover { + background: var(--color-yellow-badge-hover-bg) !important; +} + +.repository.view.issue .comment-list .timeline-item.commits-list .singular-commit .shabox .sha.label.isSigned.isVerifiedUnmatched { + border: 1px solid var(--color-orange-badge); + background: var(--color-orange-badge-bg); +} + +.repository.view.issue .comment-list .timeline-item.commits-list .singular-commit .shabox .sha.label.isSigned.isVerifiedUnmatched .shortsha { + display: inline-block; + padding-top: 1px; +} + +.repository.view.issue .comment-list .timeline-item.commits-list .singular-commit .shabox .sha.label.isSigned.isVerifiedUnmatched:hover { + background: var(--color-orange-badge-hover-bg) !important; +} + +.repository.view.issue .comment-list .timeline-item.event > .commit-status-link { + float: right; + margin-right: 8px; + margin-top: 4px; +} + +.repository.view.issue .comment-list .timeline-item .comparebox { + line-height: 32px; + vertical-align: middle; +} + +.repository.view.issue .comment-list .timeline-item .comparebox .compare.label { + font-size: 1rem; + margin: 0; + border: 1px solid var(--color-light-border); +} + +@media (max-width: 767px) { + .repository.view.issue .comment-list .timeline-item .ui.segments { + margin-left: -2rem; + } +} + +.repository.view.issue .comment-list .ui.comments { + max-width: 100%; +} + +.repository.view.issue .comment-list .ui.comments .avatar { + margin-right: 0.5rem; +} + +.repository.view.issue .comment-list .comment > .content > div:first-child { + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} + +.repository.view.issue .comment-list .comment > .content > div:last-child { + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; +} + +.repository.view.issue .comment-list .comment .comment-container { + border: 1px solid var(--color-secondary); + border-radius: var(--border-radius); +} + +@media (max-width: 767px) { + .repository.view.issue .comment-list .comment .content .form .button { + width: 100%; + margin: 0; + } + .repository.view.issue .comment-list .comment .content .form .button:not(:last-child) { + margin-bottom: 1rem; + } +} + +.repository.view.issue .comment-list .comment .merge-section { + background-color: var(--color-box-body); +} + +.repository.view.issue .comment-list .comment .merge-section .item-section { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0; + margin-top: -0.25rem; + margin-bottom: -0.25rem; +} + +@media (max-width: 767px) { + .repository.view.issue .comment-list .comment .merge-section .item-section { + align-items: flex-start; + flex-direction: column; + } +} + +.repository.view.issue .comment-list .comment .merge-section .divider { + margin-left: -1rem; + margin-right: -1rem; +} + +.repository.view.issue .comment-list .comment .merge-section.no-header::before, +.repository.view.issue .comment-list .comment .merge-section.no-header::after { + right: 100%; + top: 20px; + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; +} + +.repository.view.issue .comment-list .comment .merge-section.no-header::before { + border-right-color: var(--color-secondary); + border-width: 9px; + margin-top: -9px; +} + +.repository.view.issue .comment-list .comment .merge-section.no-header::after { + border-right-color: var(--color-box-body); + border-width: 8px; + margin-top: -8px; +} + +.repository.view.issue .comment-list .comment .markup { + font-size: 14px; +} + +.repository.view.issue .comment-list .comment .no-content { + color: var(--color-text-light-2); + font-style: italic; +} + +.repository.view.issue .comment-list .comment .ui.form .field:first-child { + clear: none; +} + +.repository.view.issue .comment-list .comment .ui.form .field.footer { + overflow: hidden; +} + +.repository.view.issue .comment-list .comment .ui.form .field .tab.markup { + min-height: 5rem; +} + +.repository.view.issue .comment-list .comment .ui.form textarea { + height: 200px; + font-family: var(--fonts-monospace); +} + +.repository.view.issue .comment-list .comment .edit.buttons { + margin-top: 10px; +} + +.repository.view.issue .comment-list .code-comment { + border: 1px solid transparent; + padding: 0.25rem 0.5rem; + margin: 0; +} + +.repository.view.issue .comment-list .code-comment .content { + border: none !important; +} + +.repository.view.issue .comment-list .code-comment .comment-header { + background: transparent; + border-bottom: 0 !important; + padding: 0 !important; +} + +.repository.view.issue .comment-list .code-comment .comment-header::after, +.repository.view.issue .comment-list .code-comment .comment-header::before { + display: none; +} + +.repository.view.issue .comment-list .code-comment .comment-content { + margin-left: 36px; +} + +.repository.view.issue .comment-list .code-comment img.avatar, +.repository.view.issue .comment-list .comment img.avatar { + width: 28px; + height: 28px; +} + +.repository.view.issue .comment-list .comment-code-cloud .segment.reactions { + margin-top: 16px !important; + margin-bottom: -8px !important; + border-top: none !important; +} + +.repository.view.issue .comment-list .comment-code-cloud .segment.reactions .ui.label { + border: 1px solid; + padding: 6px 10px !important; + margin: 0 2px; + border-radius: var(--border-radius); + border-color: var(--color-secondary-dark-1) !important; +} + +.repository.view.issue .comment-list .comment-code-cloud .segment.reactions .ui.label.basic.primary { + background-color: var(--color-reaction-active-bg) !important; + border-color: var(--color-primary-alpha-80) !important; +} + +.repository.view.issue .comment-list .comment-code-cloud button.comment-form-reply { + margin: 0; +} + +.repository.view.issue .comment-list .event { + padding-left: 15px; +} + +.repository.view.issue .comment-list .event .detail { + margin-top: 4px; + margin-left: 14px; +} + +.repository.view.issue .comment-list .event .detail .svg { + margin-right: 2px; +} + +.repository.view.issue .comment-list .event .segments { + box-shadow: none; +} + +@media (max-width: 767px) { + .repository.view.issue .comment-list { + padding: 1rem 0 !important; /* Important is required here to override existing fomantic styles. */ + } +} + +.repository.view.issue .ui.depending .item.is-closed .title { + text-decoration: line-through; +} + +.repository .comment.form .ui.comments { + margin-top: -12px; + max-width: 100%; +} + +.repository .comment.form .content .field:first-child { + clear: none; +} + +.repository .comment.form .content .form::before, +.repository .comment.form .content .form::after { + right: 100%; + top: 20px; + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; +} + +.repository .comment.form .content .form::before { + border-right-color: var(--color-secondary); + border-width: 9px; + margin-top: -9px; +} + +.repository .comment.form .content .form::after { + border-right-color: var(--color-box-body); + border-width: 8px; + margin-top: -8px; +} + +.repository .comment.form .content textarea { + height: 200px; + font-family: var(--fonts-monospace); +} + +.repository .comment.form .content .CodeMirror-scroll { + max-height: 85vh; +} + +.repository .milestone.list { + list-style: none; + padding-top: 15px; +} + +.repository .milestone.list > .item { + padding-top: 10px; + padding-bottom: 10px; + border-bottom: 1px dashed var(--color-secondary); +} + +.repository .milestone.list > .item progress { + width: 200px; + height: 16px; +} + +.repository .milestone.list > .item .meta { + color: var(--color-text-light-2); + padding-top: 5px; +} + +.repository .milestone.list > .item .meta .issue-stats .svg { + padding-left: 5px; +} + +.repository .milestone.list > .item .meta .overdue { + color: var(--color-red); +} + +.repository .milestone.list > .item .operate { + margin-top: -15px; +} + +.repository .milestone.list > .item .operate > a { + font-size: 15px; + padding-top: 5px; + padding-right: 10px; + color: var(--color-text-light-2); +} + +.repository .milestone.list > .item .operate > a:hover { + color: var(--color-text); +} + +.repository .milestone.list > .item .content { + padding-top: 10px; +} + +.repository.new.milestone textarea { + height: 200px; +} + +.repository.compare.pull .show-form-container { + text-align: left; +} + +.repository.compare.pull .choose.branch .svg { + margin-right: 10px; +} + +.repository.compare.pull .comment.form .content::before, +.repository.compare.pull .comment.form .content::after { + right: 100%; + top: 20px; + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; +} + +.repository.compare.pull .comment.form .content::before { + border-right-color: var(--color-secondary); + border-width: 9px; + margin-top: -9px; +} + +.repository.compare.pull .comment.form .content::after { + border-right-color: var(--color-box-body); + border-width: 8px; + margin-top: -8px; +} + +.repository.compare.pull .pullrequest-form { + margin-bottom: 1.5rem; +} + +.repository.compare.pull .markup { + font-size: 14px; +} + +.repository.compare.pull .title .issue-title { + margin-bottom: 0.5rem; +} + +.repository.compare.pull .title .issue-title .index { + color: var(--color-text-light-2); +} + +.repository .filter.dropdown .menu { + margin-top: 1px !important; +} + +.repository.branches .commit-divergence .bar-group { + position: relative; + float: left; + padding-bottom: 6px; + width: 50%; + max-width: 90px; +} + +.repository.branches .commit-divergence .bar-group:last-child { + border-left: 1px solid var(--color-secondary-dark-2); +} + +.repository.branches .commit-divergence .count { + margin: 0 3px; +} + +.repository.branches .commit-divergence .count.count-ahead { + text-align: left; +} + +.repository.branches .commit-divergence .count.count-behind { + text-align: right; +} + +.repository.branches .commit-divergence .bar { + height: 4px; + position: absolute; + background-color: var(--color-secondary-dark-2); +} + +.repository.branches .commit-divergence .bar.bar-behind { + right: 0; +} + +.repository.branches .commit-divergence .bar.bar-ahead { + left: 0; +} + +.repository.commits .header .search input { + font-weight: normal; + padding: 5px 10px; +} + +.repository #commits-table thead th:first-of-type { + padding-left: 15px; +} + +.repository #commits-table thead .sha { + width: 200px; +} + +.repository #commits-table thead .shatd { + text-align: center; +} + +.repository #commits-table td.sha .sha.label { + margin: 0; +} + +.repository #commits-table td.message { + text-overflow: unset; +} + +.repository #commits-table.ui.basic.striped.table tbody tr:nth-child(2n) { + background-color: rgba(0, 0, 0, 0.02) !important; +} + +.repository #commits-table td.sha .sha.label, +.repository #repo-files-table .sha.label, +.repository #rev-list .sha.label, +.repository .timeline-item.commits-list .singular-commit .sha.label { + border: 1px solid var(--color-light-border); +} + +.repository #commits-table td.sha .sha.label .ui.signature.avatar, +.repository #repo-files-table .sha.label .ui.signature.avatar, +.repository #rev-list .sha.label .ui.signature.avatar, +.repository .timeline-item.commits-list .singular-commit .sha.label .ui.signature.avatar { + height: 16px; + margin-bottom: 0; + width: 16px; +} + +.repository #commits-table td.sha .sha.label .detail.icon, +.repository #repo-files-table .sha.label .detail.icon, +.repository #rev-list .sha.label .detail.icon, +.repository .timeline-item.commits-list .singular-commit .sha.label .detail.icon { + background: var(--color-light); + margin: -6px -10px -4px 0; + padding: 5px 4px 5px 6px; + border-left: 1px solid var(--color-light-border); + border-top: 0; + border-right: 0; + border-bottom: 0; + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.repository #commits-table td.sha .sha.label .detail.icon img, +.repository #repo-files-table .sha.label .detail.icon img, +.repository #rev-list .sha.label .detail.icon img, +.repository .timeline-item.commits-list .singular-commit .sha.label .detail.icon img { + margin-right: 0; +} + +.repository #commits-table td.sha .sha.label .detail.icon .svg, +.repository #repo-files-table .sha.label .detail.icon .svg, +.repository #rev-list .sha.label .detail.icon .svg, +.repository .timeline-item.commits-list .singular-commit .sha.label .detail.icon .svg { + margin: 0 0.25em 0 0; +} + +.repository #commits-table td.sha .sha.label .detail.icon > div, +.repository #repo-files-table .sha.label .detail.icon > div, +.repository #rev-list .sha.label .detail.icon > div, +.repository .timeline-item.commits-list .singular-commit .sha.label .detail.icon > div { + display: flex; + align-items: center; +} + +.repository #commits-table td.sha .sha.label.isSigned.isWarning, +.repository #repo-files-table .sha.label.isSigned.isWarning, +.repository #rev-list .sha.label.isSigned.isWarning, +.repository .timeline-item.commits-list .singular-commit .sha.label.isSigned.isWarning { + border: 1px solid var(--color-red-badge); + background: var(--color-red-badge-bg); +} + +.repository #commits-table td.sha .sha.label.isSigned.isWarning .shortsha, +.repository #repo-files-table .sha.label.isSigned.isWarning .shortsha, +.repository #rev-list .sha.label.isSigned.isWarning .shortsha, +.repository .timeline-item.commits-list .singular-commit .sha.label.isSigned.isWarning .shortsha { + display: inline-block; + padding-top: 1px; +} + +.repository #commits-table td.sha .sha.label.isSigned.isWarning .detail.icon, +.repository #repo-files-table .sha.label.isSigned.isWarning .detail.icon, +.repository #rev-list .sha.label.isSigned.isWarning .detail.icon, +.repository .timeline-item.commits-list .singular-commit .sha.label.isSigned.isWarning .detail.icon { + border-left: 1px solid var(--color-red-badge); + color: var(--color-red-badge); +} + +.repository #commits-table td.sha .sha.label.isSigned.isWarning:hover, +.repository #repo-files-table .sha.label.isSigned.isWarning:hover, +.repository #rev-list .sha.label.isSigned.isWarning:hover, +.repository .timeline-item.commits-list .singular-commit .sha.label.isSigned.isWarning:hover { + background: var(--color-red-badge-hover-bg) !important; +} + +.repository #commits-table td.sha .sha.label.isSigned.isVerified, +.repository #repo-files-table .sha.label.isSigned.isVerified, +.repository #rev-list .sha.label.isSigned.isVerified, +.repository .timeline-item.commits-list .singular-commit .sha.label.isSigned.isVerified { + border: 1px solid var(--color-green-badge); + background: var(--color-green-badge-bg); +} + +.repository #commits-table td.sha .sha.label.isSigned.isVerified .shortsha, +.repository #repo-files-table .sha.label.isSigned.isVerified .shortsha, +.repository #rev-list .sha.label.isSigned.isVerified .shortsha, +.repository .timeline-item.commits-list .singular-commit .sha.label.isSigned.isVerified .shortsha { + display: inline-block; + padding-top: 1px; +} + +.repository #commits-table td.sha .sha.label.isSigned.isVerified .detail.icon, +.repository #repo-files-table .sha.label.isSigned.isVerified .detail.icon, +.repository #rev-list .sha.label.isSigned.isVerified .detail.icon, +.repository .timeline-item.commits-list .singular-commit .sha.label.isSigned.isVerified .detail.icon { + border-left: 1px solid var(--color-green-badge); + color: var(--color-green-badge); +} + +.repository #commits-table td.sha .sha.label.isSigned.isVerified:hover, +.repository #repo-files-table .sha.label.isSigned.isVerified:hover, +.repository #rev-list .sha.label.isSigned.isVerified:hover, +.repository .timeline-item.commits-list .singular-commit .sha.label.isSigned.isVerified:hover { + background: var(--color-green-badge-hover-bg) !important; +} + +.repository #commits-table td.sha .sha.label.isSigned.isVerifiedUntrusted, +.repository #repo-files-table .sha.label.isSigned.isVerifiedUntrusted, +.repository #rev-list .sha.label.isSigned.isVerifiedUntrusted, +.repository .timeline-item.commits-list .singular-commit .sha.label.isSigned.isVerifiedUntrusted { + border: 1px solid var(--color-yellow-badge); + background: var(--color-yellow-badge-bg); +} + +.repository #commits-table td.sha .sha.label.isSigned.isVerifiedUntrusted .shortsha, +.repository #repo-files-table .sha.label.isSigned.isVerifiedUntrusted .shortsha, +.repository #rev-list .sha.label.isSigned.isVerifiedUntrusted .shortsha, +.repository .timeline-item.commits-list .singular-commit .sha.label.isSigned.isVerifiedUntrusted .shortsha { + display: inline-block; + padding-top: 1px; +} + +.repository #commits-table td.sha .sha.label.isSigned.isVerifiedUntrusted .detail.icon, +.repository #repo-files-table .sha.label.isSigned.isVerifiedUntrusted .detail.icon, +.repository #rev-list .sha.label.isSigned.isVerifiedUntrusted .detail.icon, +.repository .timeline-item.commits-list .singular-commit .sha.label.isSigned.isVerifiedUntrusted .detail.icon { + border-left: 1px solid var(--color-yellow-badge); + color: var(--color-yellow-badge); +} + +.repository #commits-table td.sha .sha.label.isSigned.isVerifiedUntrusted:hover, +.repository #repo-files-table .sha.label.isSigned.isVerifiedUntrusted:hover, +.repository #rev-list .sha.label.isSigned.isVerifiedUntrusted:hover, +.repository .timeline-item.commits-list .singular-commit .sha.label.isSigned.isVerifiedUntrusted:hover { + background: var(--color-yellow-badge-hover-bg) !important; +} + +.repository #commits-table td.sha .sha.label.isSigned.isVerifiedUnmatched, +.repository #repo-files-table .sha.label.isSigned.isVerifiedUnmatched, +.repository #rev-list .sha.label.isSigned.isVerifiedUnmatched, +.repository .timeline-item.commits-list .singular-commit .sha.label.isSigned.isVerifiedUnmatched { + border: 1px solid var(--color-orange-badge); + background: var(--color-orange-badge-bg); +} + +.repository #commits-table td.sha .sha.label.isSigned.isVerifiedUnmatched .shortsha, +.repository #repo-files-table .sha.label.isSigned.isVerifiedUnmatched .shortsha, +.repository #rev-list .sha.label.isSigned.isVerifiedUnmatched .shortsha, +.repository .timeline-item.commits-list .singular-commit .sha.label.isSigned.isVerifiedUnmatched .shortsha { + display: inline-block; + padding-top: 1px; +} + +.repository #commits-table td.sha .sha.label.isSigned.isVerifiedUnmatched .detail.icon, +.repository #repo-files-table .sha.label.isSigned.isVerifiedUnmatched .detail.icon, +.repository #rev-list .sha.label.isSigned.isVerifiedUnmatched .detail.icon, +.repository .timeline-item.commits-list .singular-commit .sha.label.isSigned.isVerifiedUnmatched .detail.icon { + border-left: 1px solid var(--color-orange-badge); + color: var(--color-orange-badge); +} + +.repository #commits-table td.sha .sha.label.isSigned.isVerifiedUnmatched:hover, +.repository #repo-files-table .sha.label.isSigned.isVerifiedUnmatched:hover, +.repository #rev-list .sha.label.isSigned.isVerifiedUnmatched:hover, +.repository .timeline-item.commits-list .singular-commit .sha.label.isSigned.isVerifiedUnmatched:hover { + background: var(--color-orange-badge-hover-bg) !important; +} + +.repository .data-table { + width: 100%; +} + +.repository .data-table tr { + border-top: 0; +} + +.repository .data-table td, +.repository .data-table th { + padding: 5px !important; + overflow: hidden; + font-size: 12px; + text-align: left; + white-space: nowrap; + border: 1px solid var(--color-secondary); +} + +.repository .data-table td { + white-space: pre-line; +} + +.repository .data-table th { + font-weight: 600; + background: var(--color-box-header); + border-top: 0; +} + +.repository .data-table td.added, +.repository .data-table th.added, +.repository .data-table tr.added { + background-color: var(--color-diff-added-row-bg) !important; +} + +.repository .data-table td.removed, +.repository .data-table th.removed, +.repository .data-table tr.removed { + background-color: var(--color-diff-removed-row-bg) !important; +} + +.repository .data-table td.moved, +.repository .data-table th.moved, +.repository .data-table tr.moved { + background-color: var(--color-diff-moved-row-bg) !important; +} + +.repository .data-table tbody.section { + border-top: 2px solid var(--color-secondary); +} + +.repository .data-table .line-num { + width: 1%; + min-width: 50px; + font-family: monospace; + line-height: 20px; + color: var(--color-secondary-dark-2); + white-space: nowrap; + vertical-align: top; + cursor: pointer; + text-align: right; + background: var(--color-body); + border: 0; +} + +.repository .diff-detail-box { + padding: 7px 0; + background: var(--color-body); + line-height: 30px; +} + +@media (max-width: 991px) { + .repository .diff-detail-box { + flex-direction: column; + align-items: flex-start; + } +} + +@media (max-width: 480px) { + .repository .diff-detail-box { + flex-wrap: wrap; + } +} + +.repository .diff-detail-box.sticky { + position: sticky; + top: 0; + z-index: 8; + border-bottom: 1px solid var(--color-secondary); + padding-left: 2px; + padding-right: 2px; + margin-left: -1px; + margin-right: -1px; +} + +.repository .diff-detail-box > div::after { + clear: both; + content: ""; + display: block; +} + +.repository .diff-detail-box .diff-detail-stats strong { + margin-left: 0.25rem; + margin-right: 0.25rem; +} + +/* Because the translations contain the we need to style with nth-of-type */ + +.repository .diff-detail-box .diff-detail-stats strong:nth-of-type(1) { + color: var(--color-yellow); +} + +.repository .diff-detail-box .diff-detail-stats strong:nth-of-type(2) { + color: var(--color-green); +} + +.repository .diff-detail-box .diff-detail-stats strong:nth-of-type(3) { + color: var(--color-red); +} + +@media (max-width: 480px) { + .repository .diff-detail-box .diff-detail-stats { + font-size: 0; + line-height: 1.6rem; + } + .repository .diff-detail-box .diff-detail-stats strong { + font-size: 1rem; + } +} + +.repository .diff-detail-box .diff-detail-actions > * { + margin-right: 0; +} + +.repository .diff-detail-box .diff-detail-actions > * + * { + margin-left: 0.25rem; +} + +@media (max-width: 480px) { + .repository .diff-detail-box .diff-detail-actions { + padding-top: 0.25rem; + } + .repository .diff-detail-box .diff-detail-actions .ui.button:not(.btn-submit) { + padding-left: 0.5rem; + padding-right: 0.5rem; + display: flex; + flex-wrap: wrap; + justify-content: center; + text-align: center; + } +} + +.repository .diff-detail-box span.status { + display: inline-block; + width: 12px; + height: 12px; + margin-right: 8px; + vertical-align: middle; +} + +.repository .diff-detail-box span.status.modify { + background-color: var(--color-yellow); +} + +.repository .diff-detail-box span.status.add { + background-color: var(--color-green); +} + +.repository .diff-detail-box span.status.del { + background-color: var(--color-red); +} + +.repository .diff-detail-box span.status.rename { + background-color: var(--color-teal); +} + +.repository .diff-detail-box .button { + padding: 8px 12px; +} + +.repository .diff-box .header:not(.resolved-placeholder) { + display: flex; + align-items: center; +} + +.repository .diff-box .header:not(.resolved-placeholder) .file { + min-width: 0; +} + +.repository .diff-box .header:not(.resolved-placeholder) .file .file-link { + max-width: fit-content; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + overflow: hidden; +} + +.repository .diff-box .header:not(.resolved-placeholder) .button { + padding: 8px 12px; + flex: 0 0 auto; + margin-top: -8px; + margin-bottom: -8px; + margin-right: 0; +} + +.repository .diff-box .resolved-placeholder { + display: flex; + align-items: center; +} + +.repository .diff-box .resolved-placeholder .button { + padding: 8px 12px; +} + +.repository .diff-file-box .header { + background-color: var(--color-box-header); +} + +.repository .diff-file-box .file-body.file-code { + background: var(--color-code-bg); +} + +.repository .diff-file-box .file-body.file-code .lines-num { + text-align: right; + color: var(--color-text-light); + width: 1%; + min-width: 50px; +} + +.repository .diff-file-box .file-body.file-code .lines-num span.fold { + display: block; + text-align: center; +} + +.repository .diff-file-box .code-diff { + font-size: 12px; +} + +.repository .diff-file-box .code-diff td { + padding: 0 0 0 10px !important; + border-top: 0; +} + +.repository .diff-file-box .code-diff .lines-num { + padding: 0 5px !important; +} + +.repository .diff-file-box .code-diff .tag-code .lines-num, +.repository .diff-file-box .code-diff .tag-code td { + padding: 0 !important; +} + +.repository .diff-file-box .code-diff tbody tr td.halfwidth { + width: 49%; /* halfwidth is used in split view - and in that case, 1% of each */ +} + +.repository .diff-file-box .code-diff tbody tr td.center { + text-align: center; +} + +.repository .diff-file-box .code-diff tbody tr [data-line-num]::before { + content: attr(data-line-num); + text-align: right; +} + +.repository .diff-file-box .code-diff tbody tr .lines-type-marker { + width: 10px; + min-width: 10px; +} + +.repository .diff-file-box .code-diff tbody tr [data-type-marker]::before { + content: attr(data-type-marker); + text-align: right; + display: inline-block; +} + +.repository .diff-file-box .code-diff-split .tag-code .lines-code code.code-inner { + padding-left: 10px !important; +} + +.repository .diff-file-box .code-diff-split table, +.repository .diff-file-box .code-diff-split tbody { + width: 100%; +} + +.repository .diff-file-box.file-content { + clear: right; +} + +.repository .diff-file-box.file-content img { + max-width: 100%; + padding: 0; + border-radius: 0; +} + +.repository .diff-file-box.file-content img.emoji { + padding: 0; +} + +.repository .diff-file-box .ui.bottom.attached.table.segment { + padding-top: 5px; + padding-bottom: 5px; +} + +.repository .diff-stats { + clear: both; + margin-bottom: 5px; + max-height: 400px; + overflow: auto; + padding-left: 0; +} + +.repository .diff-stats li { + list-style: none; + padding-bottom: 4px; + margin-bottom: 4px; + padding-left: 6px; +} + +.repository .diff-stats li + li { + border-top: 1px solid var(--color-secondary); +} + +.repository .repo-search-result { + padding-top: 10px; + padding-bottom: 10px; +} + +.repository .repo-search-result .lines-num a { + color: inherit; +} + +.repository.quickstart .guide .item { + padding: 1em; +} + +.repository.quickstart .guide .item small { + font-weight: normal; +} + +.repository.quickstart .guide .clone.button:first-child { + border-radius: var(--border-radius) 0 0 var(--border-radius); +} + +.repository.quickstart .guide .ui.action.small.input { + width: 100%; +} + +.repository.quickstart .guide #repo-clone-url { + border-radius: 0; + padding: 5px 10px; + font-size: 1.2em; + line-height: 1.4; +} + +.repository.release #release-list { + border-top: 1px solid var(--color-secondary); + margin-top: 20px; + padding-top: 15px; + padding-left: 0; +} + +.repository.release #release-list .release-list-title { + font-size: 2rem; + font-weight: normal; + margin-top: -4px; + margin-bottom: 0; +} + +.repository.release #release-list > li { + list-style: none; +} + +.repository.release #release-list > li .meta, +.repository.release #release-list > li .detail { + padding-top: 30px; + padding-bottom: 40px; +} + +.repository.release #release-list > li .meta { + text-align: right; + position: relative; +} + +.repository.release #release-list > li .meta .label { + margin-right: 0; +} + +.repository.release #release-list > li .meta .commit { + display: block; + margin-top: 10px; +} + +.repository.release #release-list > li .meta .choose { + margin-top: 15px; +} + +.repository.release #release-list > li .meta .choose .button { + margin-right: 0; +} + +.repository.release #release-list > li .detail { + border-left: 2px solid var(--color-secondary); +} + +.repository.release #release-list > li .detail .author img { + margin-bottom: 3px; +} + +.repository.release #release-list > li .detail .download > a .svg { + margin-left: 5px; + margin-right: 5px; +} + +.repository.release #release-list > li .detail .download .list { + padding-left: 0; +} + +.repository.release #release-list > li .detail .download .list li { + list-style: none; + display: block; + padding: 8px; + border: 1px solid var(--color-secondary); + background: var(--color-light); +} + +.repository.release #release-list > li .detail .download .list li a > .text.right { + margin-right: 5px; +} + +.repository.release #release-list > li .detail .download .list li + li { + border-top: 0; +} + +.repository.release #release-list > li .detail .download .list li:first-of-type { + border-radius: var(--border-radius) 0 0 var(--border-radius); +} + +.repository.release #release-list > li .detail .download .list li:last-of-type { + border-radius: 0 var(--border-radius) var(--border-radius) 0; +} + +.repository.release #release-list > li .detail .dot { + width: 10px; + height: 10px; + background-color: var(--color-secondary-dark-3); + z-index: 9; + position: absolute; + display: block; + left: -6px; + top: 40px; + border-radius: 100%; + border: 2.5px solid var(--color-body); +} + +.repository.release #tags-table .tag { + padding: 8px 12px; +} + +.repository.release #tags-table .release-tag-name { + font-size: 18px; + font-weight: normal; +} + +.repository.new.release .target { + min-width: 500px; +} + +.repository.new.release .target #tag-name { + margin-top: -4px; +} + +.repository.new.release .target .at { + margin-left: -5px; + margin-right: 5px; +} + +.repository.new.release .target .selection.dropdown { + padding-top: 10px; + padding-bottom: 10px; +} + +.repository.new.release .prerelease.field { + margin-bottom: 0; +} + +@media (max-width: 438px) { + .repository.new.release .field button, + .repository.new.release .field input { + width: 100%; + } +} + +@media (max-width: 767px) { + .repository.new.release .field button { + margin-bottom: 1em; + } +} + +.repository.new.release .field .wrap_remove { + height: 38px; +} + +.repository.new.release .field .attachment_edit { + width: 450px !important; +} + +.repository.forks .list { + margin-top: 0; +} + +.repository.forks .list .item { + padding-top: 10px; + padding-bottom: 10px; + border-bottom: 1px solid var(--color-secondary); +} + +.repository.forks .list .item .ui.avatar { + float: left; + margin-right: 5px; +} + +.repository.forks .list .item .link { + padding-top: 5px; +} + +.repository.packages .empty { + padding-top: 70px; + padding-bottom: 100px; +} + +.repository.packages .empty .svg { + height: 48px; +} + +.repository.packages .file-size { + white-space: nowrap; +} + +.repository.wiki.start .ui.segment { + padding-top: 70px; + padding-bottom: 100px; +} + +.repository.wiki.start .ui.segment .svg { + height: 48px; +} + +.repository.wiki.new .ui.attached.tabular.menu.previewtabs { + margin-bottom: 15px; +} + +.repository.wiki.view > .markup { + padding: 15px 30px; +} + +.repository.wiki.view > .markup h1:first-of-type, +.repository.wiki.view > .markup h2:first-of-type, +.repository.wiki.view > .markup h3:first-of-type, +.repository.wiki.view > .markup h4:first-of-type, +.repository.wiki.view > .markup h5:first-of-type, +.repository.wiki.view > .markup h6:first-of-type { + margin-top: 0; +} + +.repository.wiki .form .CodeMirror-scroll { + max-height: 85vh; +} + +@media (max-width: 767px) { + .repository.wiki .dividing.header .stackable.grid .button { + margin-top: 2px; + margin-bottom: 2px; + } +} + +@media (max-width: 767px) { + .repository.wiki #clone-panel #repo-clone-url { + width: 160px; + } +} + +.repository.settings.collaboration .collaborator.list { + padding: 0; +} + +.repository.settings.collaboration .collaborator.list > .item { + margin: 0; + line-height: 2em; +} + +.repository.settings.collaboration .collaborator.list > .item:not(:last-child) { + border-bottom: 1px solid var(--color-secondary); +} + +.repository.settings.collaboration #repo-collab-form #search-user-box .results { + left: 7px; +} + +.repository.settings.collaboration #repo-collab-form .ui.button { + margin-left: 5px; + margin-top: -3px; +} + +.repository.settings.collaboration #repo-collab-team-form #search-team-box .results { + left: 7px; +} + +.repository.settings.collaboration #repo-collab-team-form .ui.button { + margin-left: 5px; + margin-top: -3px; +} + +.repository.settings.branches .protected-branches .selection.dropdown { + width: 300px; +} + +.repository.settings.branches .protected-branches .item { + border: 1px solid var(--color-secondary); + padding: 10px 15px; +} + +.repository.settings.branches .protected-branches .item:not(:last-child) { + border-bottom: 0; +} + +.repository.settings.branches .branch-protection .help { + margin-left: 26px; + padding-top: 0; +} + +.repository.settings.branches .branch-protection .fields { + margin-left: 20px; + display: block; +} + +.repository.settings.branches .branch-protection .whitelist { + margin-left: 26px; +} + +.repository.settings.branches .branch-protection .whitelist .dropdown img { + display: inline-block; +} + +.repository.settings.webhook .events .column { + padding-bottom: 0; +} + +.repository.settings.webhook .events .help { + font-size: 13px; + margin-left: 26px; + padding-top: 0; +} + +.repository .ui.attached.isSigned.isWarning { + border-left: 1px solid var(--color-error-border); + border-right: 1px solid var(--color-error-border); +} + +.repository .ui.attached.isSigned.isWarning.top, +.repository .ui.attached.isSigned.isWarning.message { + border-top: 1px solid var(--color-error-border); +} + +.repository .ui.attached.isSigned.isWarning.message { + box-shadow: none; + background-color: var(--color-error-bg); + color: var(--color-error-text); +} + +.repository .ui.attached.isSigned.isWarning.message .ui.text { + color: var(--color-error-text); +} + +.repository .ui.attached.isSigned.isWarning:last-child, +.repository .ui.attached.isSigned.isWarning.bottom { + border-bottom: 1px solid var(--color-error-border); +} + +.repository .ui.attached.isSigned.isVerified { + border-left: 1px solid var(--color-success-border); + border-right: 1px solid var(--color-success-border); +} + +.repository .ui.attached.isSigned.isVerified.top, +.repository .ui.attached.isSigned.isVerified.message { + border-top: 1px solid var(--color-success-border); +} + +.repository .ui.attached.isSigned.isVerified.message { + box-shadow: none; + background-color: var(--color-success-bg); + color: var(--color-success-text); +} + +.repository .ui.attached.isSigned.isVerified.message .pull-right { + color: var(--color-text); +} + +.repository .ui.attached.isSigned.isVerified.message .ui.text { + color: var(--color-success-text); +} + +.repository .ui.attached.isSigned.isVerified:last-child, +.repository .ui.attached.isSigned.isVerified.bottom { + border-bottom: 1px solid var(--color-success-border); +} + +.repository .ui.attached.isSigned.isVerifiedUntrusted, +.repository .ui.attached.isSigned.isVerifiedUnmatched { + border-left: 1px solid var(--color-warning-border); + border-right: 1px solid var(--color-warning-border); +} + +.repository .ui.attached.isSigned.isVerifiedUntrusted.top, +.repository .ui.attached.isSigned.isVerifiedUnmatched.top, +.repository .ui.attached.isSigned.isVerifiedUntrusted.message, +.repository .ui.attached.isSigned.isVerifiedUnmatched.message { + border-top: 1px solid var(--color-warning-border); +} + +.repository .ui.attached.isSigned.isVerifiedUntrusted.message, +.repository .ui.attached.isSigned.isVerifiedUnmatched.message { + box-shadow: none; + background-color: var(--color-warning-bg); + color: var(--color-warning-text); +} + +.repository .ui.attached.isSigned.isVerifiedUntrusted.message .ui.text, +.repository .ui.attached.isSigned.isVerifiedUnmatched.message .ui.text { + color: var(--color-warning-text); +} + +.repository .ui.attached.isSigned.isVerifiedUntrusted:last-child, +.repository .ui.attached.isSigned.isVerifiedUnmatched:last-child, +.repository .ui.attached.isSigned.isVerifiedUntrusted.bottom, +.repository .ui.attached.isSigned.isVerifiedUnmatched.bottom { + border-bottom: 1px solid var(--color-warning-border); +} + +.repository .ui.segment.sub-menu { + padding: 7px; + line-height: 0; +} + +.repository .ui.segment.sub-menu .list { + width: 100%; + display: flex; + align-items: center; +} + +.repository .ui.segment.sub-menu .list .item { + width: 100%; + color: var(--color-text); +} + +.repository .ui.segment.sub-menu .list .item:first-of-type { + border-radius: var(--border-radius) 0 0 var(--border-radius); + padding-left: 0.25rem; +} + +.repository .ui.segment.sub-menu .list .item:last-of-type { + border-radius: 0 var(--border-radius) var(--border-radius) 0; + padding-right: 0.25rem; +} + +.repository .ui.segment.sub-menu .list .item a { + color: var(--color-text); +} + +.repository .ui.segment.sub-menu .list .item a:hover { + color: var(--color-primary-light-2); +} + +.repository .ui.segment.sub-menu .list .item.active { + background: var(--color-secondary); +} + +.repository .segment.reactions.dropdown .menu, +.repository .select-reaction.dropdown .menu { + right: 0 !important; + left: auto !important; + min-width: 15em; +} + +.repository .segment.reactions.dropdown .menu > .header, +.repository .select-reaction.dropdown .menu > .header { + margin: 0.75rem 0 0.5rem; +} + +.repository .segment.reactions.dropdown .menu > .item, +.repository .select-reaction.dropdown .menu > .item { + float: left; + padding: 0.25rem !important; + margin: 0.25rem; + font-size: 1.5em; + width: 39px; + left: 13px; + border-radius: 6px; + display: flex; + justify-content: center; + align-items: center; +} + +.repository .segment.reactions.dropdown .menu > .item img.emoji, +.repository .select-reaction.dropdown .menu > .item img.emoji { + margin-right: 0; +} + +.repository .segment.reactions.dropdown .menu > .item:hover, +.repository .select-reaction.dropdown .menu > .item:hover { + background: var(--color-primary); +} + +.repository .segment.reactions { + padding: 0; + display: flex; + border: none !important; + border-top: 1px solid var(--color-secondary) !important; + width: 100% !important; + max-width: 100% !important; + margin: 0 !important; +} + +.repository .segment.reactions .ui.label { + max-height: 40px; + padding: 10px 18px !important; + display: flex !important; + align-items: center; + border: 0; + border-right: 1px solid; + border-radius: 0; + margin: 0; + font-size: 14px; + font-weight: normal; + border-color: var(--color-secondary) !important; + background: var(--color-reaction-bg); +} + +.repository .segment.reactions .ui.label.disabled { + cursor: default; + opacity: 1; +} + +.repository .segment.reactions .ui.label.basic { + color: var(--color-primary) !important; +} + +.repository .segment.reactions .ui.label.basic.primary { + background-color: var(--color-reaction-active-bg) !important; + border-color: var(--color-secondary) !important; +} + +.repository .segment.reactions .reaction-count { + margin-left: 0.5rem; +} + +.repository .segment.reactions .select-reaction { + display: flex; + align-items: center; + padding: 0 14px; +} + +.repository .segment.reactions .select-reaction:not(.active) a { + display: none; +} + +.repository .segment.reactions:hover .select-reaction a { + display: block; +} + +.repository .ui.fluid.action.input .ui.search.action.input { + flex: auto; +} + +.repository .repository-summary { + box-shadow: none !important; +} + +.repository .repository-summary .segment.language-stats-details, +.repository .repository-summary .segment.repository-summary { + border-top: none; + background: none; +} + +.repository .repository-summary .segment.language-stats-details .item { + white-space: nowrap; +} + +.repository .repository-summary .segment.language-stats { + padding: 0; + height: 11px; + display: flex; + white-space: nowrap; + width: 100%; + border-radius: 0; +} + +@media (max-width: 767px) { + .repository .repository-summary .segment.language-stats { + display: none; + } +} + +.repository .repository-summary .segment.language-stats .bar { + white-space: nowrap; + border: 0; + padding: 0; + margin: 0; + height: 100%; +} + +.repository .repository-menu { + padding: 0 !important; +} + +.repository .repository-menu .item { + padding-top: 9px !important; + padding-bottom: 9px !important; +} + +#cite-repo-modal #citation-panel { + width: 500px; +} + +@media (max-width: 767px) { + #cite-repo-modal #citation-panel { + width: 100%; + } +} + +#cite-repo-modal #citation-panel input { + border-radius: 0; + padding: 5px 10px; + width: 50%; + line-height: 1.4; +} + +#cite-repo-modal #citation-panel .citation.button { + font-size: 13px; + padding: 7.5px 5px; +} + +#cite-repo-modal #citation-panel #citation-copy-content { + border-radius: 0; + padding: 5px 10px; + font-size: 1.2em; + line-height: 1.4; +} + +#cite-repo-modal #citation-panel #citation-copy-apa, +#cite-repo-modal #citation-panel #citation-copy-bibtex { + border-right: none; +} + +#cite-repo-modal #citation-panel #goto-citation-btn { + border-left: none; +} + +#cite-repo-modal #citation-panel > :first-child { + border-radius: var(--border-radius) 0 0 var(--border-radius) !important; +} + +#cite-repo-modal #citation-panel > :last-child { + border-radius: 0 var(--border-radius) var(--border-radius) 0 !important; +} + +#cite-repo-modal #citation-panel .icon.button { + padding: 0 10px; +} + +.user-cards .list { + padding: 0; + display: flex; + flex-wrap: wrap; +} + +.user-cards .list .item { + list-style: none; + width: 32%; + margin: 10px 10px 10px 0; + padding-bottom: 14px; + float: left; +} + +.user-cards .list .item .avatar { + width: 48px; + height: 48px; + float: left; + display: block; + margin-right: 10px; +} + +.user-cards .list .item .name { + margin-top: 0; + margin-bottom: 0; + font-weight: normal; +} + +.user-cards .list .item .meta { + margin-top: 5px; +} + +#search-repo-box .results .result img, +#search-user-box .results .result img { + float: left; + margin-right: 8px; + width: 2em; + height: 2em; +} + +#search-repo-box .results .result .content, +#search-user-box .results .result .content { + margin: 6px 0; +} + +#search-team-box .results .result .content { + margin: 6px 0; +} + +#issue-actions { + margin-top: -1rem !important; /* counteract padding from Semantic */ +} + +.ui.menu .item > img:not(.ui) { + width: auto; +} + +.page.buttons { + padding-top: 15px; +} + +.commit-header-row { + min-height: 50px !important; + padding-top: 0 !important; + padding-bottom: 0 !important; +} + +.settings .content > .header, +.settings .content .segment { + box-shadow: 0 1px 2px 0 var(--color-box-header); +} + +.settings.webhooks .list > .item:not(:first-child), +.settings.githooks .list > .item:not(:first-child), +.settings.runners .list > .item:not(:first-child) { + padding: 0.25rem 1rem; + margin: 12px -1rem -1rem; +} + +.settings .list > .item:not(:first-child) { + border-top: 1px solid var(--color-secondary); + padding: 1rem; + margin: 16px -1rem -1rem; +} + +.settings .list > .item > .svg { + display: table-cell; +} + +.settings .list > .item > .svg + .content { + display: table-cell; + padding: 0 0 0 0.5em; + vertical-align: top; +} + +.settings .list > .item .info { + margin-top: 10px; +} + +.settings .list > .item .info .tab.segment { + border: 0; + padding: 10px 0 0; +} + +.settings .list.key .meta { + padding-top: 5px; + color: var(--color-text-light-2); +} + +.settings .list.email > .item:not(:first-child) { + min-height: 60px; +} + +.settings .list.collaborator > .item { + padding: 0; +} + +.ui.vertical.menu .header.item { + font-size: 1.1em; + background: var(--color-box-header); +} + +.comment:target .comment-container { + border-color: var(--color-primary) !important; + box-shadow: 0 0 0 3px var(--color-primary-alpha-30) !important; +} + +.comment:target .header::before { + border-right-color: var(--color-primary) !important; + filter: drop-shadow(-3px 0 0 var(--color-primary-alpha-30)) !important; +} + +.code-comment:target { + border-color: var(--color-primary) !important; + border-radius: var(--border-radius) !important; + box-shadow: 0 0 0 3px var(--color-primary-alpha-30) !important; +} + +.code-comment:target .content { + box-shadow: none !important; +} + +.comment-header { + border: none !important; + background: var(--color-box-header); + border-bottom: 1px solid var(--color-secondary) !important; + font-weight: normal !important; + padding: 0.5rem 1rem; + margin: 0 !important; + position: relative; + color: var(--color-text-light-2); + min-height: 41px; + background-color: var(--color-box-header); + display: flex; + justify-content: space-between; + align-items: center; +} + +.comment-header::before, +.comment-header::after { + right: 100%; + top: 20px; + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; +} + +.comment-header::before { + border-right-color: var(--color-secondary); + border-width: 9px; + margin-top: -9px; +} + +.comment-header::after { + border-right-color: var(--color-box-header); + border-width: 8px; + margin-top: -8px; +} + +.comment-header.arrow-top::before, +.comment-header.arrow-top::after { + transform: rotate(90deg); +} + +.comment-header.arrow-top::before { + top: -9px; + left: 6px; +} + +.comment-header.arrow-top::after { + top: -8px; + left: 7px; +} + +.comment-header a { + color: var(--color-text); +} + +.comment-header a:hover { + color: var(--color-primary); +} + +.comment-header .actions a { + margin-right: 0 !important; + padding: 0.5rem !important; +} + +.comment-header-left > * + *, +.comment-header-right > * + * { + margin-left: 0.25rem; +} + +.comment-body { + background: var(--color-box-body); + border: none !important; + width: 100% !important; + max-width: 100% !important; + margin: 0 !important; +} + +.edit-label.modal .form .column, +.new-label.modal .form .column { + padding-right: 0; +} + +.edit-label.modal .form .buttons, +.new-label.modal .form .buttons { + margin-left: auto; + padding-top: 15px; +} + +.edit-label.modal .form .color.picker.column, +.new-label.modal .form .color.picker.column { + display: flex; +} + +.edit-label.modal .form .color.picker.column .minicolors, +.new-label.modal .form .color.picker.column .minicolors { + flex: 1; +} + +.edit-label.modal .form .minicolors-swatch.minicolors-sprite, +.new-label.modal .form .minicolors-swatch.minicolors-sprite { + top: 10px; + left: 10px; + width: 15px; + height: 15px; +} + +#avatar-arrow::before, +#avatar-arrow::after { + right: 100%; + top: 20px; + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; +} + +#avatar-arrow::before { + border-right-color: var(--color-secondary); + border-width: 9px; + margin-top: -9px; +} + +#avatar-arrow::after { + border-right-color: var(--color-box-header); + border-width: 8px; + margin-top: -8px; +} + +#transfer-repo-modal .ui.message, +#delete-repo-modal .ui.message, +#delete-wiki-modal .ui.message, +#convert-fork-repo-modal .ui.message, +#convert-mirror-repo-modal .ui.message, +#fork-repo-modal .ui.message { + width: 100% !important; +} + +.tab-size-1 { + tab-size: 1 !important; + -moz-tab-size: 1 !important; +} + +.tab-size-2 { + tab-size: 2 !important; + -moz-tab-size: 2 !important; +} + +.tab-size-3 { + tab-size: 3 !important; + -moz-tab-size: 3 !important; +} + +.tab-size-4 { + tab-size: 4 !important; + -moz-tab-size: 4 !important; +} + +.tab-size-5 { + tab-size: 5 !important; + -moz-tab-size: 5 !important; +} + +.tab-size-6 { + tab-size: 6 !important; + -moz-tab-size: 6 !important; +} + +.tab-size-7 { + tab-size: 7 !important; + -moz-tab-size: 7 !important; +} + +.tab-size-8 { + tab-size: 8 !important; + -moz-tab-size: 8 !important; +} + +.tab-size-9 { + tab-size: 9 !important; + -moz-tab-size: 9 !important; +} + +.tab-size-10 { + tab-size: 10 !important; + -moz-tab-size: 10 !important; +} + +.tab-size-11 { + tab-size: 11 !important; + -moz-tab-size: 11 !important; +} + +.tab-size-12 { + tab-size: 12 !important; + -moz-tab-size: 12 !important; +} + +.tab-size-13 { + tab-size: 13 !important; + -moz-tab-size: 13 !important; +} + +.tab-size-14 { + tab-size: 14 !important; + -moz-tab-size: 14 !important; +} + +.tab-size-15 { + tab-size: 15 !important; + -moz-tab-size: 15 !important; +} + +.tab-size-16 { + tab-size: 16 !important; + -moz-tab-size: 16 !important; +} + +.stats-table { + display: table; + width: 100%; +} + +.stats-table .table-cell { + display: table-cell; +} + +.stats-table .table-cell.tiny { + height: 0.5em; +} + +.labels-list .label { + margin: 2px 0; + display: inline-flex !important; + line-height: 1.3em; /* there is a `font-size: 1.25em` for inside emoji, so here the line-height needs to be larger slightly */ +} + +/* Scoped labels with different colors on left and right */ +.scope-parent { + background: none !important; + padding: 0 !important; +} + +.ui.label.scope-left { + border-bottom-right-radius: 0; + border-top-right-radius: 0; + margin-right: 0; +} + +.ui.label.scope-right { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + margin-left: 0; +} + +.repo-button-row { + margin-bottom: 10px; +} + +.repo-button-row > * { + margin-top: 8px; +} + +.wiki .repo-button-row { + margin-bottom: 0; +} + +.wiki .repo-button-row > * { + margin-top: 0; +} + +.repo-button-row .button { + padding: 6px 10px !important; + height: 30px; +} + +.repo-button-row input { + height: 30px; +} + +tbody.commit-list { + vertical-align: baseline; +} + +.message-wrapper, +.author-wrapper { + overflow: hidden; + text-overflow: ellipsis; + max-width: calc(100% - 50px); + display: inline-block; + vertical-align: middle; +} + +.author-wrapper { + max-width: 180px; +} + +/* in the commit list, messages can wrap so we can use inline */ +.commit-list .message-wrapper { + display: inline; +} + +/* but in the repo-files-table we cannot */ +#repo-files-table .commit-list .message-wrapper { + display: inline-block; +} + +@media (max-width: 767px) { + tr.commit-list { + width: 100%; + } + th .message-wrapper { + display: block; + max-width: calc(100vw - 70px); + } + .author-wrapper { + max-width: 80px; + } +} + +@media (min-width: 768px) and (max-width: 991px) { + tr.commit-list { + width: 723px; + } + th .message-wrapper { + max-width: 120px; + } +} + +@media (min-width: 992px) and (max-width: 1200px) { + tr.commit-list { + width: 933px; + } + th .message-wrapper { + max-width: 350px; + } +} + +@media (min-width: 1201px) { + tr.commit-list { + width: 1127px; + } + th .message-wrapper { + max-width: 525px; + } +} + +.commit-list .commit-status-link { + display: inline-block; + vertical-align: middle; +} + +.commit-body { + white-space: pre-wrap; + line-height: initial; +} + +/* commit history list */ +.repository:not(.diff) .commit-body { + margin: 0; +} + +/* PR-comment */ +.repository:not(.diff) .timeline-item .commit-body { + margin-left: 40px; +} + +.git-notes.top { + text-align: left; +} + +.comment-diff-data { + background: var(--color-code-bg); + max-height: calc(100vh - 10.5rem); + overflow-y: auto; +} + +.comment-diff-data pre { + line-height: 18px; + white-space: pre-wrap; + word-break: break-all; + overflow-wrap: break-word; +} + +.content-history-detail-dialog .header .avatar { + position: relative; + top: -2px; +} + +#topic_edit { + margin-top: 5px; +} + +#repo-topics { + margin-top: 5px; + display: flex; + align-items: center; + flex-wrap: wrap; +} + +.repo-topic { + font-weight: normal !important; + cursor: pointer; + margin: 2px !important; +} + +#new-dependency-drop-list.ui.selection.dropdown { + min-width: 0; + width: 100%; + border-radius: 4px 0 0 4px; + border-right: 0; + white-space: nowrap; +} + +#new-dependency-drop-list .text { + width: 100%; + overflow: hidden; +} + +#manage_topic { + font-size: 12px; +} + +.label + #manage_topic { + margin-left: 5px; +} + +.ui.small.label.topic { + margin-bottom: 4px; +} + +.repo-header { + display: flex; + align-items: center; + justify-content: space-between; + flex-wrap: wrap; + word-break: break-word; +} + +@media (max-width: 767px) { + .repo-header + .container { + margin-top: 7px; + } +} + +.repo-buttons { + align-items: center; + display: flex; + flex-direction: row; + flex-wrap: wrap; + word-break: keep-all; +} + +@media (max-width: 767px) { + .repo-buttons { + margin-top: 1em; + } +} + +.repo-buttons .ui.labeled.button > .label:hover { + color: var(--color-primary-light-2); + background: var(--color-light); +} + +.repo-buttons button[disabled] ~ .label { + opacity: var(--opacity-disabled); + color: var(--color-text-dark); + background: var(--color-light-mimic-enabled) !important; +} + +.repo-buttons button[disabled] ~ .label:hover { + color: var(--color-primary-dark-1); +} + +.repo-buttons .ui.labeled.button { + cursor: initial; +} + +.repo-buttons .ui.labeled.button > .label { + border-left: 0 !important; + margin: 0 !important; +} + +.repo-buttons .ui.labeled.button.disabled { + pointer-events: inherit !important; +} + +.repo-buttons .ui.labeled.button.disabled > .label { + color: var(--color-text-dark); + background: var(--color-light-mimic-enabled) !important; +} + +.repo-buttons .ui.labeled.button.disabled > .label:hover { + color: var(--color-primary-dark-1); +} + +.repo-buttons .ui.labeled.button.disabled > .button { + pointer-events: none !important; +} + +@media (max-width: 767px) { + .repo-buttons .ui.labeled.button .svg { + display: none; + } +} + +.tag-code { + height: 28px; +} + +.tag-code, +.tag-code td, +.tag-code .blob-excerpt { + background-color: var(--color-box-body-highlight); + vertical-align: middle; +} + +.resolved-placeholder { + font-weight: normal !important; + border: 1px solid var(--color-secondary) !important; + border-radius: var(--border-radius) !important; + margin: 4px !important; +} + +.resolved-placeholder + .comment-code-cloud { + padding-top: 0 !important; +} + +td.blob-excerpt { + background-color: var(--color-secondary-alpha-30); +} + +.issue-keyword { + border-bottom: 1px dotted var(--color-text-light-3) !important; +} + +.issue-keyword:hover { + border-bottom: none !important; +} + +.file-header { + align-items: center; + display: flex; + justify-content: space-between; + overflow-x: auto; + padding: 6px 12px !important; + font-size: 13px !important; +} + +.file-info { + display: flex; + align-items: center; +} + +.file-info-entry { + display: flex; + align-items: center; + width: max-content; +} + +.file-info-entry + .file-info-entry { + border-left: 1px solid currentcolor; + margin-left: 8px; + padding-left: 8px; +} + +#diff-container { + display: flex; +} + +#diff-file-boxes { + flex: 1; + max-width: 100%; +} + +#diff-file-tree { + width: 20%; + max-width: 380px; + line-height: inherit; + position: sticky; + padding-top: 0; + top: 47px; + max-height: calc(100vh - 50px); + height: 100%; + overflow-y: auto; +} + +@media (max-width: 991px) { + #diff-file-tree { + display: none !important; + } + .diff-toggle-file-tree-button { + display: none !important; + } +} + +.ui.message.unicode-escape-prompt { + margin-bottom: 0; + border-radius: 0; + display: flex; + flex-direction: column; +} + +.wiki-content-sidebar .ui.message.unicode-escape-prompt p, +.wiki-content-footer .ui.message.unicode-escape-prompt p { + display: none; +} + +.wiki-content-toc > ul > li { + margin-bottom: 4px; +} + +.wiki-content-toc ul { + margin: 0; + list-style: none; + padding-left: 1em; +} + +/* fomantic's last-child selector does not work with hidden last child */ +.ui.buttons .unescape-button { + border-top-right-radius: 0.28571429rem; + border-bottom-right-radius: 0.28571429rem; +} + +.webhook-info { + padding: 7px 12px; + margin: 10px 0; + background-color: var(--color-markup-code-block); + border: 1px solid var(--color-secondary); + border-radius: 3px; + font-size: 13px; + line-height: 1.5; + overflow: auto; +} + +.title_wip_desc { + margin-top: 1em; +} + +.sidebar-item-link { + align-items: center; + word-break: break-all; +} + +.diff-file-box[data-folded="true"] .diff-file-body { + display: none; +} + +.diff-file-box[data-folded="true"] .diff-file-header { + border-radius: var(--border-radius) !important; +} + +.diff-file-header-actions > * + * { + margin-left: 0.5rem !important; +} + +.ui.attached.header.diff-file-header.sticky-2nd-row { + position: sticky; + top: 77px; + z-index: 7; +} + +@media (max-width: 480px) { + .ui.attached.header.diff-file-header.sticky-2nd-row { + position: static; + } +} + +.ui.attached.header.diff-file-header .diff-file-header-actions { + flex-shrink: 0; +} + +.ui.attached.header.diff-file-header .diff-file-name { + flex: auto; + min-width: 100px; +} + +.diff-file-body { + overflow-x: scroll; +} + +.diff-stats-bar { + display: inline-block; + background-color: var(--color-red); + height: 12px; + width: 40px; +} + +.diff-stats-bar .diff-stats-add-bar { + background-color: var(--color-green); + height: 100%; +} + +/* prevent page shaking on language bar click */ +.repository-summary-language-stats { + height: 48px; + overflow: hidden; +} + +@media (max-width: 767px) { + .repository-summary-language-stats { + height: auto; + } +} + +.ui.form .right .ui.button { + margin-left: 0.25em; + margin-right: 0; +} + +.removed-code { + background: var(--color-diff-removed-word-bg); +} + +.added-code { + background: var(--color-diff-added-word-bg); +} + +.code-diff-unified .del-code, +.code-diff-unified .del-code td, +.code-diff-split .del-code .lines-num-old, +.code-diff-split .del-code .lines-escape-old, +.code-diff-split .del-code .lines-type-marker-old, +.code-diff-split .del-code .lines-code-old { + background: var(--color-diff-removed-row-bg); + border-color: var(--color-diff-removed-row-border); +} + +.code-diff-unified .add-code, +.code-diff-unified .add-code td, +.code-diff-split .add-code .lines-num-new, +.code-diff-split .add-code .lines-type-marker-new, +.code-diff-split .add-code .lines-escape-new, +.code-diff-split .add-code .lines-code-new, +.code-diff-split .del-code .add-code.lines-num-new, +.code-diff-split .del-code .add-code.lines-type-marker-new, +.code-diff-split .del-code .add-code.lines-escape-new, +.code-diff-split .del-code .add-code.lines-code-new { + background: var(--color-diff-added-row-bg); + border-color: var(--color-diff-added-row-border); +} + +.code-diff-split .del-code .lines-num-new, +.code-diff-split .del-code .lines-type-marker-new, +.code-diff-split .del-code .lines-code-new, +.code-diff-split .del-code .lines-escape-new, +.code-diff-split .add-code .lines-num-old, +.code-diff-split .add-code .lines-escape-old, +.code-diff-split .add-code .lines-type-marker-old, +.code-diff-split .add-code .lines-code-old { + background: var(--color-diff-inactive); +} + +.code-diff-split tbody tr td:nth-child(5), +.code-diff-split tbody tr td.add-comment-right { + border-left: 1px solid var(--color-secondary); +} + +.repository .ui.menu.new-menu { + background: none !important; +} + +@media (max-width: 1200px) { + .repository .ui.menu.new-menu::after { + background: none !important; + } +} + +.repository.migrate .card { + transition: all 0.1s ease-in-out; + box-shadow: none !important; + border: 1px solid var(--color-secondary); + color: var(--color-text); +} + +.repository.migrate .card:hover { + transform: scale(105%); + box-shadow: 0 0.5rem 1rem var(--color-shadow) !important; +} + +@media (max-width: 767px) { + .repository.file.list #repo-files-table .entry, + .repository.file.list #repo-files-table .commit-list { + align-items: center; + display: flex !important; + padding-top: 4px; + padding-bottom: 4px; + } + .repository.file.list #repo-files-table .entry td.age, + .repository.file.list #repo-files-table .commit-list td.age, + .repository.file.list #repo-files-table .entry th.age, + .repository.file.list #repo-files-table .commit-list th.age { + margin-left: auto; + } + .repository.file.list #repo-files-table .entry td.message, + .repository.file.list #repo-files-table .commit-list td.message, + .repository.file.list #repo-files-table .entry span.commit-summary, + .repository.file.list #repo-files-table .commit-list span.commit-summary { + display: none !important; + } + .issue-list-headers.ui[class].grid > div:nth-child(1) { + order: 1; + width: 50%; + } + .issue-list-headers.ui[class].grid > div:nth-child(2) { + order: 3; + width: 100%; + } + .issue-list-headers.ui[class].grid > div.column:not(.row):nth-child(3) { + order: 2; + width: 50%; + } + .repository.view.issue .comment-list .timeline, + .repository.view.issue .comment-list .timeline-item { + margin-left: 0; + } + .repository.view.issue .comment-list .timeline::before { + left: 14px; + } + .repository.view.issue .comment-list .timeline .inline-timeline-avatar { + display: flex; + margin-bottom: auto; + } + .repository.view.issue .comment-list .timeline .inline-timeline-avatar img.avatar { + height: 24px; + width: 24px; + } + .repository.view.issue .comment-list .timeline .comment-header { + padding-left: 4px; + } + .repository.view.issue .comment-list .timeline .comment-header::before, + .repository.view.issue .comment-list .timeline .comment-header::after { + content: unset; + } + /* Don't show the general avatar, we show the inline avatar on mobile. + * And don't show the role labels, there's no place for that. */ + .repository.view.issue .comment-list .timeline .timeline-avatar, + .repository.view.issue .comment-list .timeline .comment-header-right .role-label { + display: none; + } + .commit-header-row .ui.horizontal.list { + width: 100%; + overflow-x: auto; + margin-top: 2px; + } + .commit-header-row .ui.horizontal.list .item { + align-items: center; + display: flex; + } + .commit-header-row .author { + padding: 3px 0; + } + .commit-header h3 { + flex-basis: auto !important; + margin-bottom: 0.5rem !important; + } + .commits-table { + flex-direction: column; + } + .commits-table .commits-table-left { + align-items: initial !important; + margin-bottom: 6px; + } + .commits-table .commits-table-right form { + display: flex; + flex-wrap: wrap; + } + .commits-table .commits-table-right form > div:nth-child(1) { + order: 1; + } + .commits-table .commits-table-right form > div:nth-child(2) { + order: 3; + margin-left: 0.5rem; + margin-top: 0.5rem; + } + .commits-table .commits-table-right form > button:nth-child(3) { + order: 2; + margin-left: 0.25rem; + } + .commit-table { + overflow-x: auto; + } + .commit-table td.sha, + .commit-table th.sha { + display: none !important; + } + .commit-table .commit-list span.message-wrapper { + max-width: none; + } + .commit-table .commit-list tr td:last-child { + display: block; + width: max-content; + } + .commit-table .commit-list td.author { + display: block; + width: calc(100% + 0.5rem); + } + .commit-table .commit-list .copy-commit-sha { + display: none !important; + } + .comment-header { + flex-wrap: wrap; + } + .comment-header .comment-header-left { + flex-wrap: wrap; + } + .comment-header .comment-header-right { + margin-left: auto; + } +} + +.branch-dropdown-button { + max-width: 340px; + vertical-align: bottom !important; +} + +@media (min-width: 768px) and (max-width: 991px) { + .branch-dropdown-button { + max-width: 185px; + } +} + +@media (max-width: 767px) { + .branch-dropdown-button { + max-width: 165px; + } +} + +.pr-status { + padding: 0 !important; /* To clear fomantic's padding on .ui.segment elements */ + display: flex; + align-items: center; +} + +.pr-status .commit-status { + margin: 1em; + flex-shrink: 0; +} + +.pr-status .status-context { + display: flex; + justify-content: space-between; + width: 100%; +} + +.pr-status .status-context > span { + padding: 1em 0; +} + +.pr-status .status-details { + display: flex; + padding-right: 0.5em; + align-items: center; + justify-content: flex-end; +} + +@media (max-width: 767px) { + .pr-status .status-details { + flex-direction: column; + align-items: flex-end; + justify-content: center; + } +} + +.pr-status .status-details > span { + padding-right: 0.5em; /* To match the alignment with the "required" label */ +} diff --git a/web_src/css/review.css b/web_src/css/review.css new file mode 100644 index 000000000000..b58cc5a196a8 --- /dev/null +++ b/web_src/css/review.css @@ -0,0 +1,322 @@ +.show-outdated, +.hide-outdated { + -webkit-touch-callout: none; + -webkit-user-select: none; + user-select: none; +} + +.ui.button.add-code-comment { + padding: 2px; + position: absolute; + margin-left: -22px; + z-index: 5; + opacity: 0; + transition: transform 0.1s ease-in-out; + transform: scale(1); + box-shadow: none !important; + border: none !important; +} + +.ui.button.add-code-comment:hover { + transform: scale(1.1); +} + +.lines-escape a.toggle-escape-button::before { + visibility: visible; + content: "⚠️"; + font-family: var(--fonts-emoji); + color: var(--color-red); +} + +.repository .diff-file-box .code-diff td.lines-escape { + padding-left: 0 !important; +} + +.diff-file-box .lines-code:hover .ui.button.add-code-comment { + opacity: 1; +} + +.repository .diff-file-box .code-diff .add-comment-left, +.repository .diff-file-box .code-diff .add-comment-right, +.repository .diff-file-box .code-diff .add-code-comment .add-comment-left, +.repository .diff-file-box .code-diff .add-code-comment .add-comment-right, +.repository .diff-file-box .code-diff .add-code-comment .lines-type-marker { + padding-left: 0 !important; + padding-right: 0 !important; +} + +.add-comment-left.add-comment-right .ui.attached.header { + border: 1px solid var(--color-secondary); +} + +.add-comment-left.add-comment-right .ui.attached.header:not(.top) { + margin-bottom: 0.5em; +} + +.add-comment .lines-num, +.add-comment .lines-escape, +.add-comment .lines-type-marker { + display: none; +} + +.show-outdated:hover, +.hide-outdated:hover { + text-decoration: underline; +} + +.comment-code-cloud { + padding: 0.5rem 1rem !important; + position: relative; + margin: 0 auto; + max-width: 1000px; +} + +@media (max-width: 767px) { + .comment-code-cloud { + max-width: none; + padding: 0.75rem !important; + } + .comment-code-cloud .code-comment-buttons { + margin: 0.5rem 0 0.25rem !important; + } + .comment-code-cloud .code-comment-buttons .code-comment-buttons-buttons { + width: 100%; + } + .comment-code-cloud .ui.buttons { + width: 100%; + margin: 0 !important; + } + .comment-code-cloud .ui.buttons .button { + flex: 1; + } +} + +.comment-code-cloud .comments .comment { + padding: 0; +} + +@media (max-width: 767px) { + .comment-code-cloud .comments .comment { + display: flex; + } + .comment-code-cloud + .comments + .comment + .comment-header-right.actions + .ui.basic.label { + display: none; + } + .comment-code-cloud .comments .comment .avatar { + width: auto; + float: none; + margin: 0 0.5rem 0 0; + flex-shrink: 0; + } + .comment-code-cloud .comments .comment .avatar ~ .content { + margin-left: 1em; + } + .comment-code-cloud .comments .comment img.avatar { + margin: 0 !important; + } + .comment-code-cloud .comments .comment .comment-content { + margin-left: 0 !important; + } + .comment-code-cloud .comments .comment .comment-container { + width: 100%; + } + .comment-code-cloud .comments .comment.code-comment { + padding: 0 0 0.5rem !important; + } +} + +.comment-code-cloud .attached.tab { + border: 0; + padding: 0; + margin: 0; +} + +.comment-code-cloud .attached.header { + padding: 0.1rem 1rem; +} + +.comment-code-cloud .attached.header .text { + margin: 0; +} + +.comment-code-cloud .right.menu.options .item { + padding: 0.85714286em 0.442857em; + cursor: pointer; +} + +.comment-code-cloud .ui.active.tab { + padding: 0.5em; +} + +.comment-code-cloud .ui.active.tab.markup { + padding: 1em; + min-height: 168px; +} + +.comment-code-cloud .ui.tabular.menu { + margin: 0.5em; +} + +.comment-code-cloud .footer { + border-top: 1px solid var(--color-secondary); + padding: 10px 0; +} + +.comment-code-cloud .footer .markup-info { + display: inline-block; + margin: 5px 0; + font-size: 12px; + color: var(--color-text-light); +} + +.comment-code-cloud .footer .ui.right.floated { + padding-top: 6px; +} + +.comment-code-cloud .footer::after { + clear: both; + content: ""; + display: block; +} + +@media (max-width: 767px) { + .comment-code-cloud .button { + width: 100%; + margin: 0 !important; + margin-bottom: 0.75rem !important; + } +} + +.diff-file-body .comment-form { + margin: 0 0 0 3em; +} + +.file-comment { + color: var(--color-text); +} + +a.blob-excerpt { + color: var(--color-text-light); + height: 28px; + display: flex; + justify-content: center; + align-items: center; + width: 100%; + background: var(--color-expand-button); +} + +a.blob-excerpt:hover { + background: var(--color-primary); + color: var(--color-primary-contrast); +} + +/* See the comment of createCommentEasyMDE() for the review editor */ +/* EasyMDE's options can not handle minHeight & maxHeight together correctly, we have to set minHeight in JS code */ +.review-box-panel .CodeMirror-scroll { + min-height: 80px; + max-height: calc(100vh - 360px); +} + +@media (max-width: 767px) { + .review-box-panel .CodeMirror-scroll { + max-width: calc(100vw - 70px); + } +} + +@media (min-width: 768px) and (max-width: 991px) { + .review-box-panel .CodeMirror-scroll { + max-width: 700px; + } +} + +@media (min-width: 992px) and (max-width: 1200px) { + .review-box-panel .CodeMirror-scroll { + max-width: 800px; + } +} + +@media (min-width: 1201px) { + .review-box-panel .CodeMirror-scroll { + max-width: 900px; + } +} + +#review-box { + position: relative; +} + +.review-box-panel { + position: absolute; + min-width: max-content; + top: 45px; + right: -5px; + z-index: 2; +} + +#review-box .review-comments-counter { + background-color: var(--color-primary-light-4); + color: var(--color-primary-contrast); +} + +#review-box:hover .review-comments-counter { + background-color: var(--color-primary-light-5); +} + +#review-box .review-comments-counter[data-pending-comment-number="0"] { + display: none; +} + +.pull.files.diff [id] { + scroll-margin-top: 99px; +} + +@media (max-width: 991px) { + .pull.files.diff [id] { + scroll-margin-top: 130px; + } +} + +.changed-since-last-review { + border: 1px var(--color-accent) solid; + background-color: var(--color-small-accent); + border-radius: 15px; + padding: 4px 8px; + margin: -8px 0; /* just like other buttons in the diff box header */ + font-size: 0.857rem; /* just like .ui.tiny.button */ +} + +.viewed-file-form { + display: flex; + align-items: center; + border: 1px solid transparent; + padding: 4px 8px; + margin: -8px 0; /* just like other buttons in the diff box header */ + border-radius: 0.285rem; /* just like .ui.tiny.button */ + font-size: 0.857rem; /* just like .ui.tiny.button */ +} + +.viewed-file-form input { + margin-right: 4px; +} + +.viewed-file-checked-form { + background-color: var(--color-small-accent); + border-color: var(--color-accent); +} + +#viewed-files-summary { + width: 72px; + height: 10px; +} + +.diff-file-box { + border-radius: 0.285rem; /* Just like ui.top.attached.header */ +} + +.diff-file-box:target { + box-shadow: 0 0 0 3px var(--color-accent); +} diff --git a/web_src/css/runner.css b/web_src/css/runner.css new file mode 100644 index 000000000000..d0ea5252e516 --- /dev/null +++ b/web_src/css/runner.css @@ -0,0 +1,54 @@ +.runner-container { + padding-bottom: 30px; +} + +.runner-container .runner-ops > a { + margin-left: 0.5em; +} + +.runner-container .runner-ops-delete { + color: var(--color-red-light); +} + +.runner-container .runner-basic-info .gt-dib { + margin-right: 1em; +} + +.runner-container .runner-status-online { + padding: 0.3em 0.5em; + background-color: var(--color-green); + color: var(--color-white); +} + +.runner-container .runner-new-text { + color: var(--color-white); +} + +.runner-container #runner-new:hover .runner-new-text { + color: var(--color-white) !important; +} + +.runner-container .runner-new-menu { + width: 300px; +} + +.runner-container .task-status-success { + background-color: var(--color-green); + color: var(--color-white); +} + +.runner-container .task-status-failure { + background-color: var(--color-red-light); + color: var(--color-white); +} + +.runner-container .task-status-running { + background-color: var(--color-blue); + color: var(--color-white); +} + +.runner-container .task-status-cancelled, +.runner-container .task-status-blocked { + background-color: var(--color-yellow); + color: var(--color-white); +} diff --git a/web_src/css/shared/issuelist.css b/web_src/css/shared/issuelist.css new file mode 100644 index 000000000000..6e2cc737e7d9 --- /dev/null +++ b/web_src/css/shared/issuelist.css @@ -0,0 +1,166 @@ +.issue.list { + list-style: none; + margin-top: 1rem; +} + +.issue.list a:not(.label):hover { + color: var(--color-primary) !important; +} + +.issue.list > .item .issue-checkbox { + margin-top: 1px; +} + +.issue.list > .item .issue-item-icon svg { + margin-right: 0.75rem; + margin-top: 1px; +} + +.issue.list > .item .issue-item-icons-right > * + * { + margin-left: 0.5rem; +} + +.issue.list > .item .issue-item-main { + width: 100%; +} + +.issue.list > .item .action-item-main { + width: 80%; +} + +.issue.list > .item .issue-item-right { + width: 15%; +} + +.issue.list > .item .issue-item-top-row { + max-width: 100%; + color: var(--color-text); + font-size: 16px; + min-width: 0; + font-weight: 600; +} + +.issue.list > .item .issue-item-top-row a.index { + max-width: fit-content; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + overflow: hidden; + word-break: break-all; +} + +.issue.list > .item .labels-list { + position: relative; + top: -1.5px; +} + +.issue.list > .item .issue-item-bottom-row { + font-size: 13px; +} + +.issue.list > .item .title { + color: var(--color-text); + word-break: break-word; +} + +.issue.list > .item .issue-item-icon-right { + min-width: 2rem; +} + +.issue.list > .item .assignee { + position: relative; + top: -2px; +} + +.issue.list > .item .assignee img { + width: 20px; + height: 20px; + margin-right: 2px; +} + +.issue.list > .item .desc { + color: var(--color-text-light-2); +} + +.issue.list > .item .desc a { + color: inherit; +} + +.issue.list > .item .desc .time-since, +.issue.list > .item .desc a { + margin-left: 0.25rem; + margin-right: 0.25rem; +} + +.issue.list > .item .desc .waiting, +.issue.list > .item .desc .approvals, +.issue.list > .item .desc .rejects { + padding-left: 5px; +} + +.issue.list > .item .desc .checklist { + padding-left: 5px; +} + +.issue.list > .item .desc .checklist progress { + margin-left: 2px; + width: 80px; + height: 6px; + display: inline-block; + border-radius: 3px; + vertical-align: 2px !important; +} + +.issue.list > .item .desc .checklist progress::-webkit-progress-value { + background-color: var(--color-secondary-dark-4); +} + +.issue.list > .item .desc .checklist progress::-moz-progress-bar { + background-color: var(--color-secondary-dark-4); +} + +.issue.list > .item .desc .conflicting { + padding-left: 5px; +} + +.issue.list > .item .desc .due-date { + padding-left: 5px; +} + +.issue.list > .item .desc a.milestone, +.issue.list > .item .desc a.project { + margin-left: 5px; +} + +.issue.list > .item .desc a.ref { + margin-left: 8px; +} + +.issue.list > .item .desc a.ref span { + margin-right: -4px; +} + +.issue.list > .item .desc .overdue { + color: var(--color-red); +} + +.issue.list .branches { + display: inline-flex; + padding: 0 4px; +} + +.issue.list .branches .branch { + background-color: var(--color-secondary); + border-radius: 3px; +} + +.issue.list .branches .truncated-name { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 10em; +} + +.issue.list > .item + .item { + border-top: 1px solid var(--color-secondary); +} diff --git a/web_src/less/standalone/swagger.less b/web_src/css/standalone/swagger.css similarity index 94% rename from web_src/less/standalone/swagger.less rename to web_src/css/standalone/swagger.css index 3b902483d829..5c1902f11f79 100644 --- a/web_src/less/standalone/swagger.less +++ b/web_src/css/standalone/swagger.css @@ -27,5 +27,5 @@ body { .swagger-back-link svg { color: inherit; fill: currentcolor; - margin-right: .5rem; + margin-right: 0.5rem; } diff --git a/web_src/less/_svg.less b/web_src/css/svg.css similarity index 64% rename from web_src/less/_svg.less rename to web_src/css/svg.css index a2ea64c4380b..b63445eb4e20 100644 --- a/web_src/less/_svg.less +++ b/web_src/css/svg.css @@ -2,8 +2,8 @@ display: inline-block; vertical-align: text-top; fill: currentcolor; +} - .middle & { - vertical-align: middle; - } +.middle .svg { + vertical-align: middle; } diff --git a/web_src/less/themes/theme-arc-green.less b/web_src/css/themes/theme-arc-green.css similarity index 98% rename from web_src/less/themes/theme-arc-green.less rename to web_src/css/themes/theme-arc-green.css index 17b8f9bae034..e2216085a907 100644 --- a/web_src/less/themes/theme-arc-green.less +++ b/web_src/css/themes/theme-arc-green.css @@ -1,6 +1,6 @@ -@import "../chroma/base.less"; -@import "../chroma/dark.less"; -@import "../codemirror/dark.less"; +@import "../chroma/base.css"; +@import "../chroma/dark.css"; +@import "../codemirror/dark.css"; :root { --is-dark-theme: true; diff --git a/web_src/css/themes/theme-auto.css b/web_src/css/themes/theme-auto.css new file mode 100644 index 000000000000..e0d31e2cfbb7 --- /dev/null +++ b/web_src/css/themes/theme-auto.css @@ -0,0 +1 @@ +@import "./theme-arc-green.css" (prefers-color-scheme: dark); diff --git a/web_src/less/_tribute.less b/web_src/css/tribute.css similarity index 80% rename from web_src/less/_tribute.less rename to web_src/css/tribute.css index 9adf155ffaf4..b7b0a255092c 100644 --- a/web_src/less/_tribute.less +++ b/web_src/css/tribute.css @@ -1,8 +1,8 @@ @import "tributejs/dist/tribute.css"; .tribute-container { - box-shadow: 0 .25rem .5rem rgba(0, 0, 0, .25); - border-radius: .25rem; + box-shadow: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.25); + border-radius: 0.25rem; } .tribute-container ul { @@ -11,12 +11,12 @@ } .tribute-container li { - padding: 3px .5rem !important; + padding: 3px 0.5rem !important; } .tribute-container li span.fullname { font-weight: normal; - font-size: .8rem; + font-size: 0.8rem; margin-left: 3px; } @@ -33,7 +33,7 @@ .tribute-item .emoji, .tribute-item img[src*="/avatar/"] { - margin-right: .5rem; + margin-right: 0.5rem; } .tribute-container img { diff --git a/web_src/css/user.css b/web_src/css/user.css new file mode 100644 index 000000000000..adf865496be3 --- /dev/null +++ b/web_src/css/user.css @@ -0,0 +1,173 @@ +.user.profile .ui.card .header { + display: block; + font-weight: 600; + font-size: 1.3rem; + margin-top: -0.2rem; + line-height: 1.3rem; +} + +.user.profile .ui.card .profile-avatar-name { + border-top: none; + text-align: center; +} + +.user.profile .ui.card .extra.content { + padding: 0; +} + +.user.profile .ui.card .extra.content ul { + margin: 0; + padding: 0; +} + +.user.profile .ui.card .extra.content ul li { + padding: 10px; + list-style: none; +} + +.user.profile .ui.card .extra.content ul li:not(:last-child) { + border-bottom: 1px solid var(--color-secondary); +} + +.user.profile .ui.card .extra.content ul li .svg { + margin-left: 1px; + margin-right: 5px; +} + +.user.profile .ui.card .extra.content ul li.follow .ui.button { + width: 100%; +} + +.user.profile .ui.card #profile-avatar { + background: none; + padding: 1rem 1rem 0.25rem; + justify-content: center; +} + +.user.profile .ui.card #profile-avatar img { + width: 100%; + height: auto; + object-fit: contain; + margin: 0; +} + +@media (max-width: 767px) { + .user.profile .ui.card #profile-avatar img { + width: 30vw; + } +} + +@media (max-width: 767px) { + .user.profile .ui.card { + width: 100%; + } +} + +.user.profile .ui.repository.list { + margin-top: 25px; +} + +.user.profile #loading-heatmap { + margin-bottom: 1em; +} + +.user.profile .ui.secondary.stackable.pointing.menu { + flex-wrap: wrap; +} + +.user.followers .header.name { + font-size: 20px; + line-height: 24px; + vertical-align: middle; +} + +.user.followers .follow .ui.button { + padding: 8px 15px; +} + +.user.notification .svg { + float: left; + font-size: 2em; +} + +.user.notification .svg.green { + color: var(--color-green); +} + +.user.notification .svg.red { + color: var(--color-red); +} + +.user.notification .svg.purple { + color: var(--color-purple); +} + +.user.notification .svg.blue { + color: var(--color-blue); +} + +.user.notification .content { + float: left; + margin-left: 7px; +} + +.user.notification table form { + display: inline-block; +} + +.user.notification table button { + padding: 3px 3px 3px 5px; +} + +.user.notification table tr { + cursor: pointer; +} + +.user .button.adopt, +.user .button.delete { + margin-top: -15px; + margin-bottom: -15px; +} + +.user .button.adopt .label, +.user .button.delete .label { + vertical-align: middle; +} + +.user.link-account:not(.icon) { + padding-top: 15px; + padding-bottom: 5px; +} + +.user.settings .iconFloat { + float: left; +} + +.user-orgs { + display: flex; + flex-flow: row wrap; + padding: 0; + margin: -3px !important; +} + +.user-orgs li { + display: flex; + border-bottom: 0 !important; + padding: 3px !important; + width: 20%; + max-width: 60px; +} + +.user-badges { + display: grid; + grid-template-columns: repeat(auto-fill, 64px); + gap: 2px; +} + +.user-badges img { + object-fit: contain; +} + +#notification_div .tab.segment { + overflow-x: auto; +} diff --git a/web_src/js/components/DashboardRepoList.js b/web_src/js/components/DashboardRepoList.js deleted file mode 100644 index 2328cc83a90c..000000000000 --- a/web_src/js/components/DashboardRepoList.js +++ /dev/null @@ -1,345 +0,0 @@ -import {createApp, nextTick} from 'vue'; -import $ from 'jquery'; -import {initVueSvg, vueDelimiters} from './VueComponentLoader.js'; -import {initTooltip} from '../modules/tippy.js'; - -const {appSubUrl, assetUrlPrefix, pageData} = window.config; - -function initVueComponents(app) { - app.component('repo-search', { - delimiters: vueDelimiters, - props: { - searchLimit: { - type: Number, - default: 10 - }, - subUrl: { - type: String, - required: true - }, - uid: { - type: Number, - default: 0 - }, - teamId: { - type: Number, - required: false, - default: 0 - }, - organizations: { - type: Array, - default: () => [], - }, - isOrganization: { - type: Boolean, - default: true - }, - canCreateOrganization: { - type: Boolean, - default: false - }, - organizationsTotalCount: { - type: Number, - default: 0 - }, - moreReposLink: { - type: String, - default: '' - } - }, - - data() { - const params = new URLSearchParams(window.location.search); - - let tab = params.get('repo-search-tab'); - if (!tab) { - tab = 'repos'; - } - - let reposFilter = params.get('repo-search-filter'); - if (!reposFilter) { - reposFilter = 'all'; - } - - let privateFilter = params.get('repo-search-private'); - if (!privateFilter) { - privateFilter = 'both'; - } - - let archivedFilter = params.get('repo-search-archived'); - if (!archivedFilter) { - archivedFilter = 'unarchived'; - } - - let searchQuery = params.get('repo-search-query'); - if (!searchQuery) { - searchQuery = ''; - } - - let page = 1; - try { - page = parseInt(params.get('repo-search-page')); - } catch { - // noop - } - if (!page) { - page = 1; - } - - return { - hasMounted: false, // accessing $refs in computed() need to wait for mounted - tab, - repos: [], - reposTotalCount: 0, - reposFilter, - archivedFilter, - privateFilter, - page, - finalPage: 1, - searchQuery, - isLoading: false, - staticPrefix: assetUrlPrefix, - counts: {}, - repoTypes: { - all: { - searchMode: '', - }, - forks: { - searchMode: 'fork', - }, - mirrors: { - searchMode: 'mirror', - }, - sources: { - searchMode: 'source', - }, - collaborative: { - searchMode: 'collaborative', - }, - } - }; - }, - - computed: { - // used in `repolist.tmpl` - showMoreReposLink() { - return this.repos.length > 0 && this.repos.length < this.counts[`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`]; - }, - searchURL() { - return `${this.subUrl}/repo/search?sort=updated&order=desc&uid=${this.uid}&team_id=${this.teamId}&q=${this.searchQuery - }&page=${this.page}&limit=${this.searchLimit}&mode=${this.repoTypes[this.reposFilter].searchMode - }${this.reposFilter !== 'all' ? '&exclusive=1' : '' - }${this.archivedFilter === 'archived' ? '&archived=true' : ''}${this.archivedFilter === 'unarchived' ? '&archived=false' : '' - }${this.privateFilter === 'private' ? '&is_private=true' : ''}${this.privateFilter === 'public' ? '&is_private=false' : '' - }`; - }, - repoTypeCount() { - return this.counts[`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`]; - }, - checkboxArchivedFilterTitle() { - return this.hasMounted && this.$refs.checkboxArchivedFilter?.getAttribute(`data-title-${this.archivedFilter}`); - }, - checkboxArchivedFilterProps() { - return {checked: this.archivedFilter === 'archived', indeterminate: this.archivedFilter === 'both'}; - }, - checkboxPrivateFilterTitle() { - return this.hasMounted && this.$refs.checkboxPrivateFilter?.getAttribute(`data-title-${this.privateFilter}`); - }, - checkboxPrivateFilterProps() { - return {checked: this.privateFilter === 'private', indeterminate: this.privateFilter === 'both'}; - }, - }, - - mounted() { - const el = document.getElementById('dashboard-repo-list'); - this.changeReposFilter(this.reposFilter); - for (const elTooltip of el.querySelectorAll('.tooltip')) { - initTooltip(elTooltip); - } - $(el).find('.dropdown').dropdown(); - nextTick(() => { - this.$refs.search.focus(); - }); - - this.hasMounted = true; - }, - - methods: { - changeTab(t) { - this.tab = t; - this.updateHistory(); - }, - - changeReposFilter(filter) { - this.reposFilter = filter; - this.repos = []; - this.page = 1; - this.counts[`${filter}:${this.archivedFilter}:${this.privateFilter}`] = 0; - this.searchRepos(); - }, - - updateHistory() { - const params = new URLSearchParams(window.location.search); - - if (this.tab === 'repos') { - params.delete('repo-search-tab'); - } else { - params.set('repo-search-tab', this.tab); - } - - if (this.reposFilter === 'all') { - params.delete('repo-search-filter'); - } else { - params.set('repo-search-filter', this.reposFilter); - } - - if (this.privateFilter === 'both') { - params.delete('repo-search-private'); - } else { - params.set('repo-search-private', this.privateFilter); - } - - if (this.archivedFilter === 'unarchived') { - params.delete('repo-search-archived'); - } else { - params.set('repo-search-archived', this.archivedFilter); - } - - if (this.searchQuery === '') { - params.delete('repo-search-query'); - } else { - params.set('repo-search-query', this.searchQuery); - } - - if (this.page === 1) { - params.delete('repo-search-page'); - } else { - params.set('repo-search-page', `${this.page}`); - } - - const queryString = params.toString(); - if (queryString) { - window.history.replaceState({}, '', `?${queryString}`); - } else { - window.history.replaceState({}, '', window.location.pathname); - } - }, - - toggleArchivedFilter() { - if (this.archivedFilter === 'unarchived') { - this.archivedFilter = 'archived'; - } else if (this.archivedFilter === 'archived') { - this.archivedFilter = 'both'; - } else { // including both - this.archivedFilter = 'unarchived'; - } - this.page = 1; - this.repos = []; - this.counts[`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`] = 0; - this.searchRepos(); - }, - - togglePrivateFilter() { - if (this.privateFilter === 'both') { - this.privateFilter = 'public'; - } else if (this.privateFilter === 'public') { - this.privateFilter = 'private'; - } else { // including private - this.privateFilter = 'both'; - } - this.page = 1; - this.repos = []; - this.counts[`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`] = 0; - this.searchRepos(); - }, - - - changePage(page) { - this.page = page; - if (this.page > this.finalPage) { - this.page = this.finalPage; - } - if (this.page < 1) { - this.page = 1; - } - this.repos = []; - this.counts[`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`] = 0; - this.searchRepos(); - }, - - async searchRepos() { - this.isLoading = true; - - const searchedMode = this.repoTypes[this.reposFilter].searchMode; - const searchedURL = this.searchURL; - const searchedQuery = this.searchQuery; - - let response, json; - try { - if (!this.reposTotalCount) { - const totalCountSearchURL = `${this.subUrl}/repo/search?count_only=1&uid=${this.uid}&team_id=${this.teamId}&q=&page=1&mode=`; - response = await fetch(totalCountSearchURL); - this.reposTotalCount = response.headers.get('X-Total-Count'); - } - - response = await fetch(searchedURL); - json = await response.json(); - } catch { - if (searchedURL === this.searchURL) { - this.isLoading = false; - } - return; - } - - if (searchedURL === this.searchURL) { - this.repos = json.data; - const count = response.headers.get('X-Total-Count'); - if (searchedQuery === '' && searchedMode === '' && this.archivedFilter === 'both') { - this.reposTotalCount = count; - } - this.counts[`${this.reposFilter}:${this.archivedFilter}:${this.privateFilter}`] = count; - this.finalPage = Math.ceil(count / this.searchLimit); - this.updateHistory(); - this.isLoading = false; - } - }, - - repoIcon(repo) { - if (repo.fork) { - return 'octicon-repo-forked'; - } else if (repo.mirror) { - return 'octicon-mirror'; - } else if (repo.template) { - return `octicon-repo-template`; - } else if (repo.private) { - return 'octicon-lock'; - } else if (repo.internal) { - return 'octicon-repo'; - } - return 'octicon-repo'; - } - }, - - template: document.getElementById('dashboard-repo-list-template'), - }); -} - -export function initDashboardRepoList() { - const el = document.getElementById('dashboard-repo-list'); - const dashboardRepoListData = pageData.dashboardRepoList || null; - if (!el || !dashboardRepoListData) return; - - const app = createApp({ - delimiters: vueDelimiters, - data() { - return { - searchLimit: dashboardRepoListData.searchLimit || 0, - subUrl: appSubUrl, - uid: dashboardRepoListData.uid || 0, - }; - }, - }); - initVueSvg(app); - initVueComponents(app); - app.mount(el); -} diff --git a/web_src/js/components/DashboardRepoList.vue b/web_src/js/components/DashboardRepoList.vue new file mode 100644 index 000000000000..cc76ab627ff4 --- /dev/null +++ b/web_src/js/components/DashboardRepoList.vue @@ -0,0 +1,432 @@ + + + diff --git a/web_src/js/components/PullRequestMergeForm.vue b/web_src/js/components/PullRequestMergeForm.vue index fc610d219426..4d8c14a76d92 100644 --- a/web_src/js/components/PullRequestMergeForm.vue +++ b/web_src/js/components/PullRequestMergeForm.vue @@ -10,8 +10,8 @@ -d '{"context": "test/context", "description": "description", "state": "${state}", "target_url": "http://localhost"}' -->
    - -
    + +
    @@ -30,7 +30,8 @@ -
    +
    + {{ mergeForm.textClearMergeMessageHint }}
    diff --git a/web_src/js/components/RepoActionView.vue b/web_src/js/components/RepoActionView.vue index aadc8369b75e..079c81921e15 100644 --- a/web_src/js/components/RepoActionView.vue +++ b/web_src/js/components/RepoActionView.vue @@ -43,8 +43,7 @@
    - - + @@ -287,51 +286,54 @@ export function initRepositoryActionView() { - - + + diff --git a/web_src/js/components/RepoActivityTopAuthors.vue b/web_src/js/components/RepoActivityTopAuthors.vue index 37b6df91878f..294ee6f7bcce 100644 --- a/web_src/js/components/RepoActivityTopAuthors.vue +++ b/web_src/js/components/RepoActivityTopAuthors.vue @@ -51,7 +51,7 @@ diff --git a/web_src/js/components/RepoBranchTagDropdown.js b/web_src/js/components/RepoBranchTagDropdown.js deleted file mode 100644 index e1bf35c1294d..000000000000 --- a/web_src/js/components/RepoBranchTagDropdown.js +++ /dev/null @@ -1,209 +0,0 @@ -import {createApp, nextTick} from 'vue'; -import $ from 'jquery'; -import {vueDelimiters} from './VueComponentLoader.js'; - -export function initRepoBranchTagDropdown(selector) { - $(selector).each(function (dropdownIndex, elRoot) { - const data = { - csrfToken: window.config.csrfToken, - items: [], - searchTerm: '', - menuVisible: false, - createTag: false, - release: null, - - isViewTag: false, - isViewBranch: false, - isViewTree: false, - - active: 0, - - ...window.config.pageData.branchDropdownDataList[dropdownIndex], - }; - - // the "data.defaultBranch" is ambiguous, it could be "branch name" or "tag name" - - if (data.showBranchesInDropdown && data.branches) { - for (const branch of data.branches) { - data.items.push({name: branch, url: branch, branch: true, tag: false, selected: branch === data.defaultBranch}); - } - } - if (!data.noTag && data.tags) { - for (const tag of data.tags) { - if (data.release) { - data.items.push({name: tag, url: tag, branch: false, tag: true, selected: tag === data.release.tagName}); - } else { - data.items.push({name: tag, url: tag, branch: false, tag: true, selected: tag === data.defaultBranch}); - } - } - } - - const view = createApp({ - delimiters: vueDelimiters, - data() { - return data; - }, - computed: { - filteredItems() { - const items = this.items.filter((item) => { - return ((this.mode === 'branches' && item.branch) || (this.mode === 'tags' && item.tag)) && - (!this.searchTerm || item.name.toLowerCase().includes(this.searchTerm.toLowerCase())); - }); - - // no idea how to fix this so linting rule is disabled instead - this.active = (items.length === 0 && this.showCreateNewBranch ? 0 : -1); // eslint-disable-line vue/no-side-effects-in-computed-properties - return items; - }, - showNoResults() { - return this.filteredItems.length === 0 && !this.showCreateNewBranch; - }, - showCreateNewBranch() { - if (this.disableCreateBranch || !this.searchTerm) { - return false; - } - - return this.items.filter((item) => item.name.toLowerCase() === this.searchTerm.toLowerCase()).length === 0; - } - }, - - watch: { - menuVisible(visible) { - if (visible) { - this.focusSearchField(); - } - } - }, - - beforeMount() { - switch (data.viewType) { - case 'tree': - this.isViewTree = true; - break; - case 'tag': - this.isViewTag = true; - break; - default: - this.isViewBranch = true; - break; - } - - document.body.addEventListener('click', (event) => { - if (elRoot.contains(event.target)) return; - if (this.menuVisible) { - this.menuVisible = false; - } - }); - }, - - methods: { - selectItem(item) { - const prev = this.getSelected(); - if (prev !== null) { - prev.selected = false; - } - item.selected = true; - const url = (item.tag) ? this.tagURLPrefix + item.url + this.tagURLSuffix : this.branchURLPrefix + item.url + this.branchURLSuffix; - if (!this.branchForm) { - window.location.href = url; - } else { - this.isViewTree = false; - this.isViewTag = false; - this.isViewBranch = false; - this.$refs.dropdownRefName.textContent = item.name; - if (this.setAction) { - $(`#${this.branchForm}`).attr('action', url); - } else { - $(`#${this.branchForm} input[name="refURL"]`).val(url); - } - $(`#${this.branchForm} input[name="ref"]`).val(item.name); - if (item.tag) { - this.isViewTag = true; - $(`#${this.branchForm} input[name="refType"]`).val('tag'); - } else { - this.isViewBranch = true; - $(`#${this.branchForm} input[name="refType"]`).val('branch'); - } - if (this.submitForm) { - $(`#${this.branchForm}`).trigger('submit'); - } - this.menuVisible = false; - } - }, - createNewBranch() { - if (!this.showCreateNewBranch) return; - $(this.$refs.newBranchForm).trigger('submit'); - }, - focusSearchField() { - nextTick(() => { - this.$refs.searchField.focus(); - }); - }, - getSelected() { - for (let i = 0, j = this.items.length; i < j; ++i) { - if (this.items[i].selected) return this.items[i]; - } - return null; - }, - getSelectedIndexInFiltered() { - for (let i = 0, j = this.filteredItems.length; i < j; ++i) { - if (this.filteredItems[i].selected) return i; - } - return -1; - }, - scrollToActive() { - let el = this.$refs[`listItem${this.active}`]; - if (!el || !el.length) return; - if (Array.isArray(el)) { - el = el[0]; - } - - const cont = this.$refs.scrollContainer; - if (el.offsetTop < cont.scrollTop) { - cont.scrollTop = el.offsetTop; - } else if (el.offsetTop + el.clientHeight > cont.scrollTop + cont.clientHeight) { - cont.scrollTop = el.offsetTop + el.clientHeight - cont.clientHeight; - } - }, - keydown(event) { - if (event.keyCode === 40) { // arrow down - event.preventDefault(); - - if (this.active === -1) { - this.active = this.getSelectedIndexInFiltered(); - } - - if (this.active + (this.showCreateNewBranch ? 0 : 1) >= this.filteredItems.length) { - return; - } - this.active++; - this.scrollToActive(); - } else if (event.keyCode === 38) { // arrow up - event.preventDefault(); - - if (this.active === -1) { - this.active = this.getSelectedIndexInFiltered(); - } - - if (this.active <= 0) { - return; - } - this.active--; - this.scrollToActive(); - } else if (event.keyCode === 13) { // enter - event.preventDefault(); - - if (this.active >= this.filteredItems.length) { - this.createNewBranch(); - } else if (this.active >= 0) { - this.selectItem(this.filteredItems[this.active]); - } - } else if (event.keyCode === 27) { // escape - event.preventDefault(); - this.menuVisible = false; - } - } - } - }); - view.mount(this); - }); -} diff --git a/web_src/js/components/RepoBranchTagSelector.vue b/web_src/js/components/RepoBranchTagSelector.vue new file mode 100644 index 000000000000..6a65eeec6fae --- /dev/null +++ b/web_src/js/components/RepoBranchTagSelector.vue @@ -0,0 +1,293 @@ + + + diff --git a/web_src/js/components/VueComponentLoader.js b/web_src/js/components/VueComponentLoader.js deleted file mode 100644 index 33ebf95eff96..000000000000 --- a/web_src/js/components/VueComponentLoader.js +++ /dev/null @@ -1,49 +0,0 @@ -import {createApp} from 'vue'; -import {svgs} from '../svg.js'; - -export const vueDelimiters = ['${', '}']; - -let vueEnvInited = false; -export function initVueEnv() { - if (vueEnvInited) return; - vueEnvInited = true; - - // As far as I could tell, this is no longer possible. - // But there seem not to be a guide what to do instead. - // const isProd = window.config.runModeIsProd; - // Vue.config.devtools = !isProd; -} - -let vueSvgInited = false; -export function initVueSvg(app) { - if (vueSvgInited) return; - vueSvgInited = true; - - // register svg icon vue components, e.g. - for (const [name, htmlString] of Object.entries(svgs)) { - const template = htmlString - .replace(/height="[0-9]+"/, 'v-bind:height="size"') - .replace(/width="[0-9]+"/, 'v-bind:width="size"'); - - app.component(name, { - props: { - size: { - type: String, - default: '16', - }, - }, - template, - }); - } -} - -export function initVueApp(el, opts = {}) { - if (typeof el === 'string') { - el = document.querySelector(el); - } - if (!el) return null; - - return createApp( - {delimiters: vueDelimiters, ...opts} - ).mount(el); -} diff --git a/web_src/js/features/admin/common.js b/web_src/js/features/admin/common.js index d023e0bc3695..be5aa876a5db 100644 --- a/web_src/js/features/admin/common.js +++ b/web_src/js/features/admin/common.js @@ -198,7 +198,8 @@ export function initAdminCommon() { break; } }); - $('#delete-selection').on('click', function () { + $('#delete-selection').on('click', function (e) { + e.preventDefault(); const $this = $(this); $this.addClass('loading disabled'); const ids = []; diff --git a/web_src/js/features/common-global.js b/web_src/js/features/common-global.js index 4fa6942467ee..0f36ce2bf84f 100644 --- a/web_src/js/features/common-global.js +++ b/web_src/js/features/common-global.js @@ -202,7 +202,8 @@ export function initGlobalDropzone() { } export function initGlobalLinkActions() { - function showDeletePopup() { + function showDeletePopup(e) { + e.preventDefault(); const $this = $(this); const dataArray = $this.data(); let filter = ''; @@ -243,10 +244,10 @@ export function initGlobalLinkActions() { }); } }).modal('show'); - return false; } - function showAddAllPopup() { + function showAddAllPopup(e) { + e.preventDefault(); const $this = $(this); let filter = ''; if ($this.attr('id')) { @@ -272,7 +273,6 @@ export function initGlobalLinkActions() { }); } }).modal('show'); - return false; } function linkAction(e) { @@ -318,13 +318,21 @@ export function initGlobalLinkActions() { } export function initGlobalButtons() { - $('.show-panel.button').on('click', function () { + // There are many "cancel button" elements in modal dialogs, Fomantic UI expects they are button-like elements but never submit a form. + // However, Gitea misuses the modal dialog and put the cancel buttons inside forms, so we must prevent the form submission. + // There are a few cancel buttons in non-modal forms, and there are some dynamically created forms (eg: the "Edit Issue Content") + $(document).on('click', 'form .ui.cancel.button', (e) => { + e.preventDefault(); + }); + + $('.show-panel.button').on('click', function (e) { + e.preventDefault(); showElem($(this).data('panel')); }); - $('.hide-panel.button').on('click', function (event) { + $('.hide-panel.button').on('click', function (e) { // a `.hide-panel.button` can hide a panel, by `data-panel="selector"` or `data-panel-closest="selector"` - event.preventDefault(); + e.preventDefault(); let sel = $(this).attr('data-panel'); if (sel) { hideElem($(sel)); @@ -339,7 +347,8 @@ export function initGlobalButtons() { alert('Nothing to hide'); }); - $('.show-modal').on('click', function () { + $('.show-modal').on('click', function (e) { + e.preventDefault(); const modalDiv = $($(this).attr('data-modal')); for (const attrib of this.attributes) { if (!attrib.name.startsWith('data-modal-')) { @@ -360,7 +369,8 @@ export function initGlobalButtons() { } }); - $('.delete-post.button').on('click', function () { + $('.delete-post.button').on('click', function (e) { + e.preventDefault(); const $this = $(this); $.post($this.attr('data-request-url'), { _csrf: csrfToken diff --git a/web_src/js/features/common-issue.js b/web_src/js/features/common-issue.js index 0965caef154f..ebc851d67633 100644 --- a/web_src/js/features/common-issue.js +++ b/web_src/js/features/common-issue.js @@ -34,6 +34,7 @@ export function initCommonIssue() { }); $('.issue-action').on('click', async function (e) { + e.preventDefault(); let action = this.getAttribute('data-action'); let elementId = this.getAttribute('data-element-id'); const url = this.getAttribute('data-url'); diff --git a/web_src/js/features/repo-findfile.js b/web_src/js/features/repo-findfile.js index 093f90fe8efe..078c822aa2b9 100644 --- a/web_src/js/features/repo-findfile.js +++ b/web_src/js/features/repo-findfile.js @@ -1,6 +1,7 @@ import $ from 'jquery'; import {svg} from '../svg.js'; import {toggleElem} from '../utils/dom.js'; +import {pathEscapeSegments} from '../utils/url.js'; const {csrf} = window.config; @@ -73,10 +74,6 @@ export function filterRepoFilesWeighted(files, filter) { return filterResult; } -export function escapePath(s) { - return s.split('/').map(encodeURIComponent).join('/'); -} - function filterRepoFiles(filter) { const treeLink = $repoFindFileInput.attr('data-url-tree-link'); $repoFindFileTableBody.empty(); @@ -88,7 +85,7 @@ function filterRepoFiles(filter) { for (const r of filterResult) { const $row = $(tmplRow); const $a = $row.find('a'); - $a.attr('href', `${treeLink}/${escapePath(r.matchResult.join(''))}`); + $a.attr('href', `${treeLink}/${pathEscapeSegments(r.matchResult.join(''))}`); const $octiconFile = $(svg('octicon-file')).addClass('gt-mr-3'); $a.append($octiconFile); // if the target file path is "abc/xyz", to search "bx", then the matchResult is ['a', 'b', 'c/', 'x', 'yz'] diff --git a/web_src/js/features/repo-findfile.test.js b/web_src/js/features/repo-findfile.test.js index 50321853960b..a90b0bf0a2ca 100644 --- a/web_src/js/features/repo-findfile.test.js +++ b/web_src/js/features/repo-findfile.test.js @@ -1,5 +1,5 @@ import {describe, expect, test} from 'vitest'; -import {strSubMatch, calcMatchedWeight, filterRepoFilesWeighted, escapePath} from './repo-findfile.js'; +import {strSubMatch, calcMatchedWeight, filterRepoFilesWeighted} from './repo-findfile.js'; describe('Repo Find Files', () => { test('strSubMatch', () => { @@ -32,9 +32,4 @@ describe('Repo Find Files', () => { expect(res).toHaveLength(2); expect(res[0].matchResult).toEqual(['', 'word', '.txt']); }); - - test('escapePath', () => { - expect(escapePath('a/b/c')).toEqual('a/b/c'); - expect(escapePath('a/b/ c')).toEqual('a/b/%20c'); - }); }); diff --git a/web_src/js/features/repo-issue.js b/web_src/js/features/repo-issue.js index 41c9dd118f2f..a8a27c257209 100644 --- a/web_src/js/features/repo-issue.js +++ b/web_src/js/features/repo-issue.js @@ -230,7 +230,8 @@ export function initRepoIssueStatusButton() { const value = easyMDE?.value() || $(this).val(); $statusButton.text($statusButton.data(value.length === 0 ? 'status' : 'status-and-comment')); }); - $statusButton.on('click', () => { + $statusButton.on('click', (e) => { + e.preventDefault(); $('#status').val($statusButton.data('status-val')); $('#comment-form').trigger('submit'); }); diff --git a/web_src/js/features/repo-legacy.js b/web_src/js/features/repo-legacy.js index 70542ad883e9..4454b92cccdb 100644 --- a/web_src/js/features/repo-legacy.js +++ b/web_src/js/features/repo-legacy.js @@ -11,7 +11,7 @@ import { import {initUnicodeEscapeButton} from './repo-unicode-escape.js'; import {svg} from '../svg.js'; import {htmlEscape} from 'escape-goat'; -import {initRepoBranchTagDropdown} from '../components/RepoBranchTagDropdown.js'; +import {initRepoBranchTagSelector} from '../components/RepoBranchTagSelector.vue'; import { initRepoCloneLink, initRepoCommonBranchOrTagDropdown, initRepoCommonFilterSearchDropdown, initRepoCommonLanguageStats, @@ -412,7 +412,8 @@ async function onEditContent(event) { $saveButton.trigger('click'); }); - $editContentZone.find('.cancel.button').on('click', () => { + $editContentZone.find('.cancel.button').on('click', (e) => { + e.preventDefault(); showElem($renderContent); hideElem($editContentZone); if (dz) { @@ -485,7 +486,7 @@ export function initRepository() { // File list and commits if ($('.repository.file.list').length > 0 || $('.branch-dropdown').length > 0 || $('.repository.commits').length > 0 || $('.repository.release').length > 0) { - initRepoBranchTagDropdown('.choose.reference .ui.dropdown'); + initRepoBranchTagSelector('.js-branch-tag-selector'); } // Wiki diff --git a/web_src/js/index.js b/web_src/js/index.js index 6b4f4ef3ebe1..480661118bc6 100644 --- a/web_src/js/index.js +++ b/web_src/js/index.js @@ -2,9 +2,8 @@ import './bootstrap.js'; import $ from 'jquery'; -import {initVueEnv} from './components/VueComponentLoader.js'; import {initRepoActivityTopAuthorsChart} from './components/RepoActivityTopAuthors.vue'; -import {initDashboardRepoList} from './components/DashboardRepoList.js'; +import {initDashboardRepoList} from './components/DashboardRepoList.vue'; import {attachTribute} from './features/tribute.js'; import {initGlobalCopyToClipboardListener} from './features/clipboard.js'; @@ -100,7 +99,6 @@ $.fn.tab.settings.silent = true; // Disable the behavior of fomantic to toggle the checkbox when you press enter on a checkbox element. $.fn.checkbox.settings.enableEnterKey = false; -initVueEnv(); $(document).ready(() => { initGlobalCommon(); diff --git a/web_src/js/svg.js b/web_src/js/svg.js index 6476f16bfb3e..e431ca57e643 100644 --- a/web_src/js/svg.js +++ b/web_src/js/svg.js @@ -1,3 +1,4 @@ +import {h} from 'vue'; import octiconChevronDown from '../../public/img/svg/octicon-chevron-down.svg'; import octiconChevronRight from '../../public/img/svg/octicon-chevron-right.svg'; import octiconClock from '../../public/img/svg/octicon-clock.svg'; @@ -31,8 +32,19 @@ import octiconSkip from '../../public/img/svg/octicon-skip.svg'; import octiconMeter from '../../public/img/svg/octicon-meter.svg'; import octiconBlocked from '../../public/img/svg/octicon-blocked.svg'; import octiconSync from '../../public/img/svg/octicon-sync.svg'; +import octiconFilter from '../../public/img/svg/octicon-filter.svg'; +import octiconPlus from '../../public/img/svg/octicon-plus.svg'; +import octiconSearch from '../../public/img/svg/octicon-search.svg'; +import octiconArchive from '../../public/img/svg/octicon-archive.svg'; +import octiconStar from '../../public/img/svg/octicon-star.svg'; +import giteaDoubleChevronLeft from '../../public/img/svg/gitea-double-chevron-left.svg'; +import giteaDoubleChevronRight from '../../public/img/svg/gitea-double-chevron-right.svg'; +import octiconChevronLeft from '../../public/img/svg/octicon-chevron-left.svg'; +import octiconOrganization from '../../public/img/svg/octicon-organization.svg'; +import octiconTag from '../../public/img/svg/octicon-tag.svg'; +import octiconGitBranch from '../../public/img/svg/octicon-git-branch.svg'; -export const svgs = { +const svgs = { 'octicon-blocked': octiconBlocked, 'octicon-check-circle-fill': octiconCheckCircleFill, 'octicon-chevron-down': octiconChevronDown, @@ -66,14 +78,29 @@ export const svgs = { 'octicon-triangle-down': octiconTriangleDown, 'octicon-x': octiconX, 'octicon-x-circle-fill': octiconXCircleFill, + 'octicon-filter': octiconFilter, + 'octicon-plus': octiconPlus, + 'octicon-search': octiconSearch, + 'octicon-archive': octiconArchive, + 'octicon-star': octiconStar, + 'gitea-double-chevron-left': giteaDoubleChevronLeft, + 'gitea-double-chevron-right': giteaDoubleChevronRight, + 'octicon-chevron-left': octiconChevronLeft, + 'octicon-organization': octiconOrganization, + 'octicon-tag': octiconTag, + 'octicon-git-branch': octiconGitBranch, }; +// TODO: use a more general approach to access SVG icons. +// At the moment, developers must check, pick and fill the names manually, +// most of the SVG icons in assets couldn't be used directly. + const parser = new DOMParser(); const serializer = new XMLSerializer(); -// retrieve a HTML string for given SVG icon name, size and additional classes +// retrieve an HTML string for given SVG icon name, size and additional classes export function svg(name, size = 16, className = '') { - if (!(name in svgs)) return ''; + if (!(name in svgs)) throw new Error(`Unknown SVG icon: ${name}`); if (size === 16 && !className) return svgs[name]; const document = parser.parseFromString(svgs[name], 'image/svg+xml'); @@ -92,12 +119,7 @@ export const SvgIcon = { size: {type: Number, default: 16}, className: {type: String, default: ''}, }, - - computed: { - svg() { - return svg(this.name, this.size, this.className); - }, + render() { + return h('span', {innerHTML: svg(this.name, this.size, this.className)}); }, - - template: `` }; diff --git a/web_src/js/utils/url.js b/web_src/js/utils/url.js new file mode 100644 index 000000000000..a40737ca6f5a --- /dev/null +++ b/web_src/js/utils/url.js @@ -0,0 +1,3 @@ +export function pathEscapeSegments(s) { + return s.split('/').map(encodeURIComponent).join('/'); +} diff --git a/web_src/js/utils/url.test.js b/web_src/js/utils/url.test.js new file mode 100644 index 000000000000..ef2ffaa5f996 --- /dev/null +++ b/web_src/js/utils/url.test.js @@ -0,0 +1,7 @@ +import {expect, test} from 'vitest'; +import {pathEscapeSegments} from './url.js'; + +test('pathEscapeSegments', () => { + expect(pathEscapeSegments('a/b/c')).toEqual('a/b/c'); + expect(pathEscapeSegments('a/b/ c')).toEqual('a/b/%20c'); +}); diff --git a/web_src/less/_admin.less b/web_src/less/_admin.less deleted file mode 100644 index 26417d42eed6..000000000000 --- a/web_src/less/_admin.less +++ /dev/null @@ -1,115 +0,0 @@ -.admin { - &.hooks .list { - > .item { - &:not(:first-child) { - border-top: 1px solid var(--color-secondary); - padding: .25rem 1rem; - margin: 12px -1rem -1rem; - } - } - } - - .table.segment { - padding: 0; - font-size: 13px; - overflow-x: auto; - - &:not(.striped) { - thead { - th:last-child { - padding-right: 5px !important; - } - } - } - - th { - padding-top: 5px; - padding-bottom: 5px; - } - - &:not(.select) { - th, - td { - &:first-of-type { - padding-left: 15px !important; - } - } - } - - form tbody button[type='submit'] { - padding: 5px 8px; - } - - } - - .settings .button.adopt, - .settings .button.delete { - margin-top: -15px; - margin-bottom: -15px; - .label { - vertical-align: middle; - } - } - - &.user { - .email { - max-width: 200px; - } - } - - dl.admin-dl-horizontal { - padding: 20px; - margin: 0; - - dd { - margin-left: 275px; - @media @mediaSm { - margin-left: 5%; - } - } - - dt { - font-weight: 600; - float: left; - width: 285px; - clear: left; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - - @media @mediaSm { - width: auto; - margin-right: .5em; - } - } - } - - &.config { - #test-mail-btn { - margin-left: 5px; - } - } - - code, - pre { - white-space: pre-wrap; - word-wrap: break-word; - } - - #notice-table { - .notice-description { - @media @mediaSm { - max-width: 80vw; - } - @media @mediaMd { - max-width: 360px; - } - @media @mediaLg { - max-width: 510px; - } - @media @mediaXl { - max-width: 640px; - } - } - } -} diff --git a/web_src/less/_dashboard.less b/web_src/less/_dashboard.less deleted file mode 100644 index 4af55f2d2dee..000000000000 --- a/web_src/less/_dashboard.less +++ /dev/null @@ -1,198 +0,0 @@ -.dashboard { - &.feeds, - &.issues { - .context.user.menu { - z-index: 101; - min-width: 200px; - - .ui.header { - font-size: 1rem; - text-transform: none; - } - } - - .filter.menu { - width: initial; - - .item { - text-align: left; - display: flex; - align-items: center; - justify-content: space-between; - - .text { - height: 16px; - vertical-align: middle; - - &.truncate { - width: 75%; - } - } - - .floating.label { - top: 7px; - left: 90%; - width: 15%; - - @media @mediaSm { - top: 10px; - left: auto; - width: auto; - right: 13px; - } - } - } - - // Sort - .jump.item { - margin: 1px; - padding-right: 0; - } - - .menu { - max-height: 300px; - overflow-x: auto; - right: 0 !important; - left: auto !important; - } - - @media @mediaSm { - width: 100%; - } - } - - .right.stackable.menu > .item.active { - color: var(--color-red); - } - } - - .dashboard-repos, - .dashboard-orgs { - margin: 0 1px; /* Accommodate for Semantic's 1px hacks on .attached elements */ - } - - .dashboard-navbar { - width: 100vw; - padding-left: .5rem; - padding-right: .5rem; - .org-visibility .label { - margin-left: 5px; - } - - .ui.dropdown { - max-width: 100%; - - @media @mediaSm { - > .menu { - position: static; - } - } - } - } -} - -&.feeds { - .news { - li { - display: flex; - align-items: baseline; - margin-top: .5rem; - margin-bottom: .5rem; - - img { - align-self: flex-start; - } - } - li > * + * { - margin-left: .35rem; - } - - > .ui.grid { - margin-left: auto; - margin-right: auto; - } - - .left .ui.avatar { - margin-top: 13px; - } - - .time-since { - font-size: 13px; - } - - .issue.title { - width: 80%; - margin: 0 0 1em; - } - - .push.news .content ul { - line-height: 18px; - font-size: 13px; - list-style: none; - padding-left: 10px; - - .text.truncate { - width: 80%; - } - } - - .commit-id { - font-family: var(--fonts-monospace); - } - - code { - padding: 2px 4px; - border-radius: 3px; - background-color: var(--color-markup-code-block); - word-break: break-all; - } - - &:last-of-type .divider { - display: none !important; - } - } - - .list { - ul { - list-style: none; - margin: 0; - padding-left: 0; - - li { - &:not(:last-child) { - border-bottom: 1px solid var(--color-secondary); - } - - &.private { - background-color: var(--color-box-body-highlight); - } - - .repo-list-link { - padding: 6px 1em; - display: block; - - .svg { - color: var(--color-text-light-2); - } - - .star-num { - font-size: 12px; - } - } - } - } - - #privateFilterCheckbox .svg { - color: var(--color-grey); - margin-right: .25rem; - } - - .repo-owner-name-list .item-name { - min-width: 0; - } - - .repo-owner-name-list .item-name svg { - min-width: 16px; - } - } -} diff --git a/web_src/less/_explore.less b/web_src/less/_explore.less deleted file mode 100644 index 5caf21d417d2..000000000000 --- a/web_src/less/_explore.less +++ /dev/null @@ -1,93 +0,0 @@ -.explore { - .navbar { - justify-content: center; - margin-bottom: 15px !important; - background-color: var(--color-navbar) !important; - border-width: 1px !important; - - .svg { - width: 16px; - text-align: center; - margin-right: 5px; - } - } -} - -.ui.repository.list { - .item { - padding-bottom: 1.5rem; - - &:not(:first-child) { - border-top: 1px solid var(--color-secondary); - padding-top: 1.5rem; - } - - .ui.header { - font-size: 1.5rem; - margin-bottom: .5rem; - - .name { - word-break: break-all; - } - - .metas { - font-size: 14px; - } - } - - .time { - font-size: 12px; - } - - .ui.tags { - margin-bottom: .5rem; - } - } -} - -.ui.repository.branches { - .info { - font-size: 12px; - color: var(--color-text-light); - display: flex; - white-space: pre; - .commit-message { - max-width: 72em; - overflow: hidden; - text-overflow: ellipsis; - } - } - .overflow-visible { - overflow: visible; - } - /* fix alignment of PR popup in branches table */ - table .ui.popup { - text-align: left; - } -} - -.ui.user.list { - .item { - padding-bottom: 25px; - display: flex; - - &:not(:first-child) { - border-top: 1px solid var(--color-secondary); - padding-top: 25px; - } - - img.ui.avatar { - width: 40px; - height: 40px; - margin-right: 10px; - } - - .description { - margin-top: 5px; - - .svg:not(:first-child) { - margin-left: 5px; - } - } - } -} diff --git a/web_src/less/_font_i18n.less b/web_src/less/_font_i18n.less deleted file mode 100644 index 5dae8f2aa588..000000000000 --- a/web_src/less/_font_i18n.less +++ /dev/null @@ -1,130 +0,0 @@ -/* font i18n */ -:root { - /* customizable localized variables */ - :lang(ja) { - --fonts-override: var(--fonts-default-override-ja); - } - :lang(zh-CN) { - --fonts-override: var(--fonts-default-override-zh-cn); - } - :lang(zh-TW) { - --fonts-override: var(--fonts-default-override-zh-tw); - } - :lang(zh-HK) { - --fonts-override: var(--fonts-default-override-zh-hk); - } - :lang(ko) { - --fonts-override: var(--fonts-default-override-ko); - } -} - -[lang] { - font-family: var(--fonts-regular); -} - -each(@fonts, { - @weights: .gen-weights-all(@value); - @locale: replace(@key, "@", "-"); - .font-face-cjk(~"system-ui@{locale}", @weights[@light], 300); - .font-face-cjk(~"system-ui@{locale}", @weights[@regular], 400); - .font-face-cjk(~"system-ui@{locale}", @weights[@medium], 500); - .font-face-cjk(~"system-ui@{locale}", @weights[@bold], 700); - /* Safari on macOS/iOS */ - @font-face { - font-family: ~"system-ui@{locale}"; - src: local("HelveticaNeue"); - unicode-range: U+A0; - } - /* Other browsers on macOS/iOS */ - @supports not (-webkit-hyphens:none) { - @font-face { - font-family: ~"system-ui@{locale}"; - src: local("HelveticaNeue"); - unicode-range: U+20; - } - } - :root { - /* Special handling for Firefox on Windows/Linux */ - @supports (-moz-appearance:none) { - --fonts-default-override@{locale}: ~"var(--fonts-proportional), system-ui@{locale}"; - } - --fonts-default-override@{locale}: ~"system-ui@{locale}, var(--fonts-proportional)"; - } -}); - -@fonts: { - @ja: - "HiraKakuProN-:{W3,W6}", "Hiragino Kaku Gothic ProN :{W3,W6}", "HiraginoSans-:{W2,W4,W5,W6}", - .shs("JP")[], .shs("J")[], .noto("JP")[], .shs("")[], - /* https://acetaminophen.hatenablog.com/entry/2016/02/15/225009 */ - "Yu Gothic :{Regular,Medium,Bold}", "YuGothic :{Regular,Medium,Bold}", - "Droid Sans Japanese:{}", "Meiryo:{, Bold}", "MS PGothic:{}"; - @zh-cn: - .pingfang("SC")[], - .shs("CN")[], .shs("SC")[], .noto("SC")[], - "HiraginoSansGB-:{W3,W6}", "Hiragino Sans GB :{W3,W6}", - "Microsoft YaHei:{ Light,, Bold}", "Heiti SC :{Light,Medium}", "SimHei:{}"; - @zh-tw: - .pingfang("TC")[], - .shs("TW")[], .shs("TC")[], .noto("TC")[], - "HiraginoSansTC-:{W3,W6}", "Hiragino Sans TC :{W3,W6}", - "Microsoft JhengHei:{ Light,, Bold}", "Heiti TC :{Light,Medium}", "PMingLiU:{}"; - @zh-hk: - .pingfang("HK")[], - .shs("HK")[], .shs("HC")[], .noto("HK")[], .shs("TC")[], .noto("TC")[], - "HiraginoSansTC-:{W3,W6}", "Hiragino Sans TC :{W3,W6}", - "Microsoft JhengHei:{ Light,, Bold}", "Heiti TC :{Light,Medium}", "PMingLiU_HKSCS:{}", "PMingLiU:{}"; - @ko: - "AppleSDGothicNeo-:{Light,Regular,Medium,SemiBold}", - .shs("KR")[], .shs("K")[], .noto("KR")[], - "NanumBarunGothic:{ Light,, Bold}", - "Malgun Gothic:{ Semilight,, Bold}", "Nanum Gothic:{, Bold}", "Dotum:{}"; -} - -.noto(@suffix) { @value: "Noto Sans CJK @{suffix} ", "NotoSansCJK@{suffix}-"; } -.shs(@suffix) { @value: replace("Source Han Sans @{suffix} ", " ", " "), "SourceHanSans@{suffix}-"; } -.pingfang(@suffix) { @value: "PingFang@{suffix}-:{Light,Regular,Medium,Semibold}"; } -.font-face-cjk(@family, @src, @weight) { - @font-face { - font-family: @family; - src: @src; - font-weight: @weight; - unicode-range: U+11??, U+2E80-4DBF, U+4E00-9FFF, U+A960-A97F, U+AC00-D7FF, U+F900-FAFF, U+FE00-FE6F, U+FF00-FFEF, U+1F2??, U+2????; - } -} - -.gen-weights(@family) when (isstring(@family)) { - @family-str: replace(@family, ":\{.*\}$", ""); - // apply standard style names if none is given - // should the font have no styles, use :{}, as in "SimHei:{}" - @weights-str: if(@family = @family-str, "Light,Regular,Medium,Bold", replace(@family, ".*:\{(.*)\}$", "$1")); - @lightest: replace(@weights-str, ",.*", ""); - @boldest: replace(@weights-str, ".*,", ""); - @2ndboldest: replace(@weights-str, "(?:.*,|)([^,]*),.*$", "$1"); - @2ndlightest: if(@2ndboldest = @lightest, @lightest, replace(@weights-str, "^.*?,([^,]*).*", "$1")); - - @light: local("@{family-str}@{lightest}"); - @regular: local("@{family-str}@{2ndlightest}"); - @medium: local("@{family-str}@{2ndboldest}"); - @bold: local("@{family-str}@{boldest}"); -} -.gen-weights(@family) when not (isstring(@family)) { - .gen-weights-all(@family); -} -.gen-weights(@family, @last) { - @this: .gen-weights(@family); - - @light: @last[@light], @this[@light]; - @regular: @last[@regular], @this[@regular]; - @medium: @last[@medium], @this[@medium]; - @bold: @last[@bold], @this[@bold]; -} -.gen-weights-all(@family) when not (isstring(@family)) { - .gen-weights-all(@family, length(@family)); -} -.gen-weights-all(@family, 1) when not (isstring(@family)) { - .gen-weights(extract(@family, 1)); -} -.gen-weights-all(@family, @ctr) when not (isstring(@family)) and (@ctr > 1) and (@ctr <= length(@family)) { - .gen-weights(extract(@family, @ctr), .gen-weights-all(@family, @ctr - 1)); -} diff --git a/web_src/less/_form.less b/web_src/less/_form.less deleted file mode 100644 index 1a1c1678f8b3..000000000000 --- a/web_src/less/_form.less +++ /dev/null @@ -1,378 +0,0 @@ -input, -textarea, -.ui.input > input, -.ui.form input:not([type]), -.ui.form select, -.ui.form textarea, -.ui.form input[type="date"], -.ui.form input[type="datetime-local"], -.ui.form input[type="email"], -.ui.form input[type="file"], -.ui.form input[type="number"], -.ui.form input[type="password"], -.ui.form input[type="search"], -.ui.form input[type="tel"], -.ui.form input[type="text"], -.ui.form input[type="time"], -.ui.form input[type="url"], -.ui.selection.dropdown, -.ui.checkbox label::before, -.ui.checkbox input:checked ~ label::before, -.ui.checkbox input:not([type="radio"]):indeterminate ~ label::before { - background: var(--color-input-background); - border-color: var(--color-input-border); - color: var(--color-input-text); -} - -input:hover, -textarea:hover, -.ui.input input:hover, -.ui.form input:not([type]):hover, -.ui.form select:hover, -.ui.form textarea:hover, -.ui.form input[type="date"]:hover, -.ui.form input[type="datetime-local"]:hover, -.ui.form input[type="email"]:hover, -.ui.form input[type="file"]:hover, -.ui.form input[type="number"]:hover, -.ui.form input[type="password"]:hover, -.ui.form input[type="search"]:hover, -.ui.form input[type="tel"]:hover, -.ui.form input[type="text"]:hover, -.ui.form input[type="time"]:hover, -.ui.form input[type="url"]:hover, -.ui.selection.dropdown:hover, -.ui.checkbox label:hover::before, -.ui.checkbox label:active::before, -.ui.radio.checkbox label::after, -.ui.radio.checkbox input:focus ~ label::before, -.ui.radio.checkbox input:checked ~ label::before { - background: var(--color-input-background); - border-color: var(--color-input-border-hover); - color: var(--color-input-text); -} - -input:focus, -textarea:focus, -.ui.input input:focus, -.ui.form input:not([type]):focus, -.ui.form select:focus, -.ui.form textarea:focus, -.ui.form input[type="date"]:focus, -.ui.form input[type="datetime-local"]:focus, -.ui.form input[type="email"]:focus, -.ui.form input[type="file"]:focus, -.ui.form input[type="number"]:focus, -.ui.form input[type="password"]:focus, -.ui.form input[type="search"]:focus, -.ui.form input[type="tel"]:focus, -.ui.form input[type="text"]:focus, -.ui.form input[type="time"]:focus, -.ui.form input[type="url"]:focus, -.ui.selection.dropdown:focus, -.ui.checkbox input:focus ~ label::before, -.ui.checkbox input:not([type="radio"]):indeterminate:focus ~ label::before, -.ui.checkbox input:checked:focus ~ label::before, -.ui.radio.checkbox input:focus:checked ~ label::before { - background: var(--color-input-background); - border-color: var(--color-primary); - color: var(--color-input-text); -} - -.ui.form .field > label, -.ui.form .inline.fields > label, -.ui.form .inline.fields .field > label, -.ui.form .inline.fields .field > p, -.ui.form .inline.field > label, -.ui.form .inline.field > p, -.ui.checkbox label, -.ui.checkbox + label, -.ui.checkbox label:hover, -.ui.checkbox + label:hover, -.ui.checkbox input:focus ~ label, -.ui.checkbox input:active ~ label { - color: var(--color-text); -} - -.ui.input, -.ui.checkbox input:focus ~ label::after, -.ui.checkbox input:checked ~ label::after, -.ui.checkbox label:active::after, -.ui.checkbox input:not([type="radio"]):indeterminate ~ label::after, -.ui.checkbox input:not([type="radio"]):indeterminate:focus ~ label::after, -.ui.checkbox input:checked:focus ~ label::after, -.ui.disabled.checkbox label, -.ui.checkbox input[disabled] ~ label { - color: var(--color-input-text); -} - -.ui.radio.checkbox input:focus ~ label::after, -.ui.radio.checkbox input:checked ~ label::after, -.ui.radio.checkbox input:focus:checked ~ label::after { - background: var(--color-input-text); -} - -.ui.toggle.checkbox label::before { - background: var(--color-input-toggle-background); -} - -.ui.toggle.checkbox label, -.ui.toggle.checkbox input:checked ~ label, -.ui.toggle.checkbox input:focus:checked ~ label { - color: var(--color-text) !important; -} - -.ui.toggle.checkbox input:checked ~ label::before, -.ui.toggle.checkbox input:focus:checked ~ label::before { - background: var(--color-primary) !important; -} - -/* match */ -.ui.form select { - padding: .67857143em 1em; -} - -.form { - .help { - color: var(--color-secondary-dark-5); - padding-bottom: .6em; - display: inline-block; - } -} - -@create-page-form-input-padding: 250px !important; -#create-page-form { - form { - margin: auto; - - .ui.message { - text-align: center; - } - - @media @mediaMdAndUp { - width: 800px !important; - - .header { - padding-left: @create-page-form-input-padding+30px; - } - - .inline.field > label, - .inline.field.captcha-field > span { - text-align: right; - width: @create-page-form-input-padding; - word-wrap: break-word; - } - - .help { - margin-left: @create-page-form-input-padding+15px; - } - - .optional .title { - margin-left: @create-page-form-input-padding; - } - - .inline.field > input, - .inline.field > textarea { - width: 50%; - } - } - - @media @mediaSm { - .optional .title { - margin-left: 15px; - } - - .inline.field > label { - display: block; - } - } - } -} - -.signin { - .oauth2 { - div { - display: inline-block; - - p { - margin: 10px 5px 0 0; - float: left; - } - } - - a { - margin-right: 3px; - - &:last-child { - margin-right: 0; - } - } - - img { - width: 32px; - height: 32px; - - &.openidConnect { - width: auto; - } - } - } -} - -@media @mediaMdAndUp { - .g-recaptcha-style, - .h-captcha-style { - margin: 0 auto !important; - width: 304px; - padding-left: 30px; - - iframe { - border-radius: 5px !important; - width: 302px !important; - height: 76px !important; - } - } -} - -@media (max-height: 575px) { - #rc-imageselect, - .g-recaptcha-style, - .h-captcha-style { - transform: scale(.77); - transform-origin: 0 0; - } -} - -.user.activate, -.user.forgot.password, -.user.reset.password, -.user.link-account, -.user.signin, -.user.signup { - @input-padding: 200px; - #create-page-form(); - - form { - width: 700px !important; - - .header { - padding-left: 0 !important; - text-align: center; - } - - .inline.field > label { - width: @input-padding; - } - - .inline.field > label, - input { - @media @mediaSm { - width: 100% !important; - } - } - - input[type="number"] { - -moz-appearance: textfield; - } - - input::-webkit-outer-spin-button, - input::-webkit-inner-spin-button { - -webkit-appearance: none; - margin: 0; - } - } -} - -.user.signin.webauthn-prompt { - margin-top: 15px; -} - -.repository { - &.new.repo, - &.new.migrate, - &.new.fork { - #create-page-form(); - - form { - .dropdown .text { - margin-right: 0 !important; - } - - .header { - padding-left: 0 !important; - text-align: center; - } - - .selection.dropdown { - vertical-align: middle; - width: 50% !important; - } - - @media @mediaSm { - label, - input, - .selection.dropdown { - width: 100% !important; - } - - .field button, - .field a { - margin-bottom: 1em; - width: 100%; - } - } - } - } - - &.new.repo { - .ui.form { - @media @mediaMdAndUp { - #auto-init { - margin-left: @create-page-form-input-padding+15px; - } - } - - .selection.dropdown:not(.owner) { - width: 50% !important; - - @media @mediaSm { - width: 100% !important; - } - } - } - } -} - -.new.webhook { - form { - .help { - margin-left: 25px; - } - } - - .events.fields { - .column { - padding-left: 40px; - } - } -} - -.githook { - textarea { - font-family: var(--fonts-monospace); - } -} - -.new.org .ui.form { - @media @mediaSm { - .field button, - .field a { - margin-bottom: 1em; - width: 100%; - } - - .field input { - width: 100% !important; - } - } -} diff --git a/web_src/less/_home.less b/web_src/less/_home.less deleted file mode 100644 index fb31bedfa9fd..000000000000 --- a/web_src/less/_home.less +++ /dev/null @@ -1,61 +0,0 @@ -.home { - .logo { - max-width: 220px; - } - - .hero { - @media @mediaSm { - h1 { - font-size: 3.5em; - } - - h2 { - font-size: 2em; - } - } - - @media @mediaMdAndUp { - h1 { - font-size: 5.5em; - } - - h2 { - font-size: 3em; - } - } - - .svg { - color: var(--color-green); - height: 40px; - width: 50px; - vertical-align: bottom; - } - - &.header { - font-size: 20px; - } - } - - p.large { - font-size: 16px; - } - - .stackable { - padding-top: 30px; - } - - a { - color: var(--color-green); - } -} - -footer { - .ui.container .left, - .ui.container .right { - @media (max-width: 880px) { - display: block; - text-align: center; - float: none; - } - } -} diff --git a/web_src/less/_install.less b/web_src/less/_install.less deleted file mode 100644 index 026a76fbbad4..000000000000 --- a/web_src/less/_install.less +++ /dev/null @@ -1,72 +0,0 @@ -.page-content.install { - padding-top: 45px; - - form.ui.form { - @input-padding: 30%; - - .inline.field > label { - text-align: right; - width: @input-padding; - padding-right: 10px; - margin-right: 0; - } - - .inline.field > .ui.checkbox:first-child { - margin-left: @input-padding; - padding-left: 5px; - label { - width: auto; - } - } - - .title { - margin-left: @input-padding; - padding-left: 5px; - } - - input { - width: 60%; - } - - details.optional.field { - &[open] { - border-bottom: 1px solid var(--color-secondary); - padding-bottom: 10px; - - summary { - margin-bottom: 10px; - } - } - - * { - box-sizing: border-box; - } - } - - .field { - text-align: left; - - .help { - margin-left: @input-padding; - padding-left: 5px; - width: 60%; - } - - } - } - - .ui { - .reinstall-message { - width: 70%; - margin: 20px auto; - color: var(--color-red); - text-align: left; - font-weight: bold; - } - .reinstall-confirm { - width: 70%; - text-align: left; - margin: 10px auto; - } - } -} diff --git a/web_src/less/_organization.less b/web_src/less/_organization.less deleted file mode 100644 index ae406f021a29..000000000000 --- a/web_src/less/_organization.less +++ /dev/null @@ -1,200 +0,0 @@ -.organization { - .head { - .ui.header { - .text { - vertical-align: middle; - font-size: 1.6rem; - margin-left: 15px; - } - .org-visibility .label { - margin-left: 5px; - margin-top: 5px; - } - .ui.right { - margin-top: 5px; - } - } - } - - .ui.secondary.stackable.pointing.menu { - flex-wrap: wrap; - margin-top: 5px; - margin-bottom: 10px; - } - - &.new.org { - #create-page-form(); - - form { - .header { - padding-left: 0 !important; - text-align: center; - } - } - } - - &.options { - input { - min-width: 300px; - } - } - - &.profile { - .org-avatar { - width: 100px; - height: 100px; - margin-right: 15px; - } - - #org-info { - overflow-wrap: anywhere; - - .ui.header { - display: flex; - align-items: center; - font-size: 36px; - margin-bottom: 0; - .org-visibility .label { - margin-left: 5px; - margin-top: 2px; - } - } - - .desc { - font-size: 16px; - margin-bottom: 10px; - } - - .meta { - .item { - display: inline-block; - margin-right: 10px; - - .icon { - margin-right: 5px; - } - } - } - } - - .ui.top.header { - .ui.right { - margin-top: 0; - } - } - - .teams { - .item { - padding: 10px 15px; - } - } - } - - &.teams, - &.profile { - .members { - a:hover { - text-decoration: none; - } - - .ui.avatar { - width: 48px; - height: 48px; - margin-right: 5px; - margin-bottom: 5px; - } - } - } - - &.invite { - #invite-box { - margin: 50px auto auto; - width: 500px !important; - - #search-user-box { - input { - margin-left: 0; - width: 300px; - } - } - - .ui.button { - margin-left: 5px; - margin-top: -3px; - } - } - - .ui.avatar { - width: 100%; - height: 100%; - } - } - - &.members { - .list { - .item { - margin-left: 0; - margin-right: 0; - border-bottom: 1px solid var(--color-secondary); - - .ui.avatar { - width: 48px; - height: auto; - margin-right: 1rem; - align-self: flex-start; - } - - .meta { - line-height: 24px; - word-break: break-word; - min-width: 2em; - } - } - } - } - - &.teams { - .detail { - .item { - padding: 10px 15px; - - &:not(:last-child) { - border-bottom: 1px solid var(--color-secondary); - } - } - } - - .repositories, - .members { - .item { - padding: 10px 20px; - line-height: 32px; - - &:not(:last-child) { - border-bottom: 1px solid var(--color-secondary); - } - - .button { - padding: 9px 10px; - } - } - } - - #add-repo-form, - #repo-multiple-form, - #add-member-form { - input { - margin-left: 0; - } - - .ui.button { - margin-left: 5px; - margin-top: -3px; - } - } - - #repo-top-segment { - height: 60px; - } - } -} diff --git a/web_src/less/_package.less b/web_src/less/_package.less deleted file mode 100644 index f4a07a188996..000000000000 --- a/web_src/less/_package.less +++ /dev/null @@ -1,9 +0,0 @@ -.container-labels { - td:nth-child(1) { - vertical-align: top; - } - - td:nth-child(2) { - overflow-wrap: anywhere; - } -} diff --git a/web_src/less/_repository.less b/web_src/less/_repository.less deleted file mode 100644 index 0069a31cecb4..000000000000 --- a/web_src/less/_repository.less +++ /dev/null @@ -1,3611 +0,0 @@ -.repository { - .repo-header { - .ui.compact.menu { - margin-left: 1rem; - } - - .ui.header { - margin-top: 0; - } - - .fork-flag { - font-size: 12px; - margin-top: 2px; - } - - .repo-buttons .svg { - margin: 0 .42857143em 0 -.21428571em; - } - - .button { - margin-top: 2px; - margin-bottom: 2px; - } - } - - .tabs { - .navbar { - justify-content: initial; - } - } - - .navbar { - display: flex; - justify-content: space-between; - - .ui.label { - margin-left: 7px; - padding: 3px 5px; - } - } - - .owner.dropdown { - min-width: 40% !important; - } - - .unicode-escaped .escaped-code-point { - &[data-escaped]::before { - visibility: visible; - content: attr(data-escaped); - font-family: var(--fonts-monospace); - color: var(--color-red); - } - - .char { - display: none; - } - } - - .broken-code-point { - font-family: var(--fonts-monospace); - color: var(--color-blue); - } - - .unicode-escaped .ambiguous-code-point { - border: 1px var(--color-yellow) solid; - } - - .metas { - .menu { - overflow-x: auto; - max-height: 500px; - } - - .ui.list { - &.assignees .icon { - line-height: 2em; - } - - &.assignees .teamavatar { - margin-top: .125rem; - margin-left: 6.75px; - margin-right: 8.75px; - } - - .dependency { - padding: 0; - white-space: nowrap; - } - - .title { - max-width: 200px; - overflow: hidden; - text-overflow: ellipsis; - } - - @media @mediaLgAndDown { - .title { - max-width: 150px; - } - } - - @media (max-width: 1000px) { - .title { - max-width: 100px; - } - } - } - - #deadlineForm input { - width: 12.8rem; - border-radius: 4px 0 0 4px; - border-right: 0; - white-space: nowrap; - } - } - - .header-wrapper { - background-color: var(--color-navbar); - - .ui.tabs.divider { - border-bottom: 0; - } - - .ui.tabular .svg { - margin-right: 5px; - } - } - - .filter.menu { - &.labels { - .label-filter .menu .info { - display: inline-block; - padding: .5rem .25rem; - border-bottom: 1px solid var(--color-secondary); - font-size: 12px; - width: 100%; - white-space: nowrap; - text-align: center; - - code { - border: 1px solid var(--color-secondary); - border-radius: 3px; - padding: 1px 2px; - font-size: 11px; - } - } - } - - .menu { - max-height: 500px; - overflow-x: auto; - right: 0 !important; - left: auto !important; - } - } - - .select-label { - .desc { - padding-left: 23px; - } - } - - .ui.tabs { - &.container { - margin-top: 14px; - margin-bottom: 0; - - .ui.menu { - border-bottom: 0; - } - } - - &.divider { - margin-top: 0; - margin-bottom: 20px; - } - } - - #clone-panel { - #repo-clone-url { - width: 320px; - - @media @mediaMd { - width: 200px; - } - @media @mediaSm { - width: 200px; - } - } - - #repo-clone-https, - #repo-clone-ssh { - border-right: none; - } - - #more-btn { - border-left: none; - } - - button:first-of-type { - border-radius: var(--border-radius) 0 0 var(--border-radius) !important; - } - - button:last-of-type { - border-radius: 0 var(--border-radius) var(--border-radius) 0 !important; - } - - .dropdown .menu { - right: 0 !important; - left: auto !important; - } - } - - &.file.list { - .repo-description { - display: flex; - justify-content: space-between; - align-items: center; - } - - #repo-desc { - font-size: 1.2em; - } - - .choose.reference { - .header .icon { - font-size: 1.4em; - } - } - - .repo-path { - - .section, - .divider { - display: inline; - } - } - - #repo-files-table { - table-layout: fixed; - - thead { - th { - padding-top: 8px; - padding-bottom: 5px; - font-weight: normal; - } - - .ui.avatar { - margin-bottom: 5px; - } - } - - tbody { - .svg { - margin-left: 3px; - margin-right: 5px; - - &.octicon-reply { - margin-right: 10px; - } - - &.octicon-file-directory-fill, - &.octicon-file-submodule { - color: var(--color-primary); - } - - &.octicon-file, - &.octicon-file-symlink-file { - color: var(--color-secondary-dark-7); - } - } - } - - td { - padding-top: 0; - padding-bottom: 0; - overflow: initial; - - &.name { - @media @mediaXl { - max-width: 150px; - } - @media @mediaLg { - max-width: 200px; - } - @media @mediaMd { - max-width: 300px; - } - width: 33%; - - max-width: calc(100vw - 140px); - } - - &.message { - color: var(--color-text-light-1); - - @media @mediaXl { - max-width: 400px; - } - @media @mediaLg { - max-width: 350px; - } - @media @mediaMd { - max-width: 250px; - } - width: 66%; - } - - &.age { - width: 120px; - color: var(--color-text-light-1); - } - - .truncate { - display: inline-block; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - width: 100%; - padding-top: 8px; - padding-bottom: 8px; - } - - a { - padding-top: 8px; - padding-bottom: 8px; - } - - .at { - margin-left: 3px; - margin-right: 3px; - } - - > * { - vertical-align: middle; - } - } - - td.message .isSigned { - cursor: default; - } - - tr:last-of-type { - td:first-child { - border-bottom-left-radius: var(--border-radius); - } - - td:last-child { - border-bottom-right-radius: var(--border-radius); - } - } - - tr:hover { - background-color: var(--color-hover); - } - - tr.has-parent a { - display: inline-block; - padding-top: 8px; - padding-bottom: 8px; - width: calc(100% - 1.25rem); - } - } - - .non-diff-file-content { - .header { - .icon { - font-size: 1em; - } - - .small.icon { - font-size: .75em; - } - - .tiny.icon { - font-size: .5em; - } - - .file-actions { - .btn-octicon { - line-height: 1; - padding: 10px 8px; - vertical-align: middle; - color: var(--color-text); - } - - .btn-octicon:hover { - color: var(--color-primary); - } - - .btn-octicon-danger:hover { - color: var(--color-red); - } - - .btn-octicon.disabled { - color: inherit; - opacity: var(--opacity-disabled); - cursor: default; - } - } - } - - .view-raw { - padding: 5px; - - > * { - max-width: 100%; - border: 1px solid var(--color-secondary); - } - - img { - margin: 1rem 0; - border-radius: 0; - object-fit: contain; - } - - img[src$='.svg' i] { - max-height: 600px !important; - max-width: 600px !important; - } - } - - .plain-text { - padding: 1em 2em; - - pre { - word-break: break-word; - white-space: pre-wrap; - } - } - - .csv { - overflow-x: auto; - padding: 0 !important; - } - - pre { - overflow: auto; - } - - .asciicast { - padding: 5px !important; - } - } - - .sidebar { - padding-left: 0; - - .svg { - width: 16px; - } - } - } - - &.file.editor { - .treepath { - width: 100%; - - input { - vertical-align: middle; - box-shadow: rgba(0, 0, 0, .0745098) 0 1px 2px inset; - width: inherit; - padding: 7px 8px; - margin-right: 5px; - } - } - - .tabular.menu { - .svg { - margin-right: 5px; - } - } - - .commit-form-wrapper { - padding-left: 64px; - - .commit-avatar { - float: left; - margin-left: -64px; - width: 3em; - height: auto; - } - - .commit-form { - position: relative; - padding: 15px; - margin-bottom: 10px; - border: 1px solid var(--color-secondary); - background: var(--color-box-body); - border-radius: 3px; - #avatar-arrow(); - - &::after { - border-right-color: var(--color-box-body); - } - - .quick-pull-choice { - .branch-name { - display: inline-block; - padding: 2px 4px; - font: 12px var(--fonts-monospace); - color: var(--color-text); - background: var(--color-secondary); - border-radius: 3px; - margin: 0 2px; - } - - .new-branch-name-input { - position: relative; - margin-left: 25px; - - input { - width: 240px !important; - padding-left: 26px !important; - } - } - - .octicon-git-branch { - position: absolute; - top: 9px; - left: 10px; - color: var(--color-grey); - } - } - } - } - } - - &.options { - #interval { - width: 100px !important; - min-width: 100px; - } - - .danger { - .item { - padding: 20px 15px; - } - - .ui.divider { - margin: 0; - } - } - } - - @comment-avatar-width: 3em; - - .comment textarea { - max-height: none !important; - } - - &.new.issue { - .comment.form { - .comment { - .avatar { - width: @comment-avatar-width; - } - } - - .content { - margin-left: 4em; - #avatar-arrow(); - - &::after { - border-right-color: var(--color-box-body); - } - - .markup { - font-size: 14px; - } - } - - .metas { - min-width: 220px; - - .filter.menu { - max-height: 500px; - overflow-x: auto; - } - } - - } - } - - &.view.issue { - .instruct-toggle { - display: inline-block; - } - - .title { - padding-bottom: 0 !important; - - .issue-title { - margin-bottom: .5rem; - - &.edit-active { - display: flex; - align-items: center; - - h1 { - display: flex; - width: 100%; - } - - @media @mediaSm { - flex-direction: column; - - h1 { - margin-right: 0; - margin-bottom: 1rem; - padding-right: 0; - - .ui.input input { - width: calc(100% - 2rem); - } - } - - .edit-buttons { - padding-bottom: 1rem; - width: 100%; - - .button { - width: 100%; - margin-right: .5rem; - - &:last-child { - margin-right: 0; - } - } - } - } - } - - h1 { - font-weight: 300; - font-size: 2.3rem; - margin: 0; - padding-right: .5rem; - - .ui.input { - font-size: .5em; - width: 100%; - - input { - font-size: 1.5em; - padding: 6px 1rem; - } - } - } - - .edit-button { - float: right; - padding-left: 1rem; - } - - .edit-buttons { - display: flex; - } - - .index { - color: var(--color-text-light-2); - } - - .label { - margin-right: 10px; - } - - .edit-zone { - margin-top: 10px; - } - } - } - - .pull-desc { - code { - color: var(--color-primary); - } - a[data-clipboard-text] { - cursor: pointer; - svg { - vertical-align: middle; - position: relative; - top: -2px; - right: 1px; - } - } - } - - .pull { - &.tabular.menu { - margin-bottom: 1rem; - - .svg { - margin-right: 5px; - } - } - - .merge.box { - .avatar { - margin-left: 10px; - margin-top: 10px; - } - - .branch-update.grid { - .row { - padding-bottom: 1rem; - - .icon { - margin-top: 1.1rem; - } - } - } - } - - .review-item { - display: flex; - justify-content: space-between; - align-items: center; - - .review-item-left, - .review-item-right { - display: flex; - align-items: center; - } - - .text { - margin: .3em 0 .5em .5em; - } - - .type-icon { - align-self: flex-start; - margin-right: 1em; - - i { - line-height: 1.8em; - } - } - - .divider { - margin: .5rem 0; - } - - .review-content { - padding: 1em 0 1em 3.8em; - } - } - } - - .comment-list { - &:not(.prevent-before-timeline)::before { - display: block; - content: ""; - position: absolute; - margin-top: 12px; - margin-bottom: 14px; - top: 0; - bottom: 0; - left: 96px; - width: 2px; - background-color: var(--color-timeline); - z-index: -1; - } - - .timeline { - position: relative; - display: block; - margin-left: 40px; - padding-left: 16px; - - &::before { //ciara - display: block; - content: ""; - position: absolute; - margin-top: 12px; - margin-bottom: 14px; - top: 0; - bottom: 0; - left: 30px; - width: 2px; - background-color: var(--color-timeline); - z-index: -1; - } - } - - .timeline-item, - .timeline-item-group { - padding: 12px 0; - } - - .timeline-item-group { - .timeline-item { - padding-top: 8px; - padding-bottom: 8px; - } - } - - .timeline-item { - margin-left: 16px; - position: relative; - - .timeline-avatar { - position: absolute; - left: -68px; - - img { - width: 40px !important; - height: 40px !important; - } - } - - /* Don't show the mobile oriented avatar ".inline-timeline-avatar" on desktop. Desktop uses the avatar with class ".timeline-avatar" */ - .inline-timeline-avatar { - display: none; - } - - img.avatar, - .avatar img { - width: 20px; - height: 20px; - vertical-align: middle; - } - - &:first-child:not(.commit) { - padding-top: 0 !important; - } - - &:last-child:not(.commit) { - padding-bottom: 0 !important; - } - - .badge.badge-commit { - border-color: transparent; - background: radial-gradient(var(--color-body) 40%, transparent 40%) no-repeat; - } - - .badge { - width: 34px; - height: 34px; - background-color: var(--color-timeline); - border-radius: 50%; - display: flex; - float: left; - margin-left: -33px; - margin-right: 8px; - color: var(--color-text); - align-items: center; - justify-content: center; - - .svg { - width: 22px; - height: 22px; - padding: 3px; - - &.octicon-comment { - margin-top: 2px; - } - } - } - - &.comment > .content { - margin-left: -16px; - } - - &.event > .text { - line-height: 32px; - vertical-align: middle; - } - - &.commits-list { - padding-left: 15px; - padding-top: 0; - - .singular-commit { - line-height: 34px; /* this must be same as .badge height, to avoid overflow */ - clear: both; // reset the "float right shabox", in the future, use flexbox instead - - > img.avatar, - > .avatar img { - position: relative; - top: -2px; - } - - .shabox { - .sha.label { - margin: 0; - border: 1px solid var(--color-light-border); - - &.isSigned.isWarning { - border: 1px solid var(--color-red-badge); - background: var(--color-red-badge-bg); - - .shortsha { - display: inline-block; - padding-top: 1px; - } - - &:hover { - background: var(--color-red-badge-hover-bg) !important; - } - } - - &.isSigned.isVerified { - border: 1px solid var(--color-green-badge); - background: var(--color-green-badge-bg); - - .shortsha { - display: inline-block; - padding-top: 1px; - } - - &:hover { - background: var(--color-green-badge-hover-bg) !important; - } - } - - &.isSigned.isVerifiedUntrusted { - border: 1px solid var(--color-yellow-badge); - background: var(--color-yellow-badge-bg); - - .shortsha { - display: inline-block; - padding-top: 1px; - } - - &:hover { - background: var(--color-yellow-badge-hover-bg) !important; - } - } - - &.isSigned.isVerifiedUnmatched { - border: 1px solid var(--color-orange-badge); - background: var(--color-orange-badge-bg); - - .shortsha { - display: inline-block; - padding-top: 1px; - } - - &:hover { - background: var(--color-orange-badge-hover-bg) !important; - } - } - } - } - } - } - - &.event > .commit-status-link { - float: right; - margin-right: 8px; - margin-top: 4px; - } - - .comparebox { - line-height: 32px; - vertical-align: middle; - - .compare.label { - font-size: 1rem; - margin: 0; - border: 1px solid var(--color-light-border); - } - } - - @media @mediaSm { - .ui.segments { - margin-left: -2rem; - } - } - } - - .ui.comments { - max-width: 100%; - - .avatar { - margin-right: .5rem; - } - } - - .comment { - > .content { - > div:first-child { - border-top-left-radius: 4px; - border-top-right-radius: 4px; - } - - > div:last-child { - border-bottom-left-radius: 4px; - border-bottom-right-radius: 4px; - } - } - - .comment-container { - border: 1px solid var(--color-secondary); - border-radius: var(--border-radius); - } - - .content { - @media @mediaSm { - .form .button { - width: 100%; - margin: 0; - - &:not(:last-child) { - margin-bottom: 1rem; - } - } - } - } - - .merge-section { - background-color: var(--color-box-body); - - .item-section { - display: flex; - align-items: center; - justify-content: space-between; - padding: 0; - margin-top: -.25rem; - margin-bottom: -.25rem; - } - - @media @mediaSm { - .item-section { - align-items: flex-start; - flex-direction: column; - } - } - - .divider { - margin-left: -1rem; - margin-right: -1rem; - } - - &.no-header { - #avatar-arrow(); - - &::after { - border-right-color: var(--color-box-body); - } - } - } - - .markup { - font-size: 14px; - } - - .no-content { - color: var(--color-text-light-2); - font-style: italic; - } - - .ui.form { - .field { - &:first-child { - clear: none; - } - - &.footer { - overflow: hidden; - } - - .tab.markup { - min-height: 5rem; - } - } - - textarea { - height: 200px; - font-family: var(--fonts-monospace); - } - } - - .edit.buttons { - margin-top: 10px; - } - } - - .code-comment { - border: 1px solid transparent; - padding: .25rem .5rem; - margin: 0; - - .content { - border: none !important; - } - - .comment-header { - background: transparent; - border-bottom: 0 !important; - padding: 0 !important; - - &::after, - &::before { - display: none; - } - } - - .comment-content { - margin-left: 36px; - } - } - - .code-comment, - .comment { - img.avatar { - width: 28px; - height: 28px; - } - } - - .comment-code-cloud { - .segment.reactions { - margin-top: 16px !important; - margin-bottom: -8px !important; - border-top: none !important; - - .ui.label { - border: 1px solid; - padding: 6px 10px !important; - margin: 0 2px; - border-radius: var(--border-radius); - border-color: var(--color-secondary-dark-1) !important; - } - - .ui.label.basic.primary { - background-color: var(--color-reaction-active-bg) !important; - border-color: var(--color-primary-alpha-80) !important; - } - } - - button.comment-form-reply { - margin: 0; - } - } - - .event { - padding-left: 15px; - - .detail { - margin-top: 4px; - margin-left: 14px; - - .svg { - margin-right: 2px; - } - } - - .segments { - box-shadow: none; - } - } - - @media @mediaSm { - padding: 1rem 0 !important; // Important is required here to override existing fomantic styles. - } - } - - .ui.depending { - .item.is-closed { - .title { - text-decoration: line-through; - } - } - } - } - - .comment.form { - .ui.comments { - margin-top: -12px; - max-width: 100%; - } - - .content { - .field:first-child { - clear: none; - } - - .form { - #avatar-arrow(); - - &::after { - border-right-color: var(--color-box-body); - } - } - - textarea { - height: 200px; - font-family: var(--fonts-monospace); - } - - .CodeMirror-scroll { - max-height: 85vh; - } - } - } - - .milestone.list { - list-style: none; - padding-top: 15px; - - > .item { - padding-top: 10px; - padding-bottom: 10px; - border-bottom: 1px dashed var(--color-secondary); - - progress { - width: 200px; - height: 16px; - } - - .meta { - color: var(--color-text-light-2); - padding-top: 5px; - - .issue-stats .svg { - padding-left: 5px; - } - - .overdue { - color: var(--color-red); - } - } - - .operate { - margin-top: -15px; - - > a { - font-size: 15px; - padding-top: 5px; - padding-right: 10px; - color: var(--color-text-light-2); - - &:hover { - color: var(--color-text); - } - } - } - - .content { - padding-top: 10px; - } - } - } - - &.new.milestone { - textarea { - height: 200px; - } - } - - &.compare.pull { - .show-form-container { - text-align: left; - } - - .choose.branch { - .svg { - margin-right: 10px; - } - } - - .comment.form { - .content { - #avatar-arrow(); - - &::after { - border-right-color: var(--color-box-body); - } - } - } - - .pullrequest-form { - margin-bottom: 1.5rem; - } - - .markup { - font-size: 14px; - } - - .title { - .issue-title { - margin-bottom: .5rem; - .index { - color: var(--color-text-light-2); - } - } - } - } - - .filter.dropdown .menu { - margin-top: 1px !important; - } - - &.branches { - .commit-divergence { - .bar-group { - position: relative; - float: left; - padding-bottom: 6px; - width: 50%; - max-width: 90px; - - &:last-child { - border-left: 1px solid var(--color-secondary-dark-2); - } - } - - .count { - margin: 0 3px; - - &.count-ahead { - text-align: left; - } - - &.count-behind { - text-align: right; - } - } - - .bar { - height: 4px; - position: absolute; - background-color: var(--color-secondary-dark-2); - - &.bar-behind { - right: 0; - } - - &.bar-ahead { - left: 0; - } - } - } - } - - &.commits { - .header { - .search { - input { - font-weight: normal; - padding: 5px 10px; - } - } - } - } - - #commits-table { - thead { - th:first-of-type { - padding-left: 15px; - } - - .sha { - &td { - text-align: center; - } - - width: 200px; - } - } - - td.sha .sha.label { - margin: 0; - } - - td.message { - text-overflow: unset; - } - - &.ui.basic.striped.table tbody tr:nth-child(2n) { - background-color: rgba(0, 0, 0, .02) !important; - } - } - - #commits-table td.sha .sha.label, - #repo-files-table .sha.label, - #rev-list .sha.label, - .timeline-item.commits-list .singular-commit .sha.label { - border: 1px solid var(--color-light-border); - - .ui.signature.avatar { - height: 16px; - margin-bottom: 0; - width: 16px; - } - - .detail.icon { - background: var(--color-light); - margin: -6px -10px -4px 0; - padding: 5px 4px 5px 6px; - border-left: 1px solid var(--color-light-border); - border-top: 0; - border-right: 0; - border-bottom: 0; - border-top-left-radius: 0; - border-bottom-left-radius: 0; - - img { - margin-right: 0; - } - - .svg { - margin: 0 .25em 0 0; - } - - > div { - display: flex; - align-items: center; - } - } - - &.isSigned.isWarning { - border: 1px solid var(--color-red-badge); - background: var(--color-red-badge-bg); - - .shortsha { - display: inline-block; - padding-top: 1px; - } - - .detail.icon { - border-left: 1px solid var(--color-red-badge); - color: var(--color-red-badge); - } - - &:hover { - background: var(--color-red-badge-hover-bg) !important; - } - } - - &.isSigned.isVerified { - border: 1px solid var(--color-green-badge); - background: var(--color-green-badge-bg); - - .shortsha { - display: inline-block; - padding-top: 1px; - } - - .detail.icon { - border-left: 1px solid var(--color-green-badge); - color: var(--color-green-badge); - } - - &:hover { - background: var(--color-green-badge-hover-bg) !important; - } - } - - &.isSigned.isVerifiedUntrusted { - border: 1px solid var(--color-yellow-badge); - background: var(--color-yellow-badge-bg); - - .shortsha { - display: inline-block; - padding-top: 1px; - } - - .detail.icon { - border-left: 1px solid var(--color-yellow-badge); - color: var(--color-yellow-badge); - } - - &:hover { - background: var(--color-yellow-badge-hover-bg) !important; - } - } - - &.isSigned.isVerifiedUnmatched { - border: 1px solid var(--color-orange-badge); - background: var(--color-orange-badge-bg); - - .shortsha { - display: inline-block; - padding-top: 1px; - } - - .detail.icon { - border-left: 1px solid var(--color-orange-badge); - color: var(--color-orange-badge); - } - - &:hover { - background: var(--color-orange-badge-hover-bg) !important; - } - } - } - - .data-table { - width: 100%; - - tr { - border-top: 0; - } - - td, - th { - padding: 5px !important; - overflow: hidden; - font-size: 12px; - text-align: left; - white-space: nowrap; - border: 1px solid var(--color-secondary); - } - - td { - white-space: pre-line; - } - - th { - font-weight: 600; - background: var(--color-box-header); - border-top: 0; - } - - td.added, - th.added, - tr.added { - background-color: var(--color-diff-added-row-bg) !important; - } - - td.removed, - th.removed, - tr.removed { - background-color: var(--color-diff-removed-row-bg) !important; - } - - td.moved, - th.moved, - tr.moved { - background-color: var(--color-diff-moved-row-bg) !important; - } - - tbody.section { - border-top: 2px solid var(--color-secondary); - } - - .line-num { - &:extend(.unselectable); - width: 1%; - min-width: 50px; - font-family: monospace; - line-height: 20px; - color: var(--color-secondary-dark-2); - white-space: nowrap; - vertical-align: top; - cursor: pointer; - text-align: right; - background: var(--color-body); - border: 0; - } - } - - .diff-detail-box { - padding: 7px 0; - background: var(--color-body); - line-height: 30px; - - @media @mediaMdAndDown { - flex-direction: column; - align-items: flex-start; - } - - @media (max-width: 480px) { - flex-wrap: wrap; - } - - &.sticky { - position: sticky; - top: 0; - z-index: 8; - border-bottom: 1px solid var(--color-secondary); - padding-left: 2px; - padding-right: 2px; - margin-left: -1px; - margin-right: -1px; - } - - > div::after { - clear: both; - content: ""; - display: block; - } - - .diff-detail-stats strong { - margin-left: .25rem; - margin-right: .25rem; - } - - // Because the translations contain the we need to style with nth-of-type - - .diff-detail-stats strong:nth-of-type(1) { - color: var(--color-yellow); - } - - .diff-detail-stats strong:nth-of-type(2) { - color: var(--color-green); - } - - .diff-detail-stats strong:nth-of-type(3) { - color: var(--color-red); - } - - .diff-detail-stats { - @media (max-width: 480px) { - font-size: 0; - line-height: 1.6rem; - - strong { - font-size: 1rem; - } - } - } - - .diff-detail-actions > * { - margin-right: 0; - } - - .diff-detail-actions > * + * { - margin-left: .25rem; - } - - .diff-detail-actions { - @media (max-width: 480px) { - padding-top: .25rem; - - .ui.button:not(.btn-submit) { - padding-left: .5rem; - padding-right: .5rem; - display: flex; - flex-wrap: wrap; - justify-content: center; - text-align: center; - } - } - } - - span.status { - display: inline-block; - width: 12px; - height: 12px; - margin-right: 8px; - vertical-align: middle; - - &.modify { - background-color: var(--color-yellow); - } - - &.add { - background-color: var(--color-green); - } - - &.del { - background-color: var(--color-red); - } - - &.rename { - background-color: var(--color-teal); - } - } - .button { - padding: 8px 12px; - } - } - - .diff-box .header:not(.resolved-placeholder) { - display: flex; - align-items: center; - - .file { - min-width: 0; - .file-link { - max-width: fit-content; - display: -webkit-box; - -webkit-box-orient: vertical; - -webkit-line-clamp: 2; - overflow: hidden; - } - } - - .button { - padding: 8px 12px; - flex: 0 0 auto; - margin-top: -8px; - margin-bottom: -8px; - margin-right: 0; - } - } - - .diff-box .resolved-placeholder { - display: flex; - align-items: center; - - .button { - padding: 8px 12px; - } - } - - .diff-file-box { - .header { - background-color: var(--color-box-header); - } - - .file-body.file-code { - background: var(--color-code-bg); - - .lines-num { - &:extend(.unselectable); - text-align: right; - color: var(--color-text-light); - width: 1%; - min-width: 50px; - - span.fold { - display: block; - text-align: center; - } - } - } - - .code-diff { - font-size: 12px; - - td { - padding: 0 0 0 10px !important; - border-top: 0; - } - - .lines-num { - padding: 0 5px !important; - } - - .tag-code .lines-num, - .tag-code td { - padding: 0 !important; - } - - tbody { - tr { - td.halfwidth { - // halfwidth is used in split view - and in that case, 1% of each - width: 49%; - } - - td.center { - text-align: center; - } - - [data-line-num]::before { - content: attr(data-line-num); - text-align: right; - } - - .lines-type-marker { - &:extend(.unselectable); - width: 10px; - min-width: 10px; - } - - [data-type-marker]::before { - content: attr(data-type-marker); - text-align: right; - display: inline-block; - } - } - } - } - - .code-diff-split { - .tag-code .lines-code code.code-inner { - padding-left: 10px !important; - } - - table, - tbody { - width: 100%; - } - } - - &.file-content { - img { - max-width: 100%; - padding: 0; - border-radius: 0; - } - - img.emoji { - padding: 0; - } - - clear: right; - } - - .ui.bottom.attached.table.segment { - padding-top: 5px; - padding-bottom: 5px; - } - } - - .diff-stats { - clear: both; - margin-bottom: 5px; - max-height: 400px; - overflow: auto; - padding-left: 0; - - li { - list-style: none; - padding-bottom: 4px; - margin-bottom: 4px; - padding-left: 6px; - } - - li + li { - border-top: 1px solid var(--color-secondary); - } - } - - .repo-search-result { - padding-top: 10px; - padding-bottom: 10px; - - .lines-num a { - color: inherit; - } - } - - &.quickstart { - .guide { - .item { - padding: 1em; - - small { - font-weight: normal; - } - } - - .clone.button:first-child { - border-radius: var(--border-radius) 0 0 var(--border-radius); - } - - .ui.action.small.input { - width: 100%; - } - - #repo-clone-url { - border-radius: 0; - padding: 5px 10px; - font-size: 1.2em; - line-height: 1.4; - } - } - } - - &.release { - #release-list { - border-top: 1px solid var(--color-secondary); - margin-top: 20px; - padding-top: 15px; - padding-left: 0; - - .release-list-title { - font-size: 2rem; - font-weight: normal; - margin-top: -4px; - margin-bottom: 0; - } - - > li { - list-style: none; - - .meta, - .detail { - padding-top: 30px; - padding-bottom: 40px; - } - - .meta { - text-align: right; - position: relative; - - .label { - margin-right: 0; - } - - .commit { - display: block; - margin-top: 10px; - } - - .choose { - margin-top: 15px; - - .button { - margin-right: 0; - } - } - } - - .detail { - border-left: 2px solid var(--color-secondary); - - .author { - img { - margin-bottom: 3px; - } - } - - .download { - > a { - .svg { - margin-left: 5px; - margin-right: 5px; - } - } - - .list { - padding-left: 0; - - li { - list-style: none; - display: block; - padding: 8px; - border: 1px solid var(--color-secondary); - background: var(--color-light); - - a > .text.right { - margin-right: 5px; - } - } - - li + li { - border-top: 0; - } - - li:first-of-type { - border-radius: var(--border-radius) 0 0 var(--border-radius); - } - - li:last-of-type { - border-radius: 0 var(--border-radius) var(--border-radius) 0; - } - } - } - - .dot { - width: 10px; - height: 10px; - background-color: var(--color-secondary-dark-3); - z-index: 9; - position: absolute; - display: block; - left: -6px; - top: 40px; - border-radius: 100%; - border: 2.5px solid var(--color-body); - } - } - } - } - - #tags-table { - .tag { - padding: 8px 12px; - } - - .release-tag-name { - font-size: 18px; - font-weight: normal; - } - } - } - - &.new.release { - .target { - min-width: 500px; - - #tag-name { - margin-top: -4px; - } - - .at { - margin-left: -5px; - margin-right: 5px; - } - - .selection.dropdown { - padding-top: 10px; - padding-bottom: 10px; - } - } - - .prerelease.field { - margin-bottom: 0; - } - - .field { - - button, - input { - @media (max-width: 438px) { - width: 100%; - } - } - - button { - @media @mediaSm { - margin-bottom: 1em; - } - } - - .wrap_remove { - height: 38px; - } - - .attachment_edit { - width: 450px !important; - } - } - } - - &.forks { - .list { - margin-top: 0; - - .item { - padding-top: 10px; - padding-bottom: 10px; - border-bottom: 1px solid var(--color-secondary); - - .ui.avatar { - float: left; - margin-right: 5px; - } - - .link { - padding-top: 5px; - } - } - } - } - - &.packages { - .empty { - padding-top: 70px; - padding-bottom: 100px; - - .svg { - height: 48px; - } - } - - .file-size { - white-space: nowrap; - } - } - - &.wiki { - &.start { - .ui.segment { - padding-top: 70px; - padding-bottom: 100px; - - .svg { - height: 48px; - } - } - } - - &.new { - .ui.attached.tabular.menu.previewtabs { - margin-bottom: 15px; - } - } - - &.view { - > .markup { - padding: 15px 30px; - - h1, - h2, - h3, - h4, - h5, - h6 { - &:first-of-type { - margin-top: 0; - } - } - } - } - - .form .CodeMirror-scroll { - max-height: 85vh; - } - - @media @mediaSm { - .dividing.header .stackable.grid .button { - margin-top: 2px; - margin-bottom: 2px; - } - } - - @media @mediaSm { - #clone-panel #repo-clone-url { - width: 160px; - } - } - } - - &.settings { - &.collaboration { - .collaborator.list { - padding: 0; - - > .item { - margin: 0; - line-height: 2em; - - &:not(:last-child) { - border-bottom: 1px solid var(--color-secondary); - } - } - } - - #repo-collab-form { - #search-user-box { - .results { - left: 7px; - } - } - - .ui.button { - margin-left: 5px; - margin-top: -3px; - } - } - - #repo-collab-team-form { - #search-team-box { - .results { - left: 7px; - } - } - - .ui.button { - margin-left: 5px; - margin-top: -3px; - } - } - } - - &.branches { - .protected-branches { - .selection.dropdown { - width: 300px; - } - - .item { - border: 1px solid var(--color-secondary); - padding: 10px 15px; - - &:not(:last-child) { - border-bottom: 0; - } - } - } - - .branch-protection { - .help { - margin-left: 26px; - padding-top: 0; - } - - .fields { - margin-left: 20px; - display: block; - } - - .whitelist { - margin-left: 26px; - - .dropdown img { - display: inline-block; - } - } - } - } - - &.webhook { - .events { - .column { - padding-bottom: 0; - } - - .help { - font-size: 13px; - margin-left: 26px; - padding-top: 0; - } - } - } - } - - .ui.attached.isSigned.isWarning { - border-left: 1px solid var(--color-error-border); - border-right: 1px solid var(--color-error-border); - - &.top, - &.message { - border-top: 1px solid var(--color-error-border); - } - - &.message { - box-shadow: none; - background-color: var(--color-error-bg); - color: var(--color-error-text); - - .ui.text { - color: var(--color-error-text); - } - } - - &:last-child, - &.bottom { - border-bottom: 1px solid var(--color-error-border); - } - } - - .ui.attached.isSigned.isVerified { - border-left: 1px solid var(--color-success-border); - border-right: 1px solid var(--color-success-border); - - &.top, - &.message { - border-top: 1px solid var(--color-success-border); - } - - &.message { - box-shadow: none; - background-color: var(--color-success-bg); - color: var(--color-success-text); - - .pull-right { - color: var(--color-text); - } - - .ui.text { - color: var(--color-success-text); - } - } - - &:last-child, - &.bottom { - border-bottom: 1px solid var(--color-success-border); - } - } - - .ui.attached.isSigned.isVerifiedUntrusted, - .ui.attached.isSigned.isVerifiedUnmatched { - border-left: 1px solid var(--color-warning-border); - border-right: 1px solid var(--color-warning-border); - - &.top, - &.message { - border-top: 1px solid var(--color-warning-border); - } - - &.message { - box-shadow: none; - background-color: var(--color-warning-bg); - color: var(--color-warning-text); - - .ui.text { - color: var(--color-warning-text); - } - } - - &:last-child, - &.bottom { - border-bottom: 1px solid var(--color-warning-border); - } - } - - .ui.segment.sub-menu { - padding: 7px; - line-height: 0; - - .list { - width: 100%; - display: flex; - align-items: center; - - .item { - width: 100%; - color: var(--color-text); - - &:first-of-type { - border-radius: var(--border-radius) 0 0 var(--border-radius); - padding-left: .25rem; - } - - &:last-of-type { - border-radius: 0 var(--border-radius) var(--border-radius) 0; - padding-right: .25rem; - } - - a { - color: var(--color-text); - - &:hover { - color: var(--color-primary-light-2); - } - } - - &.active { - background: var(--color-secondary); - } - } - } - } - - .segment.reactions, - .select-reaction { - &.dropdown .menu { - right: 0 !important; - left: auto !important; - min-width: 15em; - - > .header { - margin: .75rem 0 .5rem; - } - - > .item { - float: left; - padding: .25rem !important; - margin: .25rem; - font-size: 1.5em; - width: 39px; - left: 13px; - border-radius: 6px; - display: flex; - justify-content: center; - align-items: center; - - img.emoji { - margin-right: 0; - } - } - - > .item:hover { - background: var(--color-primary); - } - } - } - - .segment.reactions { - padding: 0; - display: flex; - border: none !important; - border-top: 1px solid var(--color-secondary) !important; - width: 100% !important; - max-width: 100% !important; - margin: 0 !important; - - .ui.label { - max-height: 40px; - padding: 10px 18px !important; - display: flex !important; - align-items: center; - border: 0; - border-right: 1px solid; - border-radius: 0; - margin: 0; - font-size: 14px; - font-weight: normal; - border-color: var(--color-secondary) !important; - background: var(--color-reaction-bg); - - &.disabled { - cursor: default; - opacity: 1; - } - } - - .ui.label.basic { - color: var(--color-primary) !important; - } - - .ui.label.basic.primary { - background-color: var(--color-reaction-active-bg) !important; - border-color: var(--color-secondary) !important; - } - - .reaction-count { - margin-left: .5rem; - } - - .select-reaction { - display: flex; - align-items: center; - padding: 0 14px; - - &:not(.active) a { - display: none; - } - } - - &:hover .select-reaction a { - display: block; - } - } - - .ui.fluid.action.input { - .ui.search.action.input { - flex: auto; - } - } - - .repository-summary { - box-shadow: none !important; - - .segment.language-stats-details, - .segment.repository-summary { - border-top: none; - background: none; - } - - .segment.language-stats-details .item { - white-space: nowrap; - } - - .segment.language-stats { - &:extend(.unselectable); - padding: 0; - height: 11px; - display: flex; - white-space: nowrap; - width: 100%; - border-radius: 0; - - @media @mediaSm { - display: none; - } - - .bar { - white-space: nowrap; - border: 0; - padding: 0; - margin: 0; - height: 100%; - } - } - } - - .repository-menu { - padding: 0 !important; - } - - .repository-menu .item { - padding-top: 9px !important; - padding-bottom: 9px !important; - } -} - -// End of .repository - -#cite-repo-modal { - #citation-panel { - width: 500px; - - @media @mediaSm { - width: 100%; - } - - input { - border-radius: 0; - padding: 5px 10px; - width: 50%; - line-height: 1.4; - } - - .citation.button { - font-size: 13px; - padding: 7.5px 5px; - } - - #citation-copy-content { - border-radius: 0; - padding: 5px 10px; - font-size: 1.2em; - line-height: 1.4; - } - - #citation-copy-apa, - #citation-copy-bibtex { - border-right: none; - } - - #goto-citation-btn { - border-left: none; - } - - >:first-child { - border-radius: var(--border-radius) 0 0 var(--border-radius) !important; - } - - >:last-child { - border-radius: 0 var(--border-radius) var(--border-radius) 0 !important; - } - - .icon.button { - padding: 0 10px; - } - } -} - -&.user-cards { - .list { - padding: 0; - display: flex; - flex-wrap: wrap; - - .item { - list-style: none; - width: 32%; - margin: 10px 10px 10px 0; - padding-bottom: 14px; - float: left; - - .avatar { - width: 48px; - height: 48px; - float: left; - display: block; - margin-right: 10px; - } - - .name { - margin-top: 0; - margin-bottom: 0; - font-weight: normal; - } - - .meta { - margin-top: 5px; - } - } - } -} - -#search-repo-box, -#search-user-box { - .results { - .result { - img { - float: left; - margin-right: 8px; - width: 2em; - height: 2em; - } - - .content { - margin: 6px 0; - } - } - } -} - -#search-team-box { - .results { - .result { - .content { - margin: 6px 0; - } - } - } -} - -#issue-actions { - margin-top: -1rem !important; // counteract padding from Semantic -} - -.ui.menu .item > img:not(.ui) { - width: auto; -} - -.page.buttons { - padding-top: 15px; -} - -.commit-header-row { - min-height: 50px !important; - padding-top: 0 !important; - padding-bottom: 0 !important; -} - -.settings { - .content { - > .header, - .segment { - box-shadow: 0 1px 2px 0 var(--color-box-header); - } - } - - &.webhooks .list > .item:not(:first-child), - &.githooks .list > .item:not(:first-child), - &.runners .list > .item:not(:first-child) { - padding: .25rem 1rem; - margin: 12px -1rem -1rem; - } - - .list { - > .item { - &:not(:first-child) { - border-top: 1px solid var(--color-secondary); - padding: 1rem; - margin: 16px -1rem -1rem; - } - - > .svg { - display: table-cell; - } - - > .svg + .content { - display: table-cell; - padding: 0 0 0 .5em; - vertical-align: top; - } - - .info { - margin-top: 10px; - - .tab.segment { - border: 0; - padding: 10px 0 0; - } - } - } - - &.key { - .meta { - padding-top: 5px; - color: var(--color-text-light-2); - } - } - - &.email { - > .item:not(:first-child) { - min-height: 60px; - } - } - - &.collaborator { - > .item { - padding: 0; - } - } - } -} - -.ui.vertical.menu { - .header.item { - font-size: 1.1em; - background: var(--color-box-header); - } -} - -.comment:target .comment-container { - border-color: var(--color-primary) !important; - box-shadow: 0 0 0 3px var(--color-primary-alpha-30) !important; -} - -.comment:target .header::before { - border-right-color: var(--color-primary) !important; - filter: drop-shadow(-3px 0 0 var(--color-primary-alpha-30)) !important; -} - -.code-comment:target { - border-color: var(--color-primary) !important; - border-radius: var(--border-radius) !important; - box-shadow: 0 0 0 3px var(--color-primary-alpha-30) !important; -} - -.code-comment:target .content { - box-shadow: none !important; -} - -.comment-header { - #avatar-arrow(); - border: none !important; - background: var(--color-box-header); - border-bottom: 1px solid var(--color-secondary) !important; - font-weight: normal !important; - padding: .5rem 1rem; - margin: 0 !important; - position: relative; - color: var(--color-text-light-2); - min-height: 41px; - background-color: var(--color-box-header); - display: flex; - justify-content: space-between; - align-items: center; - - &.arrow-top::before, - &.arrow-top::after { - transform: rotate(90deg); - } - - &.arrow-top::before { - top: -9px; - left: 6px; - } - - &.arrow-top::after { - top: -8px; - left: 7px; - } - - a { - color: var(--color-text); - } - - a:hover { - color: var(--color-primary); - } -} - -.comment-header .actions a { - margin-right: 0 !important; - padding: .5rem !important; -} - -.comment-header-left > * + *, -.comment-header-right > * + * { - margin-left: .25rem; -} - -.comment-body { - background: var(--color-box-body); - border: none !important; - width: 100% !important; - max-width: 100% !important; - margin: 0 !important; -} - -.edit-label.modal, -.new-label.modal { - .form { - .column { - padding-right: 0; - } - - .buttons { - margin-left: auto; - padding-top: 15px; - } - - .color.picker.column { - display: flex; - .minicolors { - flex: 1; - } - } - - .minicolors-swatch.minicolors-sprite { - top: 10px; - left: 10px; - width: 15px; - height: 15px; - } - } -} - -#avatar-arrow { - &::before, - &::after { - right: 100%; - top: 20px; - border: solid transparent; - content: " "; - height: 0; - width: 0; - position: absolute; - pointer-events: none; - } - - &::before { - border-right-color: var(--color-secondary); - border-width: 9px; - margin-top: -9px; - } - - &::after { - border-right-color: var(--color-box-header); - border-width: 8px; - margin-top: -8px; - } -} - -#transfer-repo-modal, -#delete-repo-modal, -#delete-wiki-modal, -#convert-fork-repo-modal, -#convert-mirror-repo-modal, -#fork-repo-modal { - .ui.message { - width: 100% !important; - } -} - -// generate .tab-size-{i} from 1 to 16 -.generate-tab-size(16); - -.generate-tab-size(@n, @i: 1) when (@i =< @n) { - .tab-size-@{i} { - tab-size: @i !important; - -moz-tab-size: @i !important; - } - - .generate-tab-size(@n, (@i + 1)); -} - -.stats-table { - display: table; - width: 100%; - - .table-cell { - display: table-cell; - - &.tiny { - height: .5em; - } - } -} - -.labels-list .label { - margin: 2px 0; - display: inline-flex !important; - line-height: 1.3em; // there is a `font-size: 1.25em` for inside emoji, so here the line-height needs to be larger slightly -} - -// Scoped labels with different colors on left and right -.scope-parent { - background: none !important; - padding: 0 !important; -} - -.ui.label.scope-left { - border-bottom-right-radius: 0; - border-top-right-radius: 0; - margin-right: 0; -} - -.ui.label.scope-right { - border-bottom-left-radius: 0; - border-top-left-radius: 0; - margin-left: 0; -} - -.repo-button-row { - margin-bottom: 10px; -} - -.repo-button-row > * { - margin-top: 8px; -} - -.wiki .repo-button-row { - margin-bottom: 0; -} - -.wiki .repo-button-row > * { - margin-top: 0; -} - -.repo-button-row .button { - padding: 6px 10px !important; - height: 30px; -} - -.repo-button-row input { - height: 30px; -} - -tbody.commit-list { - vertical-align: baseline; -} - -.message-wrapper, -.author-wrapper { - overflow: hidden; - text-overflow: ellipsis; - max-width: calc(100% - 50px); - display: inline-block; - vertical-align: middle; -} - -.author-wrapper { - max-width: 180px; -} - -// in the commit list, messages can wrap so we can use inline -.commit-list .message-wrapper { - display: inline; -} - -// but in the repo-files-table we cannot -#repo-files-table .commit-list .message-wrapper { - display: inline-block; -} - -@media @mediaSm { - tr.commit-list { - width: 100%; - } - - th .message-wrapper { - display: block; - max-width: calc(100vw - 70px); - } - - .author-wrapper { - max-width: 80px; - } -} - -@media @mediaMd { - tr.commit-list { - width: 723px; - } - - th .message-wrapper { - max-width: 120px; - } -} - -@media @mediaLg { - tr.commit-list { - width: 933px; - } - - th .message-wrapper { - max-width: 350px; - } -} - -@media @mediaXl { - tr.commit-list { - width: 1127px; - } - - th .message-wrapper { - max-width: 525px; - } -} - -.commit-list .commit-status-link { - display: inline-block; - vertical-align: middle; -} - -.commit-body { - white-space: pre-wrap; - line-height: initial; -} - -.repository:not(.diff) { - .commit-body { // commit history list - margin: 0; - } - - .timeline-item .commit-body { // PR-comment - margin-left: 40px; - } -} - -.git-notes.top { - text-align: left; -} - -.comment-diff-data { - background: var(--color-code-bg); - max-height: calc(100vh - 10.5rem); - overflow-y: auto; -} - -.comment-diff-data pre { - line-height: 18px; - white-space: pre-wrap; - word-break: break-all; - overflow-wrap: break-word; -} - -.content-history-detail-dialog .header .avatar { - position: relative; - top: -2px; -} - -#topic_edit { - margin-top: 5px; -} - -#repo-topics { - margin-top: 5px; - display: flex; - align-items: center; - flex-wrap: wrap; -} - -.repo-topic { - font-weight: normal !important; - cursor: pointer; - margin: 2px !important; -} - -#new-dependency-drop-list { - &.ui.selection.dropdown { - min-width: 0; - width: 100%; - border-radius: 4px 0 0 4px; - border-right: 0; - white-space: nowrap; - } - - .text { - width: 100%; - overflow: hidden; - } -} - -#manage_topic { - font-size: 12px; -} - -.label + #manage_topic { - margin-left: 5px; -} - -.ui.small.label.topic { - margin-bottom: 4px; -} - -.repo-header { - display: flex; - align-items: center; - justify-content: space-between; - flex-wrap: wrap; - word-break: break-word; - - @media @mediaSm { - + .container { - margin-top: 7px; - } - } -} - -.repo-buttons { - align-items: center; - display: flex; - flex-direction: row; - flex-wrap: wrap; - word-break: keep-all; - - @media @mediaSm { - margin-top: 1em; - } -} - -.repo-buttons .ui.labeled.button > .label:hover { - color: var(--color-primary-light-2); - background: var(--color-light); -} - -.label-mimic-enabled() { - color: var(--color-text-dark); - background: var(--color-light-mimic-enabled) !important; - - &:hover { - color: var(--color-primary-dark-1); - } -} - -.repo-buttons button[disabled] ~ .label { - opacity: var(--opacity-disabled); - .label-mimic-enabled(); -} - -.repo-buttons .ui.labeled.button { - cursor: initial; - - > .label { - border-left: 0 !important; - margin: 0 !important; - } - - &.disabled { - pointer-events: inherit !important; - - > .label { - .label-mimic-enabled(); - } - - > .button { - pointer-events: none !important; - } - } - @media @mediaSm { - .svg { - display: none; - } - } -} - -.tag-code { - height: 28px; -} - -.tag-code, -.tag-code td, -.tag-code .blob-excerpt { - background-color: var(--color-box-body-highlight); - vertical-align: middle; -} - -.resolved-placeholder { - font-weight: normal !important; - border: 1px solid var(--color-secondary) !important; - border-radius: var(--border-radius) !important; - margin: 4px !important; -} - -.resolved-placeholder + .comment-code-cloud { - padding-top: 0 !important; -} - -td.blob-excerpt { - background-color: var(--color-secondary-alpha-30); -} - -.issue-keyword { - border-bottom: 1px dotted var(--color-text-light-3) !important; -} - -.issue-keyword:hover { - border-bottom: none !important; -} - -.file-header { - align-items: center; - display: flex; - justify-content: space-between; - overflow-x: auto; - padding: 6px 12px !important; - font-size: 13px !important; -} - -.file-info { - display: flex; - align-items: center; -} - -.file-info-entry { - display: flex; - align-items: center; - width: max-content; -} - -.file-info-entry + .file-info-entry { - border-left: 1px solid currentcolor; - margin-left: 8px; - padding-left: 8px; -} - -#diff-container { - display: flex; -} -#diff-file-boxes { - flex: 1; - max-width: 100%; -} - -#diff-file-tree { - width: 20%; - max-width: 380px; - line-height: inherit; - position: sticky; - padding-top: 0; - top: 47px; - max-height: calc(100vh - 50px); - height: 100%; - overflow-y: auto; -} - -@media @mediaMdAndDown { - #diff-file-tree { - display: none !important; - } - - .diff-toggle-file-tree-button { - display: none !important; - } -} - -.ui.message.unicode-escape-prompt { - margin-bottom: 0; - border-radius: 0; - display: flex; - flex-direction: column; -} - -.wiki-content-sidebar .ui.message.unicode-escape-prompt, -.wiki-content-footer .ui.message.unicode-escape-prompt { - p { - display: none; - } -} - -.wiki-content-toc { - > ul > li { - margin-bottom: 4px; - } - - ul { - margin: 0; - list-style: none; - padding-left: 1em; - } -} - -/* fomantic's last-child selector does not work with hidden last child */ -.ui.buttons .unescape-button { - border-top-right-radius: .28571429rem; - border-bottom-right-radius: .28571429rem; -} - -.webhook-info { - padding: 7px 12px; - margin: 10px 0; - background-color: var(--color-markup-code-block); - border: 1px solid var(--color-secondary); - border-radius: 3px; - font-size: 13px; - line-height: 1.5; - overflow: auto; -} - -.title_wip_desc { - margin-top: 1em; -} - -.sidebar-item-link { - align-items: center; - word-break: break-all; -} - -.diff-file-box[data-folded="true"] .diff-file-body { - display: none; -} - -.diff-file-box[data-folded="true"] .diff-file-header { - border-radius: var(--border-radius) !important; -} - -.diff-file-header-actions > * + * { - margin-left: .5rem !important; -} - -.ui.attached.header.diff-file-header { - &.sticky-2nd-row { - position: sticky; - top: 77px; - z-index: 7; - - @media (max-width: 480px) { - position: static; - } - } - - .diff-file-header-actions { - flex-shrink: 0; - } - - .diff-file-name { - flex: auto; - min-width: 100px; - } -} - -.diff-file-body { - overflow-x: scroll; -} - -.diff-stats-bar { - display: inline-block; - background-color: var(--color-red); - height: 12px; - width: 40px; - - .diff-stats-add-bar { - background-color: var(--color-green); - height: 100%; - } -} - -/* prevent page shaking on language bar click */ -.repository-summary-language-stats { - height: 48px; - overflow: hidden; - - @media @mediaSm { - height: auto; - } -} - -.ui.form .right .ui.button { - margin-left: .25em; - margin-right: 0; -} - -.removed-code { - background: var(--color-diff-removed-word-bg); -} - -.added-code { - background: var(--color-diff-added-word-bg); -} - -.code-diff-unified .del-code, -.code-diff-unified .del-code td, -.code-diff-split .del-code .lines-num-old, -.code-diff-split .del-code .lines-escape-old, -.code-diff-split .del-code .lines-type-marker-old, -.code-diff-split .del-code .lines-code-old { - background: var(--color-diff-removed-row-bg); - border-color: var(--color-diff-removed-row-border); -} - -.code-diff-unified .add-code, -.code-diff-unified .add-code td, -.code-diff-split .add-code .lines-num-new, -.code-diff-split .add-code .lines-type-marker-new, -.code-diff-split .add-code .lines-escape-new, -.code-diff-split .add-code .lines-code-new, -.code-diff-split .del-code .add-code.lines-num-new, -.code-diff-split .del-code .add-code.lines-type-marker-new, -.code-diff-split .del-code .add-code.lines-escape-new, -.code-diff-split .del-code .add-code.lines-code-new { - background: var(--color-diff-added-row-bg); - border-color: var(--color-diff-added-row-border); -} - -.code-diff-split .del-code .lines-num-new, -.code-diff-split .del-code .lines-type-marker-new, -.code-diff-split .del-code .lines-code-new, -.code-diff-split .del-code .lines-escape-new, -.code-diff-split .add-code .lines-num-old, -.code-diff-split .add-code .lines-escape-old, -.code-diff-split .add-code .lines-type-marker-old, -.code-diff-split .add-code .lines-code-old { - background: var(--color-diff-inactive); -} - -.code-diff-split tbody tr td:nth-child(5), -.code-diff-split tbody tr td.add-comment-right { - border-left: 1px solid var(--color-secondary); -} - -.repository .ui.menu.new-menu { - background: none !important; - - @media @mediaLgAndDown { - &::after { - background: none !important; - } - } -} - -.repository.migrate .card { - transition: all .1s ease-in-out; - box-shadow: none !important; - border: 1px solid var(--color-secondary); - color: var(--color-text); -} - -.repository.migrate .card:hover { - transform: scale(105%); - box-shadow: 0 .5rem 1rem var(--color-shadow) !important; -} - -@media @mediaSm { - .repository.file.list { - #repo-files-table { - .entry, - .commit-list { - align-items: center; - display: flex !important; - padding-top: 4px; - padding-bottom: 4px; - - td.age, - th.age { - margin-left: auto; - } - - td.message, - span.commit-summary { - display: none !important; - } - } - } - } - .issue-list-headers.ui[class].grid { - > div:nth-child(1) { - order: 1; - width: 50%; - } - - > div:nth-child(2) { - order: 3; - width: 100%; - } - - > div.column:not(.row):nth-child(3) { - order: 2; - width: 50%; - } - } - - .repository.view.issue .comment-list { - .timeline, - .timeline-item { - margin-left: 0; - } - - .timeline { - &::before { - left: 14px; - } - - .inline-timeline-avatar { - display: flex; - margin-bottom: auto; - - img.avatar { - height: 24px; - width: 24px; - } - } - - .comment-header { - &::before, - &::after { - content: unset; - } - - padding-left: 4px; - } - - /* Don't show the general avatar, we show the inline avatar on mobile. - * And don't show the role labels, there's no place for that. */ - .timeline-avatar, - .comment-header-right .role-label { - display: none; - } - } - } - .commit-header-row { - .ui.horizontal.list { - width: 100%; - overflow-x: auto; - margin-top: 2px; - - .item { - align-items: center; - display: flex; - } - } - - .author { - padding: 3px 0; - } - } - - .commit-header h3 { - flex-basis: auto !important; - margin-bottom: .5rem !important; - } - - .commits-table { - flex-direction: column; - - .commits-table-left { - align-items: initial !important; - margin-bottom: 6px; - } - - .commits-table-right form { - display: flex; - flex-wrap: wrap; - - > div:nth-child(1) { - order: 1; - } - - > div:nth-child(2) { - order: 3; - margin-left: .5rem; - margin-top: .5rem; - } - - > button:nth-child(3) { - order: 2; - margin-left: .25rem; - } - } - } - - .commit-table { - overflow-x: auto; - - td.sha, - th.sha { - display: none !important; - } - - .commit-list { - span.message-wrapper { - max-width: none; - } - - tr td:last-child { - display: block; - width: max-content; - } - - td.author { - display: block; - width: calc(100% + .5rem); - } - - .copy-commit-sha { - display: none !important; - } - } - } - - .comment-header { - flex-wrap: wrap; - - .comment-header-left { - flex-wrap: wrap; - } - - .comment-header-right { - margin-left: auto; - } - } -} - -.branch-dropdown-button { - max-width: 340px; - vertical-align: bottom !important; - - @media @mediaMd { - max-width: 185px; - } - @media @mediaSm { - max-width: 165px; - } -} - -.pr-status { - padding: 0 !important; // To clear fomantic's padding on .ui.segment elements - display: flex; - align-items: center; - - .commit-status { - margin: 1em; - flex-shrink: 0; - } - - .status-context { - display: flex; - justify-content: space-between; - width: 100%; - - > span { - padding: 1em 0; - } - } - - .status-details { - display: flex; - padding-right: .5em; - align-items: center; - justify-content: flex-end; - - @media @mediaSm { - flex-direction: column; - align-items: flex-end; - justify-content: center; - } - - > span { - padding-right: .5em; // To match the alignment with the "required" label - } - } -} diff --git a/web_src/less/_review.less b/web_src/less/_review.less deleted file mode 100644 index bf2be1f166ce..000000000000 --- a/web_src/less/_review.less +++ /dev/null @@ -1,324 +0,0 @@ -@import "variables.less"; - -.ui.button.add-code-comment { - padding: 2px; - position: absolute; - margin-left: -22px; - z-index: 5; - opacity: 0; - transition: transform .1s ease-in-out; - transform: scale(1); - box-shadow: none !important; - border: none !important; - - &:hover { - transform: scale(1.1); - } -} - -.lines-escape a.toggle-escape-button::before { - visibility: visible; - content: '⚠️'; - font-family: var(--fonts-emoji); - color: var(--color-red); -} - -.repository .diff-file-box .code-diff td.lines-escape { - padding-left: 0 !important; -} - -.diff-file-box .lines-code:hover .ui.button.add-code-comment { - opacity: 1; -} - -.repository .diff-file-box .code-diff .add-comment-left, -.repository .diff-file-box .code-diff .add-comment-right, -.repository .diff-file-box .code-diff .add-code-comment .add-comment-left, -.repository .diff-file-box .code-diff .add-code-comment .add-comment-right, -.repository .diff-file-box .code-diff .add-code-comment .lines-type-marker { - padding-left: 0 !important; - padding-right: 0 !important; -} - -.add-comment-left.add-comment-right .ui.attached.header { - border: 1px solid var(--color-secondary); - - &:not(.top) { - margin-bottom: .5em; - } -} - -.add-comment .lines-num, -.add-comment .lines-escape, -.add-comment .lines-type-marker { - display: none; -} - -.show-outdated, -.hide-outdated { - &:extend(.unselectable); - - &:hover { - text-decoration: underline; - } -} - -.comment-code-cloud { - padding: .5rem 1rem !important; - position: relative; - margin: 0 auto; - max-width: 1000px; - - @media @mediaSm { - max-width: none; - padding: .75rem !important; - - .code-comment-buttons { - margin: .5rem 0 .25rem !important; - - .code-comment-buttons-buttons { - width: 100%; - } - } - - .ui.buttons { - width: 100%; - margin: 0 !important; - - .button { - flex: 1; - } - } - } - - .comments .comment { - padding: 0; - - @media @mediaSm { - display: flex; - - .comment-header-right.actions .ui.basic.label { - display: none; - } - - .avatar { - width: auto; - float: none; - margin: 0 .5rem 0 0; - flex-shrink: 0; - - ~ .content { - margin-left: 1em; - } - } - - img.avatar { - margin: 0 !important; - } - - .comment-content { - margin-left: 0 !important; - } - - .comment-container { - width: 100%; - } - - &.code-comment { - padding: 0 0 .5rem !important; - } - } - } - - .attached { - &.tab { - border: 0; - padding: 0; - margin: 0; - } - - &.header { - padding: .1rem 1rem; - - .text { - margin: 0; - } - } - } - - .right.menu.options .item { - padding: .85714286em .442857em; - cursor: pointer; - } - - .ui.active.tab { - padding: .5em; - - &.markup { - padding: 1em; - min-height: 168px; - } - } - - .ui.tabular.menu { - margin: .5em; - } - - .footer { - border-top: 1px solid var(--color-secondary); - padding: 10px 0; - - .markup-info { - display: inline-block; - margin: 5px 0; - font-size: 12px; - color: var(--color-text-light); - } - - .ui.right.floated { - padding-top: 6px; - } - - &::after { - clear: both; - content: ""; - display: block; - } - } - - @media @mediaSm { - .button { - width: 100%; - margin: 0 !important; - margin-bottom: .75rem !important; - } - } -} - -.diff-file-body .comment-form { - margin: 0 0 0 3em; -} - -.file-comment { - color: var(--color-text); -} - -a.blob-excerpt { - color: var(--color-text-light); - height: 28px; - display: flex; - justify-content: center; - align-items: center; - width: 100%; - background: var(--color-expand-button); -} - -a.blob-excerpt:hover { - background: var(--color-primary); - color: var(--color-primary-contrast); -} - -// See the comment of createCommentEasyMDE() for the review editor -// EasyMDE's options can not handle minHeight & maxHeight together correctly, we have to set minHeight in JS code -.review-box-panel .CodeMirror-scroll { - min-height: 80px; - max-height: calc(100vh - 360px); -} - -@media @mediaSm { - .review-box-panel .CodeMirror-scroll { - max-width: calc(100vw - 70px); - } -} - -@media @mediaMd { - .review-box-panel .CodeMirror-scroll { - max-width: 700px; - } -} - -@media @mediaLg { - .review-box-panel .CodeMirror-scroll { - max-width: 800px; - } -} - -@media @mediaXl { - .review-box-panel .CodeMirror-scroll { - max-width: 900px; - } -} - -#review-box { - position: relative; -} - -.review-box-panel { - position: absolute; - min-width: max-content; - top: 45px; - right: -5px; - z-index: 2; -} - -#review-box .review-comments-counter { - background-color: var(--color-primary-light-4); - color: var(--color-primary-contrast); -} - -#review-box:hover .review-comments-counter { - background-color: var(--color-primary-light-5); -} - -#review-box .review-comments-counter[data-pending-comment-number="0"] { - display: none; -} - -.pull.files.diff [id] { - scroll-margin-top: 99px; - - @media @mediaMdAndDown { - scroll-margin-top: 130px; - } -} - -.changed-since-last-review { - border: 1px var(--color-accent) solid; - background-color: var(--color-small-accent); - border-radius: 15px; - padding: 4px 8px; - margin: -8px 0; // just like other buttons in the diff box header - font-size: .857rem; // just like .ui.tiny.button -} - -.viewed-file-form { - display: flex; - align-items: center; - border: 1px solid transparent; - padding: 4px 8px; - margin: -8px 0; // just like other buttons in the diff box header - border-radius: .285rem; // just like .ui.tiny.button - font-size: .857rem; // just like .ui.tiny.button -} - -.viewed-file-form input { - margin-right: 4px; -} - -.viewed-file-checked-form { - background-color: var(--color-small-accent); - border-color: var(--color-accent); -} - -#viewed-files-summary { - width: 72px; - height: 10px; -} - -.diff-file-box { - border-radius: .285rem; // Just like ui.top.attached.header -} - -.diff-file-box:target { - box-shadow: 0 0 0 3px var(--color-accent); -} diff --git a/web_src/less/_runner.less b/web_src/less/_runner.less deleted file mode 100644 index cebe345b0cfc..000000000000 --- a/web_src/less/_runner.less +++ /dev/null @@ -1,45 +0,0 @@ -@import "variables.less"; - -.runner-container { - padding-bottom: 30px; - .runner-ops > a { - margin-left: .5em; - } - .runner-ops-delete { - color: var(--color-red-light); - } - .runner-basic-info .gt-dib { - margin-right: 1em; - } - .runner-status-online { - .ui.label; - background-color: var(--color-green); - color: var(--color-white); - } - .runner-new-text { - color: var(--color-white); - } - #runner-new:hover .runner-new-text { - color: var(--color-white) !important; - } - .runner-new-menu { - width: 300px; - } - .task-status-success { - background-color: var(--color-green); - color: var(--color-white); - } - .task-status-failure { - background-color: var(--color-red-light); - color: var(--color-white); - } - .task-status-running { - background-color: var(--color-blue); - color: var(--color-white); - } - .task-status-cancelled, - .task-status-blocked { - background-color: var(--color-yellow); - color: var(--color-white); - } -} diff --git a/web_src/less/_user.less b/web_src/less/_user.less deleted file mode 100644 index eb9e791d86e8..000000000000 --- a/web_src/less/_user.less +++ /dev/null @@ -1,183 +0,0 @@ -@import "variables.less"; - -.user { - &.profile { - .ui.card { - .header { - display: block; - font-weight: 600; - font-size: 1.3rem; - margin-top: -.2rem; - line-height: 1.3rem; - } - - .profile-avatar-name { - border-top: none; - text-align: center; - } - - .extra.content { - padding: 0; - - ul { - margin: 0; - padding: 0; - - li { - padding: 10px; - list-style: none; - - &:not(:last-child) { - border-bottom: 1px solid var(--color-secondary); - } - - .svg { - margin-left: 1px; - margin-right: 5px; - } - - &.follow { - .ui.button { - width: 100%; - } - } - } - } - } - #profile-avatar { - background: none; - padding: 1rem 1rem .25rem; - justify-content: center; - img { - width: 100%; - height: auto; - object-fit: contain; - margin: 0; - @media @mediaSm { - width: 30vw; - } - } - - } - - @media @mediaSm { - width: 100%; - } - } - - .ui.repository.list { - margin-top: 25px; - } - - #loading-heatmap { - margin-bottom: 1em; - } - .ui.secondary.stackable.pointing.menu { - flex-wrap: wrap; - } - } - - &.followers { - .header.name { - font-size: 20px; - line-height: 24px; - vertical-align: middle; - } - - .follow { - .ui.button { - padding: 8px 15px; - } - } - } - - &.notification { - .svg { - float: left; - font-size: 2em; - - &.green { - color: var(--color-green); - } - - &.red { - color: var(--color-red); - } - - &.purple { - color: var(--color-purple); - } - - &.blue { - color: var(--color-blue); - } - } - - .content { - float: left; - margin-left: 7px; - } - - table { - form { - display: inline-block; - } - - button { - padding: 3px 3px 3px 5px; - } - - tr { - cursor: pointer; - } - } - } - - .button.adopt, - .button.delete { - margin-top: -15px; - margin-bottom: -15px; - .label { - vertical-align: middle; - } - } - - &.link-account:not(.icon) { - padding-top: 15px; - padding-bottom: 5px; - } - - &.settings { - .iconFloat { - float: left; - } - } -} - -.user-orgs { - display: flex; - flex-flow: row wrap; - padding: 0; - margin: -3px !important; - - li { - display: flex; - border-bottom: 0 !important; - padding: 3px !important; - width: 20%; - max-width: 60px; - } -} - -.user-badges { - display: grid; - grid-template-columns: repeat(auto-fill, 64px); - gap: 2px; -} - -.user-badges img { - object-fit: contain; -} -#notification_div .tab.segment { - overflow-x: auto; -} diff --git a/web_src/less/chroma/chroma-style-diff.go b/web_src/less/chroma/chroma-style-diff.go deleted file mode 100644 index 424325968955..000000000000 --- a/web_src/less/chroma/chroma-style-diff.go +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2023 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -//go:build ignore - -/* -This tool is used to compare the CSS names in a chroma builtin styles with the Gitea theme CSS names. - -It outputs the difference between the two sets of CSS names, eg: - -``` -CSS names not in builtin: -.chroma .ln ----- -Builtin CSS names not in file: -.chroma .vm -``` - -Developers could use this tool to re-sync the CSS names in the Gitea theme. -*/ - -package main - -import ( - "os" - "regexp" - "strings" - - "github.com/alecthomas/chroma/v2" -) - -func main() { - if len(os.Args) != 2 { - println("Usage: chroma-style-diff css-or-less-file") - os.Exit(1) - } - - data, err := os.ReadFile(os.Args[1]) - if err != nil { - println(err.Error()) - os.Exit(1) - } - - content := string(data) - - // a simple CSS parser to collect CSS names - content = regexp.MustCompile("//.*\r?\n").ReplaceAllString(content, "\n") - content = regexp.MustCompile("/\\*.*?\\*/").ReplaceAllString(content, "") - matches := regexp.MustCompile("\\s*([-.#:\\w\\s]+)\\s*\\{[^}]*}").FindAllStringSubmatch(content, -1) - - cssNames := map[string]bool{} - for _, matchGroup := range matches { - cssName := strings.TrimSpace(matchGroup[1]) - cssNames[cssName] = true - } - - // collect Chroma builtin CSS names - builtin := map[string]bool{} - for tokenType, cssName := range chroma.StandardTypes { - if tokenType > 0 && cssName != "" { - builtin[".chroma ."+cssName] = true - } - } - - // show the diff - println("CSS names not in builtin:") - for cssName := range cssNames { - if !builtin[cssName] { - println(cssName) - } - } - println("----") - println("Builtin CSS names not in file:") - for cssName := range builtin { - if !cssNames[cssName] { - println(cssName) - } - } -} diff --git a/web_src/less/codemirror/dark.less b/web_src/less/codemirror/dark.less deleted file mode 100644 index d0e954df5854..000000000000 --- a/web_src/less/codemirror/dark.less +++ /dev/null @@ -1,89 +0,0 @@ -.CodeMirror { - &.cm-s-default, - &.cm-s-paper { - .cm-property { - color: #a0cc75; - } - - .cm-header { - color: #9daccc; - } - - .cm-quote { - color: #009900; - } - - .cm-keyword { - color: #cc8a61; - } - - .cm-atom { - color: #ef5e77; - } - - .cm-number { - color: #ff5656; - } - - .cm-def { - color: #e4e4e4; - } - - .cm-variable-2 { - color: #00bdbf; - } - - .cm-variable-3 { - color: #008855; - } - - .cm-comment { - color: #8e9ab3; - } - - .cm-string { - color: #a77272; - } - - .cm-string-2 { - color: #ff5500; - } - - .cm-meta, - .cm-qualifier { - color: #ffb176; - } - - .cm-builtin { - color: #b7c951; - } - - .cm-bracket { - color: #999977; - } - - .cm-tag { - color: #f1d273; - } - - .cm-attribute { - color: #bfcc70; - } - - .cm-hr { - color: #999999; - } - - .cm-url { - color: #c5cfd0; - } - - .cm-link { - color: #d8c792; - } - - .cm-error { - color: #dbdbeb; - } - } -} diff --git a/web_src/less/features/gitgraph.less b/web_src/less/features/gitgraph.less deleted file mode 100644 index f6b1be5ba6b9..000000000000 --- a/web_src/less/features/gitgraph.less +++ /dev/null @@ -1,325 +0,0 @@ -#git-graph-container { - overflow-x: auto; - width: 100%; - min-height: 350px; - - > .ui.segment.loading { - border: 0; - z-index: 1; - min-height: 246px; - } - - h2 { - display: flex; - justify-content: space-between; - align-items: center; - } - - .color-buttons { - margin-right: 0; - } - - .ui.header.dividing { - padding-bottom: 10px; - } - - #flow-select-refs-dropdown { - border-top-right-radius: 0; - border-bottom-right-radius: 0; - min-width: 250px; - border-right: none; - - .ui.label { - max-width: 180px; - display: inline-flex !important; - align-items: center; - - .truncate { - display: inline-block; - max-width: 140px; - overflow: hidden; - text-overflow: ellipsis; - vertical-align: top; - white-space: nowrap; - } - } - - .dropdown.icon { - display: none; - } - - .default.text { - padding-top: 4px; - padding-bottom: 4px; - } - - input.search { - position: relative; - top: 1px; - } - } - - li { - list-style-type: none; - height: 24px; - line-height: 24px; - white-space: nowrap; - display: flex; - align-items: center; - - .node-relation { - font-family: var(--fonts-monospace); - } - - .author { - color: var(--color-text-light); - } - - .time { - color: var(--color-text-light-3); - font-size: 80%; - } - - a:not(.ui):hover { - text-decoration: underline; - } - - a em { - color: var(--color-red); - border-bottom: 1px dotted var(--color-secondary); - text-decoration: none; - font-style: normal; - } - } - - #rel-container { - max-width: 30%; - overflow-x: auto; - float: left; - } - - #rev-container { - width: 100%; - } - - #rev-list { - margin: 0; - padding: 0; - width: 100%; - - li.highlight.hover { - background-color: var(--color-secondary-alpha-30); - } - - .tags a.button { - padding: 2px 4px; - } - - .sha.label { - padding-top: 5px; - padding-bottom: 3px; - } - - .sha.label .shortsha { - padding-top: 0; - } - - .sha.label .shortsha-pad { - padding-right: 10px; - } - - .sha.label .ui.detail.icon.button { - padding-top: 3px; - margin-top: -5px; - padding-bottom: 1px; - } - - .author img.ui.avatar { - width: auto; - height: 18px; - max-width: none; - } - } - - #graph-raw-list { - margin: 0; - } - - &.monochrome #rel-container { - .flow-group { - stroke: var(--color-secondary-dark-5); - fill: var(--color-secondary-dark-5); - } - - .flow-group.highlight { - stroke: var(--color-secondary-dark-12); - fill: var(--color-secondary-dark-12); - } - } - - &:not(.monochrome) #rel-container { - .flow-group { - &.flow-color-16-1 { - stroke: #499a37; - fill: #499a37; - } - - &.flow-color-16-2 { - stroke: #ce4751; - fill: #ce4751; - } - - &.flow-color-16-3 { - stroke: #8f9121; - fill: #8f9121; - } - - &.flow-color-16-4 { - stroke: #ac32a6; - fill: #ac32a6; - } - - &.flow-color-16-5 { - stroke: #7445e9; - fill: #7445e9; - } - - &.flow-color-16-6 { - stroke: #c67d28; - fill: #c67d28; - } - - &.flow-color-16-7 { - stroke: #4db392; - fill: #4db392; - } - - &.flow-color-16-8 { - stroke: #aa4d30; - fill: #aa4d30; - } - - &.flow-color-16-9 { - stroke: #2a6f84; - fill: #2a6f84; - } - - &.flow-color-16-10 { - stroke: #c45327; - fill: #c45327; - } - - &.flow-color-16-11 { - stroke: #3d965c; - fill: #3d965c; - } - - &.flow-color-16-12 { - stroke: #792a93; - fill: #792a93; - } - - &.flow-color-16-13 { - stroke: #439d73; - fill: #439d73; - } - - &.flow-color-16-14 { - stroke: #103aad; - fill: #103aad; - } - - &.flow-color-16-15 { - stroke: #982e85; - fill: #982e85; - } - - &.flow-color-16-0 { - stroke: #7db233; - fill: #7db233; - } - } - - .flow-group.highlight { - &.flow-color-16-1 { - stroke: #5ac144; - fill: #5ac144; - } - - &.flow-color-16-2 { - stroke: #ed5a8b; - fill: #ed5a8b; - } - - &.flow-color-16-3 { - stroke: #ced049; - fill: #ced048; - } - - &.flow-color-16-4 { - stroke: #db61d7; - fill: #db62d6; - } - - &.flow-color-16-5 { - stroke: #8455f9; - fill: #8455f9; - } - - &.flow-color-16-6 { - stroke: #e6a151; - fill: #e6a151; - } - - &.flow-color-16-7 { - stroke: #44daaa; - fill: #44daaa; - } - - &.flow-color-16-8 { - stroke: #dd7a5c; - fill: #dd7a5c; - } - - &.flow-color-16-9 { - stroke: #38859c; - fill: #38859c; - } - - &.flow-color-16-10 { - stroke: #d95520; - fill: #d95520; - } - - &.flow-color-16-11 { - stroke: #42ae68; - fill: #42ae68; - } - - &.flow-color-16-12 { - stroke: #9126b5; - fill: #9126b5; - } - - &.flow-color-16-13 { - stroke: #4ab080; - fill: #4ab080; - } - - &.flow-color-16-14 { - stroke: #284fb8; - fill: #284fb8; - } - - &.flow-color-16-15 { - stroke: #971c80; - fill: #971c80; - } - - &.flow-color-16-0 { - stroke: #87ca28; - fill: #87ca28; - } - } - } -} diff --git a/web_src/less/features/heatmap.less b/web_src/less/features/heatmap.less deleted file mode 100644 index a6280e8b5142..000000000000 --- a/web_src/less/features/heatmap.less +++ /dev/null @@ -1,67 +0,0 @@ -#user-heatmap { - width: 100%; - font-size: 9px; - position: relative; - min-height: 125px; - - text { - fill: currentcolor !important; - } - - // for the "Less" and "More" legend - .vch__legend .vch__legend { - display: flex; - font-size: 11px; - align-items: center; - justify-content: right; - } - .vch__legend .vch__legend div:first-child, - .vch__legend .vch__legend div:last-child { - display: inline-block; - padding: 0 5px; - } - - // move the "? contributions in the last ? months" text from top to bottom - .total-contributions { - font-size: 11px; - position: absolute; - bottom: 0; - left: 25px; - } - - @media @mediaLgAndDown { - & { - min-height: 105px; - } - .total-contributions { - left: 21px; - } - } - - @media (max-width: 1000px) { - & { - min-height: 80px; - } - .total-contributions { - font-size: 10px; - left: 17px; - bottom: -4px; - } - } -} - -.user.profile #user-heatmap { - min-height: 135px; -} - -@media @mediaLgAndDown { - .user.profile #user-heatmap { - min-height: 115px; - } -} - -@media (max-width: 1000px) { - .user.profile #user-heatmap { - min-height: 90px; - } -} diff --git a/web_src/less/features/imagediff.less b/web_src/less/features/imagediff.less deleted file mode 100644 index 07763c15e126..000000000000 --- a/web_src/less/features/imagediff.less +++ /dev/null @@ -1,105 +0,0 @@ -.image-diff-container { - text-align: center; - padding: 1em 0; - - img { - border: 1px solid var(--color-primary-light-7); - background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAG0lEQVQYlWN4+vTpf3SMDTAMBYXYBLFpHgoKAeiOf0SGE9kbAAAAAElFTkSuQmCC") right bottom var(--color-primary-light-7); - } - - .before-container { - border: 1px solid var(--color-red); - display: block; - } - - .after-container { - border: 1px solid var(--color-green); - display: block; - } - - .diff-side-by-side { - .side { - display: inline-block; - line-height: 0; - vertical-align: top; - margin: 0 1em; - - .side-header { - font-weight: bold; - } - } - } - - .diff-swipe { - margin: auto; - - .swipe-frame { - position: absolute; - - .before-container { - position: absolute; - } - - .swipe-container { - position: absolute; - right: 0; - display: block; - border-left: 2px solid var(--color-secondary-dark-8); - height: 100%; - overflow: hidden; - - .after-container { - position: absolute; - right: 0; - } - } - - .swipe-bar { - position: absolute; - height: 100%; - top: 0; - left: 0; - - .handle { - background: var(--color-secondary-dark-8); - left: -5px; - height: 12px; - width: 12px; - position: absolute; - transform: rotate(45deg); - box-sizing: border-box; - display: flex; - justify-content: center; - align-items: center; - cursor: pointer; - } - - .top-handle { - top: -12px; - } - - .bottom-handle { - bottom: -14px; - } - } - } - } - - .diff-overlay { - margin: 0 auto; - - .overlay-frame { - margin: 0 auto; - position: relative; - } - - .before-container, - .after-container { - position: absolute; - } - - input { - max-width: 300px; - } - } -} diff --git a/web_src/less/index.less b/web_src/less/index.less deleted file mode 100644 index 5d55b9291f6c..000000000000 --- a/web_src/less/index.less +++ /dev/null @@ -1,42 +0,0 @@ -@import "font-awesome/css/font-awesome.css"; - -@import "./variables.less"; -@import "./animations.less"; -@import "./shared/issuelist.less"; -@import "./features/dropzone.less"; -@import "./features/gitgraph.less"; -@import "./features/heatmap.less"; -@import "./features/imagediff.less"; -@import "./features/codeeditor.less"; -@import "./features/projects.less"; -@import "./modules/tippy.less"; -@import "./markup/content.less"; -@import "./markup/codecopy.less"; -@import "./code/linebutton.less"; -@import "./markup/asciicast.less"; - -@import "./chroma/base.less"; -@import "./chroma/light.less"; -@import "./codemirror/base.less"; -@import "./codemirror/light.less"; -@import "./console/console.less"; - -@import "_svg"; -@import "_tribute"; -@import "_font_i18n"; -@import "_base"; -@import "_home"; -@import "_install"; -@import "_form"; -@import "_repository"; -@import "_editor"; -@import "_organization"; -@import "_user"; -@import "_dashboard"; -@import "_admin"; -@import "_explore"; -@import "_review"; -@import "_package"; -@import "_runner"; - -@import "./helpers.less"; diff --git a/web_src/less/markup/content.less b/web_src/less/markup/content.less deleted file mode 100644 index 725a3d9886f5..000000000000 --- a/web_src/less/markup/content.less +++ /dev/null @@ -1,559 +0,0 @@ -.markup { - overflow: hidden; - font-size: 16px; - line-height: 1.5 !important; - word-wrap: break-word; - - &.ui.segment { - padding: 3em; - } - - &.file-view { - padding: 2em !important; - } - - > *:first-child { - margin-top: 0 !important; - } - - > *:last-child { - margin-bottom: 0 !important; - } - - a:not([href]) { - color: inherit; - text-decoration: none; - } - - .absent { - color: var(--color-red); - } - - .anchor { - padding-right: 4px; - margin-left: -20px; - line-height: 1; - color: inherit; - } - - .anchor .svg { - vertical-align: middle; - } - - .anchor:focus { - outline: none; - } - - h1 .anchor .svg, - h2 .anchor .svg, - h3 .anchor .svg, - h4 .anchor .svg, - h5 .anchor .svg, - h6 .anchor .svg { - visibility: hidden; - } - - h1:hover .anchor .svg, - h2:hover .anchor .svg, - h3:hover .anchor .svg, - h4:hover .anchor .svg, - h5:hover .anchor .svg, - h6:hover .anchor .svg { - visibility: visible; - } - - h2 .anchor .svg, - h3 .anchor .svg, - h4 .anchor .svg { - position: relative; - top: -2px; - } - - h1, - h2, - h3, - h4, - h5, - h6 { - margin-top: 24px; - margin-bottom: 16px; - font-weight: 600; - line-height: 1.25; - } - - h1 tt, - h1 code, - h2 tt, - h2 code, - h3 tt, - h3 code, - h4 tt, - h4 code, - h5 tt, - h5 code, - h6 tt, - h6 code { - font-size: inherit; - } - - h1 { - padding-bottom: .3em; - font-size: 2em; - border-bottom: 1px solid var(--color-secondary); - } - - h2 { - padding-bottom: .3em; - font-size: 1.5em; - border-bottom: 1px solid var(--color-secondary); - } - - h3 { - font-size: 1.25em; - } - - h4 { - font-size: 1em; - } - - h5 { - font-size: .875em; - } - - h6 { - font-size: .85em; - color: var(--color-text-light-2); - } - - p, - blockquote, - details, - ul, - ol, - dl, - table, - pre { - margin-top: 0; - margin-bottom: 16px; - } - - hr { - height: 4px; - padding: 0; - margin: 16px 0; - background-color: var(--color-secondary); - border: 0; - } - - ul, - ol { - padding-left: 2em; - } - - ul.no-list, - ol.no-list { - padding: 0; - list-style-type: none; - } - - .task-list-item { - list-style-type: none; - position: relative; - line-height: 1.5rem; - min-height: 1.5rem; // to render a checkbox list without content `- [ ]`, we need this min-height to make sure the
  • can be visible - - input[type="checkbox"] { - position: absolute; - top: .25em; - left: -1.6em; - } - - p { - line-height: 1.5rem; - } - } - - .task-list-item + .task-list-item { - margin-top: 3px; - } - - input[type="checkbox"] { - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - position: relative; - border: 1px solid var(--color-secondary); - border-radius: 2px; - background: var(--color-input-background); - height: 14px; - width: 14px; - opacity: 1 !important; // override fomantic on edit preview - pointer-events: auto !important; // override fomantic on edit preview - vertical-align: middle !important; // override fomantic on edit preview - -webkit-print-color-adjust: exact; - color-adjust: exact; - } - - input[type="checkbox"]:not([disabled]):hover, - input[type="checkbox"]:not([disabled]):active { - border-color: var(--color-primary); - } - - input[type="checkbox"]::after { - position: absolute; - left: 0; - top: 0; - bottom: 0; - right: 0; - pointer-events: none; - background: var(--color-text); - mask-size: cover; - -webkit-mask-size: cover; - } - - input[type="checkbox"]:checked::after { - content: ""; - mask-image: var(--checkbox-mask-checked); - -webkit-mask-image: var(--checkbox-mask-checked); - -webkit-print-color-adjust: exact; - color-adjust: exact; - } - - input[type="checkbox"]:indeterminate::after { - content: ""; - mask-image: var(--checkbox-mask-indeterminate); - -webkit-mask-image: var(--checkbox-mask-indeterminate); - } - - ul ul, - ul ol, - ol ol, - ol ul { - margin-top: 0; - margin-bottom: 0; - } - - ol ol, - ul ol { - list-style-type: lower-roman; - } - - li > p { - margin-top: 16px; - } - - li + li { - margin-top: .25em; - } - - dl { - padding: 0; - } - - dl dt { - padding: 0; - margin-top: 16px; - font-size: 1em; - font-style: italic; - font-weight: 600; - } - - dl dd { - padding: 0 16px; - margin-bottom: 16px; - } - - blockquote { - margin-left: 0; - padding: 0 15px; - color: var(--color-text-light-2); - border-left: 4px solid var(--color-secondary); - } - - blockquote > :first-child { - margin-top: 0; - } - - blockquote > :last-child { - margin-bottom: 0; - } - - table { - display: block; - width: 100%; - width: max-content; - max-width: 100%; - overflow: auto; - } - - table th { - font-weight: 600; - } - - table th, - table td { - padding: 6px 13px !important; - border: 1px solid var(--color-secondary) !important; - } - - table tr { - border-top: 1px solid var(--color-secondary); - } - - table tr:nth-child(2n) { - background-color: var(--color-markup-table-row); - } - - img { - max-width: 100%; - box-sizing: initial; - } - - img[align="right"] { - padding-left: 20px; - } - - img[align="left"] { - padding-right: 20px; - } - - .emoji { - max-width: none; - vertical-align: text-top; - } - - span.frame { - display: block; - overflow: hidden; - } - - span.frame > span { - display: block; - float: left; - width: auto; - padding: 7px; - margin: 13px 0 0; - overflow: hidden; - border: 1px solid var(--color-secondary); - } - - span.frame span img { - display: block; - float: left; - } - - span.frame span span { - display: block; - padding: 5px 0 0; - clear: both; - color: var(--color-text); - } - - span.align-center { - display: block; - overflow: hidden; - clear: both; - } - - span.align-center > span { - display: block; - margin: 13px auto 0; - overflow: hidden; - text-align: center; - } - - span.align-center span img { - margin: 0 auto; - text-align: center; - } - - span.align-right { - display: block; - overflow: hidden; - clear: both; - } - - span.align-right > span { - display: block; - margin: 13px 0 0; - overflow: hidden; - text-align: right; - } - - span.align-right span img { - margin: 0; - text-align: right; - } - - span.float-left { - display: block; - float: left; - margin-right: 13px; - overflow: hidden; - } - - span.float-left span { - margin: 13px 0 0; - } - - span.float-right { - display: block; - float: right; - margin-left: 13px; - overflow: hidden; - } - - span.float-right > span { - display: block; - margin: 13px auto 0; - overflow: hidden; - text-align: right; - } - - code, - tt { - padding: .2em .4em; - margin: 0; - font-size: 85%; - white-space: break-spaces; - background-color: var(--color-markup-code-block); - border-radius: 4px; - } - - code br, - tt br { - display: none; - } - - del code { - text-decoration: inherit; - } - - pre > code { - padding: 0; - margin: 0; - font-size: 100%; - white-space: pre-wrap; - word-break: break-all; - overflow-wrap: break-word; - background: transparent; - border: 0; - } - - .highlight { - margin-bottom: 16px; - } - - .highlight pre, - pre { - padding: 16px; - font-size: 85%; - line-height: 1.45; - background-color: var(--color-markup-code-block); - border-radius: 4px; - } - - .highlight pre { - margin-bottom: 0; - word-break: normal; - } - - pre { - word-wrap: normal; - } - - pre code, - pre tt { - display: inline; - max-width: initial; - padding: 0; - margin: 0; - overflow: initial; - line-height: inherit; - word-wrap: normal; - background-color: transparent; - border: 0; - } - - pre code::before, - pre code::after, - pre tt::before, - pre tt::after { - content: normal; - } - - kbd { - display: inline-block; - padding: 3px 5px; - font-size: 11px; - line-height: 10px; - color: var(--color-text-light); - vertical-align: middle; - background-color: var(--color-markup-code-block); - border: 1px solid var(--color-secondary); - border-radius: 3px; - box-shadow: inset 0 -1px 0 var(--color-secondary); - } - - .ui.list .list, - ol.ui.list ol, - ul.ui.list ul { - padding-left: 2em; - } -} - -.repository.wiki.revisions { - .ui.container > .ui.stackable.grid { - -ms-flex-direction: row-reverse; - flex-direction: row-reverse; - - > .header { - margin-top: 0; - - .sub.header { - padding-left: 52px; - word-break: break-word; - } - } - } -} - -.file-revisions-btn { - display: block; - float: left; - margin-bottom: 2px !important; - padding: 11px !important; - margin-right: 10px !important; - - i { - &:extend(.unselectable); - } -} - -.markup-render { - display: block; - border: none; - width: 100%; - height: var(--height-loading); // actual height is set in JS after loading - overflow: hidden; - color-scheme: normal; // match the value inside the iframe to allow it to become transparent -} - -.markup-block-error { - border: 1px solid var(--color-error-border) !important; - margin-bottom: 0 !important; - border-bottom-left-radius: 0 !important; - border-bottom-right-radius: 0 !important; - box-shadow: none !important; - font-size: 85% !important; - white-space: pre-wrap !important; - padding: .5rem 1rem !important; - text-align: left !important; -} - -.markup-block-error + pre { - border-top: none !important; - margin-top: 0 !important; - border-top-left-radius: 0 !important; - border-top-right-radius: 0 !important; -} diff --git a/web_src/less/shared/issuelist.less b/web_src/less/shared/issuelist.less deleted file mode 100644 index 8d4cfc46d491..000000000000 --- a/web_src/less/shared/issuelist.less +++ /dev/null @@ -1,151 +0,0 @@ -.issue.list { - list-style: none; - margin-top: 1rem; - - a:not(.label):hover { - color: var(--color-primary) !important; - } - - > .item { - .issue-checkbox { - margin-top: 1px; - } - - .issue-item-icon svg { - margin-right: .75rem; - margin-top: 1px; - } - - .issue-item-icons-right > * + * { - margin-left: .5rem; - } - - .issue-item-main { - width: 100%; - } - - .issue-item-top-row { - max-width: 100%; - color: var(--color-text); - font-size: 16px; - min-width: 0; - font-weight: 600; - } - - .labels-list { - position: relative; - top: -1.5px; - } - - .issue-item-bottom-row { - font-size: 13px; - } - - .title { - color: var(--color-text); - word-break: break-word; - } - - .issue-item-icon-right { - min-width: 2rem; - } - - .assignee { - position: relative; - top: -2px; - } - - .assignee img { - width: 20px; - height: 20px; - margin-right: 2px; - } - - .desc { - color: var(--color-text-light-2); - - a { - color: inherit; - } - - .time-since, - a { - margin-left: .25rem; - margin-right: .25rem; - } - - .waiting, - .approvals, - .rejects { - padding-left: 5px; - } - - .checklist { - padding-left: 5px; - - progress { - margin-left: 2px; - width: 80px; - height: 6px; - display: inline-block; - border-radius: 3px; - vertical-align: 2px !important; - } - - progress::-webkit-progress-value { - background-color: var(--color-secondary-dark-4); - } - - progress::-moz-progress-bar { - background-color: var(--color-secondary-dark-4); - } - } - - .conflicting { - padding-left: 5px; - } - - .due-date { - padding-left: 5px; - } - - a.milestone, - a.project { - margin-left: 5px; - } - - a.ref { - margin-left: 8px; - - span { - margin-right: -4px; - } - } - - .overdue { - color: var(--color-red); - } - } - } - - .branches { - display: inline-flex; - padding: 0 4px; - - .branch { - background-color: var(--color-secondary); - border-radius: 3px; - } - - .truncated-name { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - max-width: 10em; - } - } - - > .item + .item { - border-top: 1px solid var(--color-secondary); - } -} diff --git a/web_src/less/themes/theme-auto.less b/web_src/less/themes/theme-auto.less deleted file mode 100644 index f49e194e1d64..000000000000 --- a/web_src/less/themes/theme-auto.less +++ /dev/null @@ -1,3 +0,0 @@ -@media (prefers-color-scheme: dark) { - @import "theme-arc-green.less"; -} diff --git a/web_src/less/variables.less b/web_src/less/variables.less deleted file mode 100644 index 23f6ac6de9e0..000000000000 --- a/web_src/less/variables.less +++ /dev/null @@ -1,14 +0,0 @@ -// here a standard set of media queries is defined, that is compatible with the -// responsive grid used in fomantic css. As there only is a precompiled build -// of fomantic checked in (since 946bbbe), we can't use their less variables -// here, but these breakpoints shouldn't change in the foreseeable future. - -@mediaMdAndUp: ~"(min-width: 768px)"; -@mediaMdAndDown: ~"(max-width: 991px)"; -@mediaLgAndUp: ~"(min-width: 992px)"; -@mediaLgAndDown: ~"(max-width: 1200px)"; - -@mediaSm: ~"(max-width: 767px)"; -@mediaMd: @mediaMdAndUp and @mediaMdAndDown; -@mediaLg: @mediaLgAndUp and @mediaLgAndDown; -@mediaXl: ~"(min-width: 1201px)"; diff --git a/web_src/svg/fontawesome-save.svg b/web_src/svg/fontawesome-save.svg new file mode 100644 index 000000000000..763d26abb1c3 --- /dev/null +++ b/web_src/svg/fontawesome-save.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/web_src/svg/gitea-swift.svg b/web_src/svg/gitea-swift.svg new file mode 100644 index 000000000000..8af43d32e466 --- /dev/null +++ b/web_src/svg/gitea-swift.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/webpack.config.js b/webpack.config.js index 245791e7ea6e..ec8a19594068 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -21,7 +21,7 @@ const glob = (pattern) => fastGlob.sync(pattern, { }); const themes = {}; -for (const path of glob('web_src/less/themes/*.less')) { +for (const path of glob('web_src/css/themes/*.css')) { themes[parse(path).name] = [path]; } @@ -57,14 +57,14 @@ export default { fileURLToPath(new URL('web_src/js/index.js', import.meta.url)), fileURLToPath(new URL('node_modules/easymde/dist/easymde.min.css', import.meta.url)), fileURLToPath(new URL('web_src/fomantic/build/semantic.css', import.meta.url)), - fileURLToPath(new URL('web_src/less/index.less', import.meta.url)), + fileURLToPath(new URL('web_src/css/index.css', import.meta.url)), ], webcomponents: [ fileURLToPath(new URL('web_src/js/webcomponents/GiteaOriginUrl.js', import.meta.url)), ], swagger: [ fileURLToPath(new URL('web_src/js/standalone/swagger.js', import.meta.url)), - fileURLToPath(new URL('web_src/less/standalone/swagger.less', import.meta.url)), + fileURLToPath(new URL('web_src/css/standalone/swagger.css', import.meta.url)), ], serviceworker: [ fileURLToPath(new URL('web_src/js/serviceworker.js', import.meta.url)), @@ -136,7 +136,7 @@ export default { ], }, { - test: /.css$/i, + test: /\.css$/i, use: [ { loader: MiniCssExtractPlugin.loader, @@ -151,29 +151,6 @@ export default { }, ], }, - { - test: /.less$/i, - use: [ - { - loader: MiniCssExtractPlugin.loader, - }, - { - loader: 'css-loader', - options: { - sourceMap: true, - importLoaders: 1, - url: {filter: filterCssImport}, - import: {filter: filterCssImport}, - }, - }, - { - loader: 'less-loader', - options: { - sourceMap: true, - }, - }, - ], - }, { test: /\.svg$/, include: fileURLToPath(new URL('public/img/svg', import.meta.url)), @@ -196,6 +173,10 @@ export default { ], }, plugins: [ + new webpack.DefinePlugin({ + __VUE_OPTIONS_API__: true, // at the moment, many Vue components still use the Vue Options API + __VUE_PROD_DEVTOOLS__: false, // do not enable devtools support in production + }), new VueLoaderPlugin(), new MiniCssExtractPlugin({ filename: 'css/[name].css',