mirror of
https://github.com/overleaf/overleaf.git
synced 2025-12-05 01:10:29 +00:00
Compare commits
16 Commits
f028f21e3c
...
5b8f6f83be
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5b8f6f83be | ||
|
|
5730fb993a | ||
|
|
a67d70c74a | ||
|
|
c0c3bfe185 | ||
|
|
ccf1fb8fcb | ||
|
|
c059a3c5b0 | ||
|
|
7d0e75e4f7 | ||
|
|
44b79c895f | ||
|
|
ae6dec9dcb | ||
|
|
e7cc70baf7 | ||
|
|
67aa42a57a | ||
|
|
4ca1407ab9 | ||
|
|
7c9fea64ac | ||
|
|
59aab0878d | ||
|
|
c4b3cd2a77 | ||
|
|
1479df36db |
@@ -22,7 +22,7 @@
|
||||
"effect": "^3.19.0",
|
||||
"lucide-react": "^0.548.0",
|
||||
"motion": "^12.23.24",
|
||||
"nanoid": "^4.0.2",
|
||||
"nanoid": "^5.0.0",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"streamdown": "^1.4.0",
|
||||
|
||||
73
package-lock.json
generated
73
package-lock.json
generated
@@ -128,7 +128,7 @@
|
||||
"effect": "^3.19.0",
|
||||
"lucide-react": "^0.548.0",
|
||||
"motion": "^12.23.24",
|
||||
"nanoid": "^4.0.2",
|
||||
"nanoid": "^5.0.0",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"streamdown": "^1.4.0",
|
||||
@@ -15663,6 +15663,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@pollyjs/adapter-node-http/-/adapter-node-http-6.0.6.tgz",
|
||||
"integrity": "sha512-jdJG7oncmSHZAtVMmRgOxh5A56b7G8H9ULlk/ZaVJ+jNrlFXhLmPpx8OQoSF4Cuq2ugdiWmwmAjFXHStcpY3Mw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@pollyjs/adapter": "^6.0.6",
|
||||
"@pollyjs/utils": "^6.0.6",
|
||||
@@ -15675,6 +15676,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@pollyjs/core/-/core-6.0.6.tgz",
|
||||
"integrity": "sha512-1ZZcmojW8iSFmvHGeLlvuudM3WiDV842FsVvtPAo3HoAYE6jCNveLHJ+X4qvonL4enj1SyTF3hXA107UkQFQrA==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@pollyjs/utils": "^6.0.6",
|
||||
"@sindresorhus/fnv1a": "^2.0.1",
|
||||
@@ -15732,6 +15734,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@pollyjs/persister-fs/-/persister-fs-6.0.6.tgz",
|
||||
"integrity": "sha512-/ALVgZiH2zGqwLkW0Mntc0Oq1v7tR8LS8JD2SAyIsHpnSXeBUnfPWwjAuYw0vqORHFVEbwned6MBRFfvU/3qng==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@pollyjs/node-server": "^6.0.6",
|
||||
"@pollyjs/persister": "^6.0.6"
|
||||
@@ -23229,6 +23232,25 @@
|
||||
"preact": "^10.5.13"
|
||||
}
|
||||
},
|
||||
"node_modules/@uppy/core/node_modules/nanoid": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.2.tgz",
|
||||
"integrity": "sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"nanoid": "bin/nanoid.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14 || ^16 || >=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@uppy/informer": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@uppy/informer/-/informer-3.1.0.tgz",
|
||||
@@ -23267,6 +23289,25 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@uppy/provider-views/node_modules/nanoid": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.2.tgz",
|
||||
"integrity": "sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"nanoid": "bin/nanoid.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14 || ^16 || >=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@uppy/provider-views/node_modules/p-queue": {
|
||||
"version": "7.4.1",
|
||||
"resolved": "https://registry.npmjs.org/p-queue/-/p-queue-7.4.1.tgz",
|
||||
@@ -42395,9 +42436,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.2.tgz",
|
||||
"integrity": "sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==",
|
||||
"version": "5.1.6",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.6.tgz",
|
||||
"integrity": "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@@ -42409,7 +42450,7 @@
|
||||
"nanoid": "bin/nanoid.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14 || ^16 || >=18"
|
||||
"node": "^18 || >=20"
|
||||
}
|
||||
},
|
||||
"node_modules/nanomatch": {
|
||||
@@ -57090,6 +57131,9 @@
|
||||
"devDependencies": {
|
||||
"@overleaf/fetch-utils": "*",
|
||||
"@overleaf/migrations": "*",
|
||||
"@pollyjs/adapter-node-http": "^6.0.6",
|
||||
"@pollyjs/core": "^6.0.6",
|
||||
"@pollyjs/persister-fs": "^6.0.6",
|
||||
"chai": "^4.3.6",
|
||||
"chai-as-promised": "^7.1.1",
|
||||
"mocha": "^11.1.0",
|
||||
@@ -59543,6 +59587,25 @@
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"services/web/node_modules/nanoid": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.2.tgz",
|
||||
"integrity": "sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"nanoid": "bin/nanoid.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14 || ^16 || >=18"
|
||||
}
|
||||
},
|
||||
"services/web/node_modules/nise": {
|
||||
"version": "1.5.3",
|
||||
"resolved": "https://registry.npmjs.org/nise/-/nise-1.5.3.tgz",
|
||||
|
||||
@@ -4,13 +4,14 @@
|
||||
|
||||
BUILD_NUMBER ?= local
|
||||
BRANCH_NAME ?= $(shell git rev-parse --abbrev-ref HEAD)
|
||||
BRANCH_NAME_TAG_SAFE = $(shell echo $(BRANCH_NAME) | sed 's/\//\-\-/g')
|
||||
PROJECT_NAME = chat
|
||||
BUILD_DIR_NAME = $(shell pwd | xargs basename | tr -cd '[a-zA-Z0-9_.\-]')
|
||||
HERE=$(shell pwd)
|
||||
export MONOREPO ?= $(shell cd ../../ && pwd)
|
||||
IMAGE_CI ?= ci/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER)
|
||||
IMAGE_CI ?= ci/$(PROJECT_NAME):$(BRANCH_NAME_TAG_SAFE)-$(BUILD_NUMBER)
|
||||
IMAGE_REPO ?= us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME)
|
||||
IMAGE_REPO_FINAL ?= $(IMAGE_REPO):$(BRANCH_NAME)-$(BUILD_NUMBER)
|
||||
IMAGE_REPO_FINAL ?= $(IMAGE_REPO):$(BRANCH_NAME_TAG_SAFE)-$(BUILD_NUMBER)
|
||||
IMAGE_CACHE ?= $(IMAGE_REPO):cache-$(shell cat \
|
||||
$(MONOREPO)/package.json \
|
||||
$(MONOREPO)/package-lock.json \
|
||||
@@ -28,7 +29,7 @@ IMAGE_CACHE ?= $(IMAGE_REPO):cache-$(shell cat \
|
||||
|
||||
DOCKER_COMPOSE_FLAGS ?= -f docker-compose.yml
|
||||
DOCKER_COMPOSE := BUILD_NUMBER=$(BUILD_NUMBER) \
|
||||
BRANCH_NAME=$(BRANCH_NAME) \
|
||||
BRANCH_NAME=$(BRANCH_NAME_TAG_SAFE) \
|
||||
PROJECT_NAME=$(PROJECT_NAME) \
|
||||
MOCHA_GREP=${MOCHA_GREP} \
|
||||
docker compose ${DOCKER_COMPOSE_FLAGS}
|
||||
|
||||
@@ -4,13 +4,14 @@
|
||||
|
||||
BUILD_NUMBER ?= local
|
||||
BRANCH_NAME ?= $(shell git rev-parse --abbrev-ref HEAD)
|
||||
BRANCH_NAME_TAG_SAFE = $(shell echo $(BRANCH_NAME) | sed 's/\//\-\-/g')
|
||||
PROJECT_NAME = clsi
|
||||
BUILD_DIR_NAME = $(shell pwd | xargs basename | tr -cd '[a-zA-Z0-9_.\-]')
|
||||
HERE=$(shell pwd)
|
||||
export MONOREPO ?= $(shell cd ../../ && pwd)
|
||||
IMAGE_CI ?= ci/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER)
|
||||
IMAGE_CI ?= ci/$(PROJECT_NAME):$(BRANCH_NAME_TAG_SAFE)-$(BUILD_NUMBER)
|
||||
IMAGE_REPO ?= us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME)
|
||||
IMAGE_REPO_FINAL ?= $(IMAGE_REPO):$(BRANCH_NAME)-$(BUILD_NUMBER)
|
||||
IMAGE_REPO_FINAL ?= $(IMAGE_REPO):$(BRANCH_NAME_TAG_SAFE)-$(BUILD_NUMBER)
|
||||
IMAGE_CACHE ?= $(IMAGE_REPO):cache-$(shell cat \
|
||||
$(MONOREPO)/package.json \
|
||||
$(MONOREPO)/package-lock.json \
|
||||
@@ -27,7 +28,7 @@ IMAGE_CACHE ?= $(IMAGE_REPO):cache-$(shell cat \
|
||||
|
||||
DOCKER_COMPOSE_FLAGS ?= -f docker-compose.yml
|
||||
DOCKER_COMPOSE := BUILD_NUMBER=$(BUILD_NUMBER) \
|
||||
BRANCH_NAME=$(BRANCH_NAME) \
|
||||
BRANCH_NAME=$(BRANCH_NAME_TAG_SAFE) \
|
||||
PROJECT_NAME=$(PROJECT_NAME) \
|
||||
MOCHA_GREP=${MOCHA_GREP} \
|
||||
docker compose ${DOCKER_COMPOSE_FLAGS}
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
overleaf/clsi
|
||||
===============
|
||||
# overleaf/clsi
|
||||
|
||||
A web api for compiling LaTeX documents in the cloud
|
||||
|
||||
The Common LaTeX Service Interface (CLSI) provides a RESTful interface to traditional LaTeX tools (or, more generally, any command line tool for composing marked-up documents into a display format such as PDF or HTML). The CLSI listens on the following ports by default:
|
||||
|
||||
* TCP/3013 - the RESTful interface
|
||||
* TCP/3048 - reports load information
|
||||
* TCP/3049 - HTTP interface to control the CLSI service
|
||||
- TCP/3013 - the RESTful interface
|
||||
- TCP/3048 - reports load information
|
||||
- TCP/3049 - HTTP interface to control the CLSI service
|
||||
|
||||
These defaults can be modified in `config/settings.defaults.js`.
|
||||
|
||||
@@ -15,29 +14,28 @@ The provided `Dockerfile` builds a Docker image which has the Docker command lin
|
||||
|
||||
The CLSI can be configured through the following environment variables:
|
||||
|
||||
* `ALLOWED_COMPILE_GROUPS` - Space separated list of allowed compile groups
|
||||
* `ALLOWED_IMAGES` - Space separated list of allowed Docker TeX Live images
|
||||
* `CATCH_ERRORS` - Set to `true` to log uncaught exceptions
|
||||
* `COMPILE_GROUP_DOCKER_CONFIGS` - JSON string of Docker configs for compile groups
|
||||
* `SANDBOXED_COMPILES` - Set to true to use sibling containers
|
||||
* `SANDBOXED_COMPILES_HOST_DIR_COMPILES` - Working directory for LaTeX compiles
|
||||
* `SANDBOXED_COMPILES_HOST_DIR_OUTPUT` - Output directory for LaTeX compiles
|
||||
* `COMPILE_SIZE_LIMIT` - Sets the body-parser [limit](https://github.com/expressjs/body-parser#limit)
|
||||
* `DOCKER_RUNTIME` -
|
||||
* `FILESTORE_DOMAIN_OVERRIDE` - The url for the filestore service e.g.`http://$FILESTORE_HOST:3009`
|
||||
* `FILESTORE_PARALLEL_FILE_DOWNLOADS` - Number of parallel file downloads
|
||||
* `LISTEN_ADDRESS` - The address for the RESTful service to listen on. Set to `0.0.0.0` to listen on all network interfaces
|
||||
* `PROCESS_LIFE_SPAN_LIMIT_MS` - Process life span limit in milliseconds
|
||||
* `SMOKE_TEST` - Whether to run smoke tests
|
||||
* `TEXLIVE_IMAGE` - The TeX Live Docker image to use for sibling containers, e.g. `us-east1-docker.pkg.dev/overleaf-ops/ol-docker/texlive-full:2017.1`
|
||||
* `TEX_LIVE_IMAGE_NAME_OVERRIDE` - The name of the registry for the Docker image e.g. `us-east1-docker.pkg.dev/overleaf-ops/ol-docker`
|
||||
* `TEXLIVE_IMAGE_USER` - When using sibling containers, the user to run as in the TeX Live image. Defaults to `tex`
|
||||
* `TEXLIVE_OPENOUT_ANY` - Sets the `openout_any` environment variable for TeX Live (see the `\openout` primitive [documentation](http://tug.org/texinfohtml/web2c.html#tex-invocation))
|
||||
- `ALLOWED_COMPILE_GROUPS` - Space separated list of allowed compile groups
|
||||
- `ALLOWED_IMAGES` - Space separated list of allowed Docker TeX Live images
|
||||
- `CATCH_ERRORS` - Set to `true` to log uncaught exceptions
|
||||
- `COMPILE_GROUP_DOCKER_CONFIGS` - JSON string of Docker configs for compile groups
|
||||
- `SANDBOXED_COMPILES` - Set to true to use sibling containers
|
||||
- `SANDBOXED_COMPILES_HOST_DIR_COMPILES` - Working directory for LaTeX compiles
|
||||
- `SANDBOXED_COMPILES_HOST_DIR_OUTPUT` - Output directory for LaTeX compiles
|
||||
- `COMPILE_SIZE_LIMIT` - Sets the body-parser [limit](https://github.com/expressjs/body-parser#limit)
|
||||
- `DOCKER_RUNTIME` -
|
||||
- `FILESTORE_DOMAIN_OVERRIDE` - The url for the filestore service e.g.`http://$FILESTORE_HOST:3009`
|
||||
- `FILESTORE_PARALLEL_FILE_DOWNLOADS` - Number of parallel file downloads
|
||||
- `LISTEN_ADDRESS` - The address for the RESTful service to listen on. Set to `0.0.0.0` to listen on all network interfaces
|
||||
- `PROCESS_LIFE_SPAN_LIMIT_MS` - Process life span limit in milliseconds
|
||||
- `SMOKE_TEST` - Whether to run smoke tests
|
||||
- `TEXLIVE_IMAGE` - The TeX Live Docker image to use for sibling containers, e.g. `us-east1-docker.pkg.dev/overleaf-ops/ol-docker/texlive-full:2025.1`
|
||||
- `TEX_LIVE_IMAGE_NAME_OVERRIDE` - The name of the registry for the Docker image e.g. `us-east1-docker.pkg.dev/overleaf-ops/ol-docker`
|
||||
- `TEXLIVE_IMAGE_USER` - When using sibling containers, the user to run as in the TeX Live image. Defaults to `tex`
|
||||
- `TEXLIVE_OPENOUT_ANY` - Sets the `openout_any` environment variable for TeX Live (see the `\openout` primitive [documentation](http://tug.org/texinfohtml/web2c.html#tex-invocation))
|
||||
|
||||
Further environment variables configure the [metrics module](https://github.com/overleaf/metrics-module)
|
||||
|
||||
Installation
|
||||
------------
|
||||
## Installation
|
||||
|
||||
The CLSI can be installed and set up as part of the entire [Overleaf stack](https://github.com/overleaf/overleaf) (complete with front end editor and document storage), or it can be run as a standalone service. To run is as a standalone service, first checkout this repository:
|
||||
|
||||
@@ -78,14 +76,14 @@ Note: if you're running the CLSI in macOS you may need to use `-v /var/run/docke
|
||||
|
||||
The CLSI should then be running at <http://localhost:3013>
|
||||
|
||||
Important note for Linux users
|
||||
==============================
|
||||
# Important note for Linux users
|
||||
|
||||
The Node application runs as user `node` in the CLSI, which has uid `1000`. As a consequence of this, the `compiles` folder gets created on your host with `uid` and `gid` set to `1000`.
|
||||
|
||||
```shell
|
||||
ls -lnd compiles
|
||||
```
|
||||
|
||||
> `drwxr-xr-x 2 1000 1000 4096 Mar 19 12:41 compiles`
|
||||
|
||||
If there is a user/group on your host which also happens to have `uid` / `gid` `1000` then that user/group will have ownership of the compiles folder on your host.
|
||||
@@ -114,9 +112,7 @@ sudo chmod g+s compiles
|
||||
|
||||
This is a facet of the way docker works on Linux. See this [upstream issue](https://github.com/moby/moby/issues/7198)
|
||||
|
||||
|
||||
API
|
||||
---
|
||||
## API
|
||||
|
||||
The CLSI is based on a JSON API.
|
||||
|
||||
@@ -128,29 +124,29 @@ The CLSI is based on a JSON API.
|
||||
|
||||
```json5
|
||||
{
|
||||
"compile": {
|
||||
"options": {
|
||||
// Which compiler to use. Can be latex, pdflatex, xelatex or lualatex
|
||||
"compiler": "lualatex",
|
||||
// How many seconds to wait before killing the process. Default is 60.
|
||||
"timeout": 40
|
||||
},
|
||||
// The main file to run LaTeX on
|
||||
"rootResourcePath": "main.tex",
|
||||
// An array of files to include in the compilation. May have either the content
|
||||
// passed directly, or a URL where it can be downloaded.
|
||||
"resources": [
|
||||
{
|
||||
"path": "main.tex",
|
||||
"content": "\\documentclass{article}\n\\begin{document}\nHello World\n\\end{document}"
|
||||
}
|
||||
// ,{
|
||||
// "path": "image.png",
|
||||
// "url": "www.example.com/image.png",
|
||||
// "modified": 123456789 // Unix time since epoch
|
||||
// }
|
||||
]
|
||||
}
|
||||
compile: {
|
||||
options: {
|
||||
// Which compiler to use. Can be latex, pdflatex, xelatex or lualatex
|
||||
compiler: 'lualatex',
|
||||
// How many seconds to wait before killing the process. Default is 60.
|
||||
timeout: 40,
|
||||
},
|
||||
// The main file to run LaTeX on
|
||||
rootResourcePath: 'main.tex',
|
||||
// An array of files to include in the compilation. May have either the content
|
||||
// passed directly, or a URL where it can be downloaded.
|
||||
resources: [
|
||||
{
|
||||
path: 'main.tex',
|
||||
content: '\\documentclass{article}\n\\begin{document}\nHello World\n\\end{document}',
|
||||
},
|
||||
// ,{
|
||||
// "path": "image.png",
|
||||
// "url": "www.example.com/image.png",
|
||||
// "modified": 123456789 // Unix time since epoch
|
||||
// }
|
||||
],
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
@@ -167,21 +163,23 @@ URLs will be downloaded and cached until provided with a more recent modified da
|
||||
|
||||
```json
|
||||
{
|
||||
"compile": {
|
||||
"status": "success",
|
||||
"outputFiles": [{
|
||||
"type": "pdf",
|
||||
"url": "http://localhost:3013/project/<project-id>/output/output.pdf"
|
||||
}, {
|
||||
"type": "log",
|
||||
"url": "http://localhost:3013/project/<project-id>/output/output.log"
|
||||
}]
|
||||
}
|
||||
"compile": {
|
||||
"status": "success",
|
||||
"outputFiles": [
|
||||
{
|
||||
"type": "pdf",
|
||||
"url": "http://localhost:3013/project/<project-id>/output/output.pdf"
|
||||
},
|
||||
{
|
||||
"type": "log",
|
||||
"url": "http://localhost:3013/project/<project-id>/output/output.log"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
License
|
||||
-------
|
||||
## License
|
||||
|
||||
The code in this repository is released under the GNU AFFERO GENERAL PUBLIC LICENSE, version 3. A copy can be found in the `LICENSE` file.
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ function runLatex(projectId, options, callback) {
|
||||
}
|
||||
// number of latex runs and whether there were errors
|
||||
const runs =
|
||||
output?.stderr?.match(/^Run number \d+ of .*latex/gm)?.length || 0
|
||||
output?.stdout?.match(/^Run number \d+ of .*latex/gm)?.length || 0
|
||||
const failed = output?.stdout?.match(/^Latexmk: Errors/m) != null ? 1 : 0
|
||||
// counters from latexmk output
|
||||
stats['latexmk-errors'] = failed
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
clsi
|
||||
--data-dirs=cache,compiles,output
|
||||
--dependencies=
|
||||
--env-add=ENABLE_PDF_CACHING="true",PDF_CACHING_ENABLE_WORKER_POOL="true",ALLOWED_IMAGES=quay.io/sharelatex/texlive-full:2017.1,TEXLIVE_IMAGE=quay.io/sharelatex/texlive-full:2017.1,TEX_LIVE_IMAGE_NAME_OVERRIDE=us-east1-docker.pkg.dev/overleaf-ops/ol-docker,TEXLIVE_IMAGE_USER="tex",SANDBOXED_COMPILES="true",SANDBOXED_COMPILES_HOST_DIR_COMPILES=$PWD/compiles,SANDBOXED_COMPILES_HOST_DIR_OUTPUT=$PWD/output
|
||||
--env-add=ENABLE_PDF_CACHING="true",PDF_CACHING_ENABLE_WORKER_POOL="true",ALLOWED_IMAGES=quay.io/sharelatex/texlive-full:2025.1,TEXLIVE_IMAGE=quay.io/sharelatex/texlive-full:2025.1,TEX_LIVE_IMAGE_NAME_OVERRIDE=us-east1-docker.pkg.dev/overleaf-ops/ol-docker,TEXLIVE_IMAGE_USER="tex",SANDBOXED_COMPILES="true",SANDBOXED_COMPILES_HOST_DIR_COMPILES=$PWD/compiles,SANDBOXED_COMPILES_HOST_DIR_OUTPUT=$PWD/output
|
||||
--env-pass-through=
|
||||
--esmock-loader=False
|
||||
--node-version=22.18.0
|
||||
|
||||
@@ -28,8 +28,8 @@ services:
|
||||
NODE_OPTIONS: "--unhandled-rejections=strict"
|
||||
ENABLE_PDF_CACHING: "true"
|
||||
PDF_CACHING_ENABLE_WORKER_POOL: "true"
|
||||
ALLOWED_IMAGES: quay.io/sharelatex/texlive-full:2017.1
|
||||
TEXLIVE_IMAGE: quay.io/sharelatex/texlive-full:2017.1
|
||||
ALLOWED_IMAGES: quay.io/sharelatex/texlive-full:2025.1
|
||||
TEXLIVE_IMAGE: quay.io/sharelatex/texlive-full:2025.1
|
||||
TEX_LIVE_IMAGE_NAME_OVERRIDE: us-east1-docker.pkg.dev/overleaf-ops/ol-docker
|
||||
TEXLIVE_IMAGE_USER: "tex"
|
||||
SANDBOXED_COMPILES: "true"
|
||||
|
||||
@@ -42,8 +42,8 @@ services:
|
||||
NODE_OPTIONS: "--unhandled-rejections=strict"
|
||||
ENABLE_PDF_CACHING: "true"
|
||||
PDF_CACHING_ENABLE_WORKER_POOL: "true"
|
||||
ALLOWED_IMAGES: quay.io/sharelatex/texlive-full:2017.1
|
||||
TEXLIVE_IMAGE: quay.io/sharelatex/texlive-full:2017.1
|
||||
ALLOWED_IMAGES: quay.io/sharelatex/texlive-full:2025.1
|
||||
TEXLIVE_IMAGE: quay.io/sharelatex/texlive-full:2025.1
|
||||
TEX_LIVE_IMAGE_NAME_OVERRIDE: us-east1-docker.pkg.dev/overleaf-ops/ol-docker
|
||||
TEXLIVE_IMAGE_USER: "tex"
|
||||
SANDBOXED_COMPILES: "true"
|
||||
|
||||
@@ -63,6 +63,11 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "clone3",
|
||||
"action": "SCMP_ACT_ERRNO",
|
||||
"errnoRet": 38
|
||||
},
|
||||
{
|
||||
"name": "close",
|
||||
"action": "SCMP_ACT_ALLOW",
|
||||
@@ -848,4 +853,4 @@
|
||||
"args": []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -1,81 +1,66 @@
|
||||
1/0: uncompressed; offset = 123103
|
||||
2/0: uncompressed; offset = 123422
|
||||
1/0: uncompressed; offset = 92043
|
||||
2/0: uncompressed; offset = 92293
|
||||
3/0: uncompressed; offset = 15
|
||||
4/0: uncompressed; offset = 216
|
||||
5/0: uncompressed; offset = 1084
|
||||
6/0: uncompressed; offset = 1244
|
||||
7/0: uncompressed; offset = 4001
|
||||
8/0: uncompressed; offset = 4155
|
||||
9/0: uncompressed; offset = 4297
|
||||
10/0: uncompressed; offset = 4933
|
||||
11/0: uncompressed; offset = 5309
|
||||
12/0: uncompressed; offset = 5498
|
||||
13/0: uncompressed; offset = 30250
|
||||
14/0: uncompressed; offset = 31471
|
||||
15/0: uncompressed; offset = 38404
|
||||
16/0: uncompressed; offset = 39046
|
||||
17/0: uncompressed; offset = 40166
|
||||
18/0: uncompressed; offset = 40906
|
||||
19/0: uncompressed; offset = 65560
|
||||
20/0: uncompressed; offset = 74702
|
||||
21/0: uncompressed; offset = 81705
|
||||
22/0: uncompressed; offset = 97182
|
||||
23/0: uncompressed; offset = 104117
|
||||
24/0: uncompressed; offset = 111195
|
||||
25/0: uncompressed; offset = 118571
|
||||
26/0: compressed; stream = 6, index = 0
|
||||
27/0: compressed; stream = 6, index = 1
|
||||
28/0: compressed; stream = 6, index = 2
|
||||
29/0: compressed; stream = 6, index = 3
|
||||
30/0: compressed; stream = 6, index = 4
|
||||
31/0: compressed; stream = 6, index = 5
|
||||
32/0: compressed; stream = 6, index = 6
|
||||
33/0: compressed; stream = 6, index = 7
|
||||
34/0: compressed; stream = 6, index = 8
|
||||
35/0: compressed; stream = 6, index = 9
|
||||
36/0: compressed; stream = 6, index = 10
|
||||
37/0: compressed; stream = 6, index = 11
|
||||
38/0: compressed; stream = 6, index = 12
|
||||
39/0: compressed; stream = 6, index = 13
|
||||
40/0: compressed; stream = 6, index = 14
|
||||
41/0: compressed; stream = 6, index = 15
|
||||
42/0: compressed; stream = 6, index = 16
|
||||
43/0: compressed; stream = 6, index = 17
|
||||
44/0: compressed; stream = 6, index = 18
|
||||
45/0: compressed; stream = 6, index = 19
|
||||
46/0: compressed; stream = 6, index = 20
|
||||
47/0: compressed; stream = 6, index = 21
|
||||
48/0: compressed; stream = 6, index = 22
|
||||
49/0: compressed; stream = 6, index = 23
|
||||
50/0: compressed; stream = 6, index = 24
|
||||
51/0: compressed; stream = 6, index = 25
|
||||
52/0: compressed; stream = 6, index = 26
|
||||
53/0: compressed; stream = 6, index = 27
|
||||
54/0: compressed; stream = 6, index = 28
|
||||
55/0: compressed; stream = 6, index = 29
|
||||
56/0: compressed; stream = 6, index = 30
|
||||
57/0: compressed; stream = 6, index = 31
|
||||
58/0: compressed; stream = 6, index = 32
|
||||
59/0: compressed; stream = 6, index = 33
|
||||
60/0: compressed; stream = 6, index = 34
|
||||
61/0: compressed; stream = 6, index = 35
|
||||
62/0: compressed; stream = 6, index = 36
|
||||
63/0: compressed; stream = 6, index = 37
|
||||
64/0: compressed; stream = 6, index = 38
|
||||
65/0: compressed; stream = 6, index = 39
|
||||
66/0: compressed; stream = 6, index = 40
|
||||
67/0: compressed; stream = 6, index = 41
|
||||
68/0: compressed; stream = 6, index = 42
|
||||
69/0: compressed; stream = 6, index = 43
|
||||
70/0: compressed; stream = 6, index = 44
|
||||
71/0: compressed; stream = 6, index = 45
|
||||
72/0: compressed; stream = 6, index = 46
|
||||
73/0: compressed; stream = 6, index = 47
|
||||
74/0: compressed; stream = 6, index = 48
|
||||
75/0: compressed; stream = 6, index = 49
|
||||
76/0: compressed; stream = 6, index = 50
|
||||
77/0: compressed; stream = 6, index = 51
|
||||
78/0: compressed; stream = 6, index = 52
|
||||
79/0: compressed; stream = 6, index = 53
|
||||
80/0: compressed; stream = 6, index = 54
|
||||
81/0: compressed; stream = 6, index = 55
|
||||
5/0: uncompressed; offset = 979
|
||||
6/0: uncompressed; offset = 1029
|
||||
7/0: uncompressed; offset = 1191
|
||||
8/0: uncompressed; offset = 1300
|
||||
9/0: uncompressed; offset = 1902
|
||||
10/0: uncompressed; offset = 2233
|
||||
11/0: uncompressed; offset = 2870
|
||||
12/0: uncompressed; offset = 3910
|
||||
13/0: uncompressed; offset = 4666
|
||||
14/0: uncompressed; offset = 5435
|
||||
15/0: uncompressed; offset = 6204
|
||||
16/0: uncompressed; offset = 7177
|
||||
17/0: uncompressed; offset = 28756
|
||||
18/0: uncompressed; offset = 37898
|
||||
19/0: uncompressed; offset = 44901
|
||||
20/0: uncompressed; offset = 60378
|
||||
21/0: uncompressed; offset = 67313
|
||||
22/0: uncompressed; offset = 74391
|
||||
23/0: uncompressed; offset = 81767
|
||||
24/0: uncompressed; offset = 86299
|
||||
25/0: uncompressed; offset = 87068
|
||||
26/0: uncompressed; offset = 87881
|
||||
27/0: uncompressed; offset = 88694
|
||||
28/0: uncompressed; offset = 89507
|
||||
29/0: uncompressed; offset = 90252
|
||||
30/0: compressed; stream = 29, index = 0
|
||||
31/0: compressed; stream = 29, index = 1
|
||||
32/0: compressed; stream = 29, index = 2
|
||||
33/0: compressed; stream = 29, index = 3
|
||||
34/0: compressed; stream = 29, index = 4
|
||||
35/0: compressed; stream = 29, index = 5
|
||||
36/0: compressed; stream = 29, index = 6
|
||||
37/0: compressed; stream = 29, index = 7
|
||||
38/0: compressed; stream = 29, index = 8
|
||||
39/0: compressed; stream = 29, index = 9
|
||||
40/0: compressed; stream = 29, index = 10
|
||||
41/0: compressed; stream = 29, index = 11
|
||||
42/0: compressed; stream = 29, index = 12
|
||||
43/0: compressed; stream = 29, index = 13
|
||||
44/0: compressed; stream = 29, index = 14
|
||||
45/0: compressed; stream = 29, index = 15
|
||||
46/0: compressed; stream = 29, index = 16
|
||||
47/0: compressed; stream = 29, index = 17
|
||||
48/0: compressed; stream = 29, index = 18
|
||||
49/0: compressed; stream = 29, index = 19
|
||||
50/0: compressed; stream = 29, index = 20
|
||||
51/0: compressed; stream = 29, index = 21
|
||||
52/0: compressed; stream = 29, index = 22
|
||||
53/0: compressed; stream = 29, index = 23
|
||||
54/0: compressed; stream = 29, index = 24
|
||||
55/0: compressed; stream = 29, index = 25
|
||||
56/0: compressed; stream = 29, index = 26
|
||||
57/0: compressed; stream = 29, index = 27
|
||||
58/0: compressed; stream = 29, index = 28
|
||||
59/0: compressed; stream = 29, index = 29
|
||||
60/0: compressed; stream = 29, index = 30
|
||||
61/0: compressed; stream = 29, index = 31
|
||||
62/0: compressed; stream = 29, index = 32
|
||||
63/0: compressed; stream = 29, index = 33
|
||||
64/0: compressed; stream = 29, index = 34
|
||||
65/0: compressed; stream = 29, index = 35
|
||||
66/0: compressed; stream = 29, index = 36
|
||||
|
||||
Binary file not shown.
@@ -1,20 +1,20 @@
|
||||
1/0: uncompressed; offset = 4964
|
||||
2/0: uncompressed; offset = 5023
|
||||
3/0: uncompressed; offset = 5234
|
||||
1/0: uncompressed; offset = 4966
|
||||
2/0: uncompressed; offset = 5025
|
||||
3/0: uncompressed; offset = 5259
|
||||
4/0: uncompressed; offset = 15
|
||||
5/0: uncompressed; offset = 734
|
||||
6/0: uncompressed; offset = 799
|
||||
7/0: uncompressed; offset = 933
|
||||
8/0: uncompressed; offset = 1104
|
||||
9/0: uncompressed; offset = 1947
|
||||
10/0: uncompressed; offset = 1992
|
||||
11/0: uncompressed; offset = 2182
|
||||
12/0: uncompressed; offset = 2427
|
||||
13/0: uncompressed; offset = 2597
|
||||
14/0: uncompressed; offset = 2822
|
||||
15/0: uncompressed; offset = 2989
|
||||
16/0: uncompressed; offset = 3239
|
||||
17/0: uncompressed; offset = 3271
|
||||
18/0: uncompressed; offset = 3328
|
||||
19/0: uncompressed; offset = 3740
|
||||
20/0: uncompressed; offset = 4270
|
||||
9/0: uncompressed; offset = 1946
|
||||
10/0: uncompressed; offset = 1994
|
||||
11/0: uncompressed; offset = 2184
|
||||
12/0: uncompressed; offset = 2429
|
||||
13/0: uncompressed; offset = 2599
|
||||
14/0: uncompressed; offset = 2824
|
||||
15/0: uncompressed; offset = 2991
|
||||
16/0: uncompressed; offset = 3241
|
||||
17/0: uncompressed; offset = 3273
|
||||
18/0: uncompressed; offset = 3330
|
||||
19/0: uncompressed; offset = 3742
|
||||
20/0: uncompressed; offset = 4272
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,26 +1,26 @@
|
||||
1/0: uncompressed; offset = 25097
|
||||
2/0: uncompressed; offset = 25156
|
||||
3/0: uncompressed; offset = 25367
|
||||
1/0: uncompressed; offset = 25082
|
||||
2/0: uncompressed; offset = 25141
|
||||
3/0: uncompressed; offset = 25375
|
||||
4/0: uncompressed; offset = 15
|
||||
5/0: uncompressed; offset = 854
|
||||
6/0: uncompressed; offset = 919
|
||||
7/0: uncompressed; offset = 1074
|
||||
8/0: uncompressed; offset = 1245
|
||||
9/0: uncompressed; offset = 18343
|
||||
10/0: uncompressed; offset = 18388
|
||||
11/0: uncompressed; offset = 18752
|
||||
12/0: uncompressed; offset = 19071
|
||||
13/0: uncompressed; offset = 19360
|
||||
14/0: uncompressed; offset = 19604
|
||||
15/0: uncompressed; offset = 19770
|
||||
16/0: uncompressed; offset = 20007
|
||||
17/0: uncompressed; offset = 20174
|
||||
18/0: uncompressed; offset = 20424
|
||||
19/0: uncompressed; offset = 20456
|
||||
20/0: uncompressed; offset = 20525
|
||||
21/0: uncompressed; offset = 23109
|
||||
22/0: uncompressed; offset = 23500
|
||||
23/0: uncompressed; offset = 24229
|
||||
24/0: uncompressed; offset = 24641
|
||||
25/0: uncompressed; offset = 24741
|
||||
26/0: uncompressed; offset = 24985
|
||||
10/0: uncompressed; offset = 18391
|
||||
11/0: uncompressed; offset = 18755
|
||||
12/0: uncompressed; offset = 19074
|
||||
13/0: uncompressed; offset = 19363
|
||||
14/0: uncompressed; offset = 19607
|
||||
15/0: uncompressed; offset = 19773
|
||||
16/0: uncompressed; offset = 20010
|
||||
17/0: uncompressed; offset = 20177
|
||||
18/0: uncompressed; offset = 20427
|
||||
19/0: uncompressed; offset = 20459
|
||||
20/0: uncompressed; offset = 20528
|
||||
21/0: uncompressed; offset = 20919
|
||||
22/0: uncompressed; offset = 21648
|
||||
23/0: uncompressed; offset = 22060
|
||||
24/0: uncompressed; offset = 24626
|
||||
25/0: uncompressed; offset = 24726
|
||||
26/0: uncompressed; offset = 24970
|
||||
|
||||
Binary file not shown.
@@ -1,19 +1,21 @@
|
||||
1/0: uncompressed; offset = 20679
|
||||
2/0: uncompressed; offset = 20927
|
||||
1/0: uncompressed; offset = 22291
|
||||
2/0: uncompressed; offset = 22541
|
||||
3/0: uncompressed; offset = 15
|
||||
4/0: uncompressed; offset = 216
|
||||
5/0: uncompressed; offset = 650
|
||||
6/0: uncompressed; offset = 700
|
||||
7/0: uncompressed; offset = 826
|
||||
8/0: uncompressed; offset = 934
|
||||
9/0: uncompressed; offset = 1252
|
||||
10/0: uncompressed; offset = 8248
|
||||
11/0: uncompressed; offset = 20115
|
||||
12/0: compressed; stream = 11, index = 0
|
||||
13/0: compressed; stream = 11, index = 1
|
||||
14/0: compressed; stream = 11, index = 2
|
||||
15/0: compressed; stream = 11, index = 3
|
||||
16/0: compressed; stream = 11, index = 4
|
||||
17/0: compressed; stream = 11, index = 5
|
||||
18/0: compressed; stream = 11, index = 6
|
||||
19/0: compressed; stream = 11, index = 7
|
||||
5/0: uncompressed; offset = 664
|
||||
6/0: uncompressed; offset = 714
|
||||
7/0: uncompressed; offset = 844
|
||||
8/0: uncompressed; offset = 952
|
||||
9/0: uncompressed; offset = 1294
|
||||
10/0: uncompressed; offset = 8288
|
||||
11/0: uncompressed; offset = 20150
|
||||
12/0: uncompressed; offset = 20963
|
||||
13/0: uncompressed; offset = 21708
|
||||
14/0: compressed; stream = 13, index = 0
|
||||
15/0: compressed; stream = 13, index = 1
|
||||
16/0: compressed; stream = 13, index = 2
|
||||
17/0: compressed; stream = 13, index = 3
|
||||
18/0: compressed; stream = 13, index = 4
|
||||
19/0: compressed; stream = 13, index = 5
|
||||
20/0: compressed; stream = 13, index = 6
|
||||
21/0: compressed; stream = 13, index = 7
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
const Client = require('./helpers/Client')
|
||||
const { fetchNothing } = require('@overleaf/fetch-utils')
|
||||
const ClsiApp = require('./helpers/ClsiApp')
|
||||
const { expect } = require('chai')
|
||||
|
||||
describe('Simple LaTeX file', function () {
|
||||
const content = `\
|
||||
@@ -72,8 +73,8 @@ Hello world
|
||||
'latexmk-errors',
|
||||
'latex-runs',
|
||||
'latex-runs-with-errors',
|
||||
'latex-runs-2',
|
||||
'latex-runs-with-errors-2',
|
||||
'latex-runs-1',
|
||||
'latex-runs-with-errors-1',
|
||||
'pdf-caching-total-ranges-size',
|
||||
'pdf-caching-reclaimed-space',
|
||||
'pdf-caching-new-ranges-size',
|
||||
@@ -92,4 +93,40 @@ Hello world
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
describe('document with shell commands', function () {
|
||||
before(async function () {
|
||||
this.project_id = Client.randomId()
|
||||
this.request = {
|
||||
resources: [
|
||||
{
|
||||
path: 'main.tex',
|
||||
content: `\
|
||||
\\documentclass{article}
|
||||
\\begin{document}
|
||||
Testing system calls:
|
||||
\\immediate\\write18{/bin/date > date.txt}
|
||||
The current date from system is: \\input{date.txt}
|
||||
The current date from popen is: \\input{"|date"}
|
||||
\\end{document}\
|
||||
`,
|
||||
},
|
||||
],
|
||||
}
|
||||
await ClsiApp.ensureRunning()
|
||||
})
|
||||
|
||||
it('should compile successfully', async function () {
|
||||
const body = await Client.compile(this.project_id, this.request)
|
||||
expect(body).to.exist
|
||||
expect(body.compile?.status, 'compile status').to.equal('success')
|
||||
})
|
||||
|
||||
it('should return the PDF', async function () {
|
||||
const body = await Client.compile(this.project_id, this.request)
|
||||
const pdf = Client.getOutputFile(body, 'pdf')
|
||||
expect(pdf, 'pdf file not produced').to.exist
|
||||
expect(pdf.type, 'invalid pdf file').to.equal('pdf')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
14
services/clsi/test/acceptance/js/SmokeTest.js
Normal file
14
services/clsi/test/acceptance/js/SmokeTest.js
Normal file
@@ -0,0 +1,14 @@
|
||||
const Client = require('./helpers/Client')
|
||||
const ClsiApp = require('./helpers/ClsiApp')
|
||||
const { expect } = require('chai')
|
||||
|
||||
describe('Smoke Test', function () {
|
||||
before(async function () {
|
||||
await ClsiApp.ensureRunning()
|
||||
})
|
||||
|
||||
it('should compile the test document and return a response of "OK"', async function () {
|
||||
const response = await Client.smokeTest()
|
||||
expect(response).to.equal('OK')
|
||||
})
|
||||
})
|
||||
@@ -1,5 +1,9 @@
|
||||
const express = require('express')
|
||||
const { fetchJson, fetchNothing } = require('@overleaf/fetch-utils')
|
||||
const {
|
||||
fetchJson,
|
||||
fetchNothing,
|
||||
fetchString,
|
||||
} = require('@overleaf/fetch-utils')
|
||||
const fs = require('node:fs')
|
||||
const fsPromises = require('node:fs/promises')
|
||||
const Settings = require('@overleaf/settings')
|
||||
@@ -177,12 +181,19 @@ async function compileDirectory(projectId, baseDirectory, directory) {
|
||||
return await compile(projectId, req)
|
||||
}
|
||||
|
||||
function smokeTest() {
|
||||
return fetchString(`${host}/smoke_test_force`, {
|
||||
method: 'GET',
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
randomId,
|
||||
compile,
|
||||
stopCompile,
|
||||
clearCache,
|
||||
getOutputFile,
|
||||
smokeTest,
|
||||
runFakeFilestoreService,
|
||||
startFakeFilestoreApp,
|
||||
syncFromCode,
|
||||
|
||||
@@ -54,6 +54,9 @@ module.exports = {
|
||||
\\documentclass{article}
|
||||
\\usepackage{tikz}
|
||||
\\usetikzlibrary{calc,fadings,decorations.pathreplacing}
|
||||
\\usepackage{ifplatform} % test shell escape, conditionals to test which platform is being used
|
||||
\\usepackage{minted} % to test shell commands
|
||||
\\usepackage{bashful} % to test shell commands
|
||||
\\begin{document}
|
||||
\\begin{tikzpicture}
|
||||
\\def\\nuPi{3.1459265}
|
||||
@@ -79,6 +82,24 @@ module.exports = {
|
||||
}
|
||||
}
|
||||
\\end{tikzpicture}
|
||||
|
||||
% Test minted (shell commands)
|
||||
\\begin{minted}{python}
|
||||
x = 1 + 2
|
||||
\\end{minted}
|
||||
|
||||
% Test bashful (shell commands)
|
||||
\\bash[stdout,stderr]
|
||||
date
|
||||
\\END
|
||||
|
||||
% Test system
|
||||
\\immediate\\write18{/bin/date > date.txt}
|
||||
\\input date.txt
|
||||
|
||||
% Test popen
|
||||
\\input{"|date"}
|
||||
|
||||
\\end{document}\
|
||||
`,
|
||||
},
|
||||
|
||||
@@ -1,359 +1,123 @@
|
||||
{
|
||||
"xRefEntries": [
|
||||
{
|
||||
"offset": 0,
|
||||
"gen": 0,
|
||||
"free": true
|
||||
"offset": 0
|
||||
},
|
||||
{
|
||||
"offset": 123103,
|
||||
"gen": 0,
|
||||
"offset": 92043,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 123422,
|
||||
"gen": 0,
|
||||
"offset": 92293,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 15,
|
||||
"gen": 0,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 216,
|
||||
"gen": 0,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 1084,
|
||||
"gen": 0,
|
||||
"offset": 979,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 1244,
|
||||
"gen": 0,
|
||||
"offset": 1029,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 4001,
|
||||
"gen": 0,
|
||||
"offset": 1191,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 4155,
|
||||
"gen": 0,
|
||||
"offset": 1300,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 4297,
|
||||
"gen": 0,
|
||||
"offset": 1902,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 4933,
|
||||
"gen": 0,
|
||||
"offset": 2233,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 5309,
|
||||
"gen": 0,
|
||||
"offset": 2870,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 5498,
|
||||
"gen": 0,
|
||||
"offset": 3910,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 30250,
|
||||
"gen": 0,
|
||||
"offset": 4666,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 31471,
|
||||
"gen": 0,
|
||||
"offset": 5435,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 38404,
|
||||
"gen": 0,
|
||||
"offset": 6204,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 39046,
|
||||
"gen": 0,
|
||||
"offset": 7177,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 40166,
|
||||
"gen": 0,
|
||||
"offset": 28756,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 40906,
|
||||
"gen": 0,
|
||||
"offset": 37898,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 65560,
|
||||
"gen": 0,
|
||||
"offset": 44901,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 74702,
|
||||
"gen": 0,
|
||||
"offset": 60378,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 81705,
|
||||
"gen": 0,
|
||||
"offset": 67313,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 97182,
|
||||
"gen": 0,
|
||||
"offset": 74391,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 104117,
|
||||
"gen": 0,
|
||||
"offset": 81767,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 111195,
|
||||
"gen": 0,
|
||||
"offset": 86299,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 118571,
|
||||
"gen": 0,
|
||||
"offset": 87068,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 0
|
||||
"offset": 87881,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 1
|
||||
"offset": 88694,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 2
|
||||
"offset": 89507,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 3
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 4
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 5
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 6
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 7
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 8
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 9
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 10
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 11
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 12
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 13
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 14
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 15
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 16
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 17
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 18
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 19
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 20
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 21
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 22
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 23
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 24
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 25
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 26
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 27
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 28
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 29
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 30
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 31
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 32
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 33
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 34
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 35
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 36
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 37
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 38
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 39
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 40
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 41
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 42
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 43
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 44
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 45
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 46
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 47
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 48
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 49
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 50
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 51
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 52
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 53
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 54
|
||||
},
|
||||
{
|
||||
"offset": 6,
|
||||
"gen": 55
|
||||
"offset": 90252,
|
||||
"uncompressed": true
|
||||
}
|
||||
],
|
||||
"startXRefTable": 123422
|
||||
]
|
||||
}
|
||||
@@ -1,110 +1,87 @@
|
||||
{
|
||||
"xRefEntries": [
|
||||
{
|
||||
"offset": 0,
|
||||
"gen": 65535,
|
||||
"free": true
|
||||
"offset": 0
|
||||
},
|
||||
{
|
||||
"offset": 4964,
|
||||
"gen": 0,
|
||||
"offset": 4966,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 5023,
|
||||
"gen": 0,
|
||||
"offset": 5025,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 5234,
|
||||
"gen": 0,
|
||||
"offset": 5259,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 15,
|
||||
"gen": 0,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 734,
|
||||
"gen": 0,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 799,
|
||||
"gen": 0,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 933,
|
||||
"gen": 0,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 1104,
|
||||
"gen": 0,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 1947,
|
||||
"gen": 0,
|
||||
"offset": 1946,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 1992,
|
||||
"gen": 0,
|
||||
"offset": 1994,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 2182,
|
||||
"gen": 0,
|
||||
"offset": 2184,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 2427,
|
||||
"gen": 0,
|
||||
"offset": 2429,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 2597,
|
||||
"gen": 0,
|
||||
"offset": 2599,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 2822,
|
||||
"gen": 0,
|
||||
"offset": 2824,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 2989,
|
||||
"gen": 0,
|
||||
"offset": 2991,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 3239,
|
||||
"gen": 0,
|
||||
"offset": 3241,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 3271,
|
||||
"gen": 0,
|
||||
"offset": 3273,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 3328,
|
||||
"gen": 0,
|
||||
"offset": 3330,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 3740,
|
||||
"gen": 0,
|
||||
"offset": 3742,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 4270,
|
||||
"gen": 0,
|
||||
"offset": 4272,
|
||||
"uncompressed": true
|
||||
}
|
||||
],
|
||||
"startXRefTable": 6682
|
||||
]
|
||||
}
|
||||
@@ -1,140 +1,111 @@
|
||||
{
|
||||
"xRefEntries": [
|
||||
{
|
||||
"offset": 0,
|
||||
"gen": 65535,
|
||||
"free": true
|
||||
"offset": 0
|
||||
},
|
||||
{
|
||||
"offset": 25097,
|
||||
"gen": 0,
|
||||
"offset": 25082,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 25156,
|
||||
"gen": 0,
|
||||
"offset": 25141,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 25367,
|
||||
"gen": 0,
|
||||
"offset": 25375,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 15,
|
||||
"gen": 0,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 854,
|
||||
"gen": 0,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 919,
|
||||
"gen": 0,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 1074,
|
||||
"gen": 0,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 1245,
|
||||
"gen": 0,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 18343,
|
||||
"gen": 0,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 18388,
|
||||
"gen": 0,
|
||||
"offset": 18391,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 18752,
|
||||
"gen": 0,
|
||||
"offset": 18755,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 19071,
|
||||
"gen": 0,
|
||||
"offset": 19074,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 19360,
|
||||
"gen": 0,
|
||||
"offset": 19363,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 19604,
|
||||
"gen": 0,
|
||||
"offset": 19607,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 19770,
|
||||
"gen": 0,
|
||||
"offset": 19773,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 20007,
|
||||
"gen": 0,
|
||||
"offset": 20010,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 20174,
|
||||
"gen": 0,
|
||||
"offset": 20177,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 20424,
|
||||
"gen": 0,
|
||||
"offset": 20427,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 20456,
|
||||
"gen": 0,
|
||||
"offset": 20459,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 20525,
|
||||
"gen": 0,
|
||||
"offset": 20528,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 23109,
|
||||
"gen": 0,
|
||||
"offset": 20919,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 23500,
|
||||
"gen": 0,
|
||||
"offset": 21648,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 24229,
|
||||
"gen": 0,
|
||||
"offset": 22060,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 24641,
|
||||
"gen": 0,
|
||||
"offset": 24626,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 24741,
|
||||
"gen": 0,
|
||||
"offset": 24726,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 24985,
|
||||
"gen": 0,
|
||||
"offset": 24970,
|
||||
"uncompressed": true
|
||||
}
|
||||
],
|
||||
"startXRefTable": 26815
|
||||
]
|
||||
}
|
||||
@@ -1,97 +1,59 @@
|
||||
{
|
||||
"xRefEntries": [
|
||||
{
|
||||
"offset": 0,
|
||||
"gen": 0,
|
||||
"free": true
|
||||
"offset": 0
|
||||
},
|
||||
{
|
||||
"offset": 20679,
|
||||
"gen": 0,
|
||||
"offset": 22291,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 20927,
|
||||
"gen": 0,
|
||||
"offset": 22541,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 15,
|
||||
"gen": 0,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 216,
|
||||
"gen": 0,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 650,
|
||||
"gen": 0,
|
||||
"offset": 664,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 700,
|
||||
"gen": 0,
|
||||
"offset": 714,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 826,
|
||||
"gen": 0,
|
||||
"offset": 844,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 934,
|
||||
"gen": 0,
|
||||
"offset": 952,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 1252,
|
||||
"gen": 0,
|
||||
"offset": 1294,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 8248,
|
||||
"gen": 0,
|
||||
"offset": 8288,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 20115,
|
||||
"gen": 0,
|
||||
"offset": 20150,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 11,
|
||||
"gen": 0
|
||||
"offset": 20963,
|
||||
"uncompressed": true
|
||||
},
|
||||
{
|
||||
"offset": 11,
|
||||
"gen": 1
|
||||
},
|
||||
{
|
||||
"offset": 11,
|
||||
"gen": 2
|
||||
},
|
||||
{
|
||||
"offset": 11,
|
||||
"gen": 3
|
||||
},
|
||||
{
|
||||
"offset": 11,
|
||||
"gen": 4
|
||||
},
|
||||
{
|
||||
"offset": 11,
|
||||
"gen": 5
|
||||
},
|
||||
{
|
||||
"offset": 11,
|
||||
"gen": 6
|
||||
},
|
||||
{
|
||||
"offset": 11,
|
||||
"gen": 7
|
||||
"offset": 21708,
|
||||
"uncompressed": true
|
||||
}
|
||||
],
|
||||
"startXRefTable": 20927
|
||||
]
|
||||
}
|
||||
@@ -4,13 +4,14 @@
|
||||
|
||||
BUILD_NUMBER ?= local
|
||||
BRANCH_NAME ?= $(shell git rev-parse --abbrev-ref HEAD)
|
||||
BRANCH_NAME_TAG_SAFE = $(shell echo $(BRANCH_NAME) | sed 's/\//\-\-/g')
|
||||
PROJECT_NAME = contacts
|
||||
BUILD_DIR_NAME = $(shell pwd | xargs basename | tr -cd '[a-zA-Z0-9_.\-]')
|
||||
HERE=$(shell pwd)
|
||||
export MONOREPO ?= $(shell cd ../../ && pwd)
|
||||
IMAGE_CI ?= ci/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER)
|
||||
IMAGE_CI ?= ci/$(PROJECT_NAME):$(BRANCH_NAME_TAG_SAFE)-$(BUILD_NUMBER)
|
||||
IMAGE_REPO ?= us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME)
|
||||
IMAGE_REPO_FINAL ?= $(IMAGE_REPO):$(BRANCH_NAME)-$(BUILD_NUMBER)
|
||||
IMAGE_REPO_FINAL ?= $(IMAGE_REPO):$(BRANCH_NAME_TAG_SAFE)-$(BUILD_NUMBER)
|
||||
IMAGE_CACHE ?= $(IMAGE_REPO):cache-$(shell cat \
|
||||
$(MONOREPO)/package.json \
|
||||
$(MONOREPO)/package-lock.json \
|
||||
@@ -28,7 +29,7 @@ IMAGE_CACHE ?= $(IMAGE_REPO):cache-$(shell cat \
|
||||
|
||||
DOCKER_COMPOSE_FLAGS ?= -f docker-compose.yml
|
||||
DOCKER_COMPOSE := BUILD_NUMBER=$(BUILD_NUMBER) \
|
||||
BRANCH_NAME=$(BRANCH_NAME) \
|
||||
BRANCH_NAME=$(BRANCH_NAME_TAG_SAFE) \
|
||||
PROJECT_NAME=$(PROJECT_NAME) \
|
||||
MOCHA_GREP=${MOCHA_GREP} \
|
||||
docker compose ${DOCKER_COMPOSE_FLAGS}
|
||||
|
||||
@@ -4,13 +4,14 @@
|
||||
|
||||
BUILD_NUMBER ?= local
|
||||
BRANCH_NAME ?= $(shell git rev-parse --abbrev-ref HEAD)
|
||||
BRANCH_NAME_TAG_SAFE = $(shell echo $(BRANCH_NAME) | sed 's/\//\-\-/g')
|
||||
PROJECT_NAME = docstore
|
||||
BUILD_DIR_NAME = $(shell pwd | xargs basename | tr -cd '[a-zA-Z0-9_.\-]')
|
||||
HERE=$(shell pwd)
|
||||
export MONOREPO ?= $(shell cd ../../ && pwd)
|
||||
IMAGE_CI ?= ci/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER)
|
||||
IMAGE_CI ?= ci/$(PROJECT_NAME):$(BRANCH_NAME_TAG_SAFE)-$(BUILD_NUMBER)
|
||||
IMAGE_REPO ?= us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME)
|
||||
IMAGE_REPO_FINAL ?= $(IMAGE_REPO):$(BRANCH_NAME)-$(BUILD_NUMBER)
|
||||
IMAGE_REPO_FINAL ?= $(IMAGE_REPO):$(BRANCH_NAME_TAG_SAFE)-$(BUILD_NUMBER)
|
||||
IMAGE_CACHE ?= $(IMAGE_REPO):cache-$(shell cat \
|
||||
$(MONOREPO)/package.json \
|
||||
$(MONOREPO)/package-lock.json \
|
||||
@@ -30,7 +31,7 @@ IMAGE_CACHE ?= $(IMAGE_REPO):cache-$(shell cat \
|
||||
|
||||
DOCKER_COMPOSE_FLAGS ?= -f docker-compose.yml
|
||||
DOCKER_COMPOSE := BUILD_NUMBER=$(BUILD_NUMBER) \
|
||||
BRANCH_NAME=$(BRANCH_NAME) \
|
||||
BRANCH_NAME=$(BRANCH_NAME_TAG_SAFE) \
|
||||
PROJECT_NAME=$(PROJECT_NAME) \
|
||||
MOCHA_GREP=${MOCHA_GREP} \
|
||||
docker compose ${DOCKER_COMPOSE_FLAGS}
|
||||
|
||||
@@ -4,13 +4,14 @@
|
||||
|
||||
BUILD_NUMBER ?= local
|
||||
BRANCH_NAME ?= $(shell git rev-parse --abbrev-ref HEAD)
|
||||
BRANCH_NAME_TAG_SAFE = $(shell echo $(BRANCH_NAME) | sed 's/\//\-\-/g')
|
||||
PROJECT_NAME = document-updater
|
||||
BUILD_DIR_NAME = $(shell pwd | xargs basename | tr -cd '[a-zA-Z0-9_.\-]')
|
||||
HERE=$(shell pwd)
|
||||
export MONOREPO ?= $(shell cd ../../ && pwd)
|
||||
IMAGE_CI ?= ci/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER)
|
||||
IMAGE_CI ?= ci/$(PROJECT_NAME):$(BRANCH_NAME_TAG_SAFE)-$(BUILD_NUMBER)
|
||||
IMAGE_REPO ?= us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME)
|
||||
IMAGE_REPO_FINAL ?= $(IMAGE_REPO):$(BRANCH_NAME)-$(BUILD_NUMBER)
|
||||
IMAGE_REPO_FINAL ?= $(IMAGE_REPO):$(BRANCH_NAME_TAG_SAFE)-$(BUILD_NUMBER)
|
||||
IMAGE_CACHE ?= $(IMAGE_REPO):cache-$(shell cat \
|
||||
$(MONOREPO)/package.json \
|
||||
$(MONOREPO)/package-lock.json \
|
||||
@@ -31,7 +32,7 @@ IMAGE_CACHE ?= $(IMAGE_REPO):cache-$(shell cat \
|
||||
|
||||
DOCKER_COMPOSE_FLAGS ?= -f docker-compose.yml
|
||||
DOCKER_COMPOSE := BUILD_NUMBER=$(BUILD_NUMBER) \
|
||||
BRANCH_NAME=$(BRANCH_NAME) \
|
||||
BRANCH_NAME=$(BRANCH_NAME_TAG_SAFE) \
|
||||
PROJECT_NAME=$(PROJECT_NAME) \
|
||||
MOCHA_GREP=${MOCHA_GREP} \
|
||||
docker compose ${DOCKER_COMPOSE_FLAGS}
|
||||
|
||||
@@ -4,13 +4,14 @@
|
||||
|
||||
BUILD_NUMBER ?= local
|
||||
BRANCH_NAME ?= $(shell git rev-parse --abbrev-ref HEAD)
|
||||
BRANCH_NAME_TAG_SAFE = $(shell echo $(BRANCH_NAME) | sed 's/\//\-\-/g')
|
||||
PROJECT_NAME = filestore
|
||||
BUILD_DIR_NAME = $(shell pwd | xargs basename | tr -cd '[a-zA-Z0-9_.\-]')
|
||||
HERE=$(shell pwd)
|
||||
export MONOREPO ?= $(shell cd ../../ && pwd)
|
||||
IMAGE_CI ?= ci/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER)
|
||||
IMAGE_CI ?= ci/$(PROJECT_NAME):$(BRANCH_NAME_TAG_SAFE)-$(BUILD_NUMBER)
|
||||
IMAGE_REPO ?= us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME)
|
||||
IMAGE_REPO_FINAL ?= $(IMAGE_REPO):$(BRANCH_NAME)-$(BUILD_NUMBER)
|
||||
IMAGE_REPO_FINAL ?= $(IMAGE_REPO):$(BRANCH_NAME_TAG_SAFE)-$(BUILD_NUMBER)
|
||||
IMAGE_CACHE ?= $(IMAGE_REPO):cache-$(shell cat \
|
||||
$(MONOREPO)/package.json \
|
||||
$(MONOREPO)/package-lock.json \
|
||||
@@ -27,7 +28,7 @@ IMAGE_CACHE ?= $(IMAGE_REPO):cache-$(shell cat \
|
||||
|
||||
DOCKER_COMPOSE_FLAGS ?= -f docker-compose.yml
|
||||
DOCKER_COMPOSE := BUILD_NUMBER=$(BUILD_NUMBER) \
|
||||
BRANCH_NAME=$(BRANCH_NAME) \
|
||||
BRANCH_NAME=$(BRANCH_NAME_TAG_SAFE) \
|
||||
PROJECT_NAME=$(PROJECT_NAME) \
|
||||
MOCHA_GREP=${MOCHA_GREP} \
|
||||
docker compose ${DOCKER_COMPOSE_FLAGS}
|
||||
|
||||
@@ -5,12 +5,13 @@ MVN_TARGET := target/writelatex-git-bridge-1.0-SNAPSHOT-jar-with-dependencies.ja
|
||||
|
||||
export BUILD_NUMBER ?= local
|
||||
export BRANCH_NAME ?= $(shell git rev-parse --abbrev-ref HEAD)
|
||||
BRANCH_NAME_TAG_SAFE = $(shell echo $(BRANCH_NAME) | sed 's/\//\-\-/g')
|
||||
export COMMIT_SHA ?= $(shell git rev-parse HEAD)
|
||||
PROJECT_NAME = git-bridge
|
||||
|
||||
IMAGE_CI ?= ci/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER)
|
||||
IMAGE_CI ?= ci/$(PROJECT_NAME):$(BRANCH_NAME_TAG_SAFE)-$(BUILD_NUMBER)
|
||||
IMAGE_REPO ?= us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME)
|
||||
IMAGE_REPO_BRANCH ?= $(IMAGE_REPO):$(BRANCH_NAME)
|
||||
IMAGE_REPO_BRANCH ?= $(IMAGE_REPO):$(BRANCH_NAME_TAG_SAFE)
|
||||
IMAGE_REPO_MAIN ?= $(IMAGE_REPO):main
|
||||
IMAGE_REPO_FINAL ?= $(IMAGE_REPO_BRANCH)-$(BUILD_NUMBER)
|
||||
|
||||
|
||||
@@ -4,13 +4,14 @@
|
||||
|
||||
BUILD_NUMBER ?= local
|
||||
BRANCH_NAME ?= $(shell git rev-parse --abbrev-ref HEAD)
|
||||
BRANCH_NAME_TAG_SAFE = $(shell echo $(BRANCH_NAME) | sed 's/\//\-\-/g')
|
||||
PROJECT_NAME = history-v1
|
||||
BUILD_DIR_NAME = $(shell pwd | xargs basename | tr -cd '[a-zA-Z0-9_.\-]')
|
||||
HERE=$(shell pwd)
|
||||
export MONOREPO ?= $(shell cd ../../ && pwd)
|
||||
IMAGE_CI ?= ci/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER)
|
||||
IMAGE_CI ?= ci/$(PROJECT_NAME):$(BRANCH_NAME_TAG_SAFE)-$(BUILD_NUMBER)
|
||||
IMAGE_REPO ?= us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME)
|
||||
IMAGE_REPO_FINAL ?= $(IMAGE_REPO):$(BRANCH_NAME)-$(BUILD_NUMBER)
|
||||
IMAGE_REPO_FINAL ?= $(IMAGE_REPO):$(BRANCH_NAME_TAG_SAFE)-$(BUILD_NUMBER)
|
||||
IMAGE_CACHE ?= $(IMAGE_REPO):cache-$(shell cat \
|
||||
$(MONOREPO)/package.json \
|
||||
$(MONOREPO)/package-lock.json \
|
||||
@@ -32,7 +33,7 @@ IMAGE_CACHE ?= $(IMAGE_REPO):cache-$(shell cat \
|
||||
|
||||
DOCKER_COMPOSE_FLAGS ?= -f docker-compose.yml
|
||||
DOCKER_COMPOSE := BUILD_NUMBER=$(BUILD_NUMBER) \
|
||||
BRANCH_NAME=$(BRANCH_NAME) \
|
||||
BRANCH_NAME=$(BRANCH_NAME_TAG_SAFE) \
|
||||
PROJECT_NAME=$(PROJECT_NAME) \
|
||||
MOCHA_GREP=${MOCHA_GREP} \
|
||||
docker compose ${DOCKER_COMPOSE_FLAGS}
|
||||
|
||||
@@ -4,13 +4,14 @@
|
||||
|
||||
BUILD_NUMBER ?= local
|
||||
BRANCH_NAME ?= $(shell git rev-parse --abbrev-ref HEAD)
|
||||
BRANCH_NAME_TAG_SAFE = $(shell echo $(BRANCH_NAME) | sed 's/\//\-\-/g')
|
||||
PROJECT_NAME = notifications
|
||||
BUILD_DIR_NAME = $(shell pwd | xargs basename | tr -cd '[a-zA-Z0-9_.\-]')
|
||||
HERE=$(shell pwd)
|
||||
export MONOREPO ?= $(shell cd ../../ && pwd)
|
||||
IMAGE_CI ?= ci/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER)
|
||||
IMAGE_CI ?= ci/$(PROJECT_NAME):$(BRANCH_NAME_TAG_SAFE)-$(BUILD_NUMBER)
|
||||
IMAGE_REPO ?= us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME)
|
||||
IMAGE_REPO_FINAL ?= $(IMAGE_REPO):$(BRANCH_NAME)-$(BUILD_NUMBER)
|
||||
IMAGE_REPO_FINAL ?= $(IMAGE_REPO):$(BRANCH_NAME_TAG_SAFE)-$(BUILD_NUMBER)
|
||||
IMAGE_CACHE ?= $(IMAGE_REPO):cache-$(shell cat \
|
||||
$(MONOREPO)/package.json \
|
||||
$(MONOREPO)/package-lock.json \
|
||||
@@ -29,7 +30,7 @@ IMAGE_CACHE ?= $(IMAGE_REPO):cache-$(shell cat \
|
||||
|
||||
DOCKER_COMPOSE_FLAGS ?= -f docker-compose.yml
|
||||
DOCKER_COMPOSE := BUILD_NUMBER=$(BUILD_NUMBER) \
|
||||
BRANCH_NAME=$(BRANCH_NAME) \
|
||||
BRANCH_NAME=$(BRANCH_NAME_TAG_SAFE) \
|
||||
PROJECT_NAME=$(PROJECT_NAME) \
|
||||
MOCHA_GREP=${MOCHA_GREP} \
|
||||
docker compose ${DOCKER_COMPOSE_FLAGS}
|
||||
|
||||
@@ -4,13 +4,14 @@
|
||||
|
||||
BUILD_NUMBER ?= local
|
||||
BRANCH_NAME ?= $(shell git rev-parse --abbrev-ref HEAD)
|
||||
BRANCH_NAME_TAG_SAFE = $(shell echo $(BRANCH_NAME) | sed 's/\//\-\-/g')
|
||||
PROJECT_NAME = project-history
|
||||
BUILD_DIR_NAME = $(shell pwd | xargs basename | tr -cd '[a-zA-Z0-9_.\-]')
|
||||
HERE=$(shell pwd)
|
||||
export MONOREPO ?= $(shell cd ../../ && pwd)
|
||||
IMAGE_CI ?= ci/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER)
|
||||
IMAGE_CI ?= ci/$(PROJECT_NAME):$(BRANCH_NAME_TAG_SAFE)-$(BUILD_NUMBER)
|
||||
IMAGE_REPO ?= us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME)
|
||||
IMAGE_REPO_FINAL ?= $(IMAGE_REPO):$(BRANCH_NAME)-$(BUILD_NUMBER)
|
||||
IMAGE_REPO_FINAL ?= $(IMAGE_REPO):$(BRANCH_NAME_TAG_SAFE)-$(BUILD_NUMBER)
|
||||
IMAGE_CACHE ?= $(IMAGE_REPO):cache-$(shell cat \
|
||||
$(MONOREPO)/package.json \
|
||||
$(MONOREPO)/package-lock.json \
|
||||
@@ -31,7 +32,7 @@ IMAGE_CACHE ?= $(IMAGE_REPO):cache-$(shell cat \
|
||||
|
||||
DOCKER_COMPOSE_FLAGS ?= -f docker-compose.yml
|
||||
DOCKER_COMPOSE := BUILD_NUMBER=$(BUILD_NUMBER) \
|
||||
BRANCH_NAME=$(BRANCH_NAME) \
|
||||
BRANCH_NAME=$(BRANCH_NAME_TAG_SAFE) \
|
||||
PROJECT_NAME=$(PROJECT_NAME) \
|
||||
MOCHA_GREP=${MOCHA_GREP} \
|
||||
docker compose ${DOCKER_COMPOSE_FLAGS}
|
||||
|
||||
@@ -4,13 +4,14 @@
|
||||
|
||||
BUILD_NUMBER ?= local
|
||||
BRANCH_NAME ?= $(shell git rev-parse --abbrev-ref HEAD)
|
||||
BRANCH_NAME_TAG_SAFE = $(shell echo $(BRANCH_NAME) | sed 's/\//\-\-/g')
|
||||
PROJECT_NAME = real-time
|
||||
BUILD_DIR_NAME = $(shell pwd | xargs basename | tr -cd '[a-zA-Z0-9_.\-]')
|
||||
HERE=$(shell pwd)
|
||||
export MONOREPO ?= $(shell cd ../../ && pwd)
|
||||
IMAGE_CI ?= ci/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER)
|
||||
IMAGE_CI ?= ci/$(PROJECT_NAME):$(BRANCH_NAME_TAG_SAFE)-$(BUILD_NUMBER)
|
||||
IMAGE_REPO ?= us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME)
|
||||
IMAGE_REPO_FINAL ?= $(IMAGE_REPO):$(BRANCH_NAME)-$(BUILD_NUMBER)
|
||||
IMAGE_REPO_FINAL ?= $(IMAGE_REPO):$(BRANCH_NAME_TAG_SAFE)-$(BUILD_NUMBER)
|
||||
IMAGE_CACHE ?= $(IMAGE_REPO):cache-$(shell cat \
|
||||
$(MONOREPO)/package.json \
|
||||
$(MONOREPO)/package-lock.json \
|
||||
@@ -27,7 +28,7 @@ IMAGE_CACHE ?= $(IMAGE_REPO):cache-$(shell cat \
|
||||
|
||||
DOCKER_COMPOSE_FLAGS ?= -f docker-compose.yml
|
||||
DOCKER_COMPOSE := BUILD_NUMBER=$(BUILD_NUMBER) \
|
||||
BRANCH_NAME=$(BRANCH_NAME) \
|
||||
BRANCH_NAME=$(BRANCH_NAME_TAG_SAFE) \
|
||||
PROJECT_NAME=$(PROJECT_NAME) \
|
||||
MOCHA_GREP=${MOCHA_GREP} \
|
||||
docker compose ${DOCKER_COMPOSE_FLAGS}
|
||||
|
||||
@@ -3,7 +3,17 @@ import { ProjectAuditLogEntry } from '../../models/ProjectAuditLogEntry.js'
|
||||
import { callbackify } from '@overleaf/promise-utils'
|
||||
import SubscriptionLocator from '../Subscription/SubscriptionLocator.mjs'
|
||||
|
||||
const MANAGED_GROUP_PROJECT_EVENTS = ['accept-invite', 'project-created']
|
||||
const MANAGED_GROUP_PROJECT_EVENTS = [
|
||||
'accept-invite',
|
||||
'project-created',
|
||||
'project-deleted',
|
||||
'project-archived',
|
||||
'project-unarchived',
|
||||
'project-trashed',
|
||||
'project-untrashed',
|
||||
'project-restored',
|
||||
'project-cloned',
|
||||
]
|
||||
|
||||
export default {
|
||||
promises: {
|
||||
|
||||
@@ -168,7 +168,12 @@ const _ProjectController = {
|
||||
deleterUser: user,
|
||||
ipAddress: req.ip,
|
||||
})
|
||||
|
||||
ProjectAuditLogHandler.addEntryIfManagedInBackground(
|
||||
projectId,
|
||||
'project-deleted',
|
||||
user._id,
|
||||
req.ip
|
||||
)
|
||||
res.sendStatus(200)
|
||||
},
|
||||
|
||||
@@ -176,6 +181,12 @@ const _ProjectController = {
|
||||
const projectId = req.params.Project_id
|
||||
const userId = SessionManager.getLoggedInUserId(req.session)
|
||||
await ProjectDeleter.promises.archiveProject(projectId, userId)
|
||||
ProjectAuditLogHandler.addEntryIfManagedInBackground(
|
||||
projectId,
|
||||
'project-archived',
|
||||
userId,
|
||||
req.ip
|
||||
)
|
||||
res.sendStatus(200)
|
||||
},
|
||||
|
||||
@@ -183,6 +194,12 @@ const _ProjectController = {
|
||||
const projectId = req.params.Project_id
|
||||
const userId = SessionManager.getLoggedInUserId(req.session)
|
||||
await ProjectDeleter.promises.unarchiveProject(projectId, userId)
|
||||
ProjectAuditLogHandler.addEntryIfManagedInBackground(
|
||||
projectId,
|
||||
'project-unarchived',
|
||||
userId,
|
||||
req.ip
|
||||
)
|
||||
res.sendStatus(200)
|
||||
},
|
||||
|
||||
@@ -190,6 +207,12 @@ const _ProjectController = {
|
||||
const projectId = req.params.project_id
|
||||
const userId = SessionManager.getLoggedInUserId(req.session)
|
||||
await ProjectDeleter.promises.trashProject(projectId, userId)
|
||||
ProjectAuditLogHandler.addEntryIfManagedInBackground(
|
||||
projectId,
|
||||
'project-trashed',
|
||||
userId,
|
||||
req.ip
|
||||
)
|
||||
res.sendStatus(200)
|
||||
},
|
||||
|
||||
@@ -197,6 +220,12 @@ const _ProjectController = {
|
||||
const projectId = req.params.project_id
|
||||
const userId = SessionManager.getLoggedInUserId(req.session)
|
||||
await ProjectDeleter.promises.untrashProject(projectId, userId)
|
||||
ProjectAuditLogHandler.addEntryIfManagedInBackground(
|
||||
projectId,
|
||||
'project-untrashed',
|
||||
userId,
|
||||
req.ip
|
||||
)
|
||||
res.sendStatus(200)
|
||||
},
|
||||
|
||||
@@ -212,8 +241,15 @@ const _ProjectController = {
|
||||
},
|
||||
|
||||
async restoreProject(req, res) {
|
||||
const user = SessionManager.getLoggedInUserId(req.session)
|
||||
const projectId = req.params.Project_id
|
||||
await ProjectDeleter.promises.restoreProject(projectId)
|
||||
ProjectAuditLogHandler.addEntryIfManagedInBackground(
|
||||
projectId,
|
||||
'project-restored',
|
||||
user._id,
|
||||
req.ip
|
||||
)
|
||||
res.sendStatus(200)
|
||||
},
|
||||
|
||||
@@ -235,6 +271,12 @@ const _ProjectController = {
|
||||
projectName,
|
||||
tags
|
||||
)
|
||||
ProjectAuditLogHandler.addEntryIfManagedInBackground(
|
||||
projectId,
|
||||
'project-cloned',
|
||||
currentUser._id,
|
||||
req.ip
|
||||
)
|
||||
res.json({
|
||||
name: project.name,
|
||||
lastUpdated: project.lastUpdated,
|
||||
@@ -446,7 +488,10 @@ const _ProjectController = {
|
||||
affiliations: InstitutionsGetter.promises
|
||||
.getCurrentAffiliations(userId)
|
||||
.catch(err => {
|
||||
logger.error({ err, userId }, 'failed to get institution licence')
|
||||
logger.error(
|
||||
{ err, userId },
|
||||
'failed to get current affiliations'
|
||||
)
|
||||
return false
|
||||
}),
|
||||
subscription:
|
||||
@@ -1174,12 +1219,15 @@ const _ProjectController = {
|
||||
aiFeaturesAllowed,
|
||||
userIsMemberOfGroupSubscription
|
||||
) {
|
||||
let inEnterpriseCommons = false
|
||||
const affiliations = userValues.affiliations || []
|
||||
for (const affiliation of affiliations) {
|
||||
inEnterpriseCommons =
|
||||
inEnterpriseCommons || affiliation.institution?.enterpriseCommons
|
||||
}
|
||||
const affiliations = userValues.affiliations
|
||||
const affiliateLookupFailed = affiliations === false
|
||||
|
||||
// if affiliations is specifically false instead of empty, we know the affiliate lookup failed, and should defer to blocking auto-loading
|
||||
const inEnterpriseCommons =
|
||||
affiliateLookupFailed ||
|
||||
affiliations.some(
|
||||
affiliation => affiliation.institution?.enterpriseCommons
|
||||
)
|
||||
|
||||
// check if a user has never tried writefull before (writefull.enabled will be null)
|
||||
// if they previously accepted writefull, or are have been already assigned to a trial, user.writefull will be true,
|
||||
|
||||
@@ -14,7 +14,6 @@ import EmailHelper from '../Helpers/EmailHelper.js'
|
||||
import Errors from '../Errors/Errors.js'
|
||||
import { callbackify, callbackifyMultiResult } from '@overleaf/promise-utils'
|
||||
import NotificationsBuilder from '../Notifications/NotificationsBuilder.mjs'
|
||||
import RecurlyClient from './RecurlyClient.mjs'
|
||||
|
||||
const { ObjectId } = mongodb
|
||||
|
||||
@@ -78,18 +77,13 @@ async function _deleteUserSubscription(subscription, userId, ipAddress) {
|
||||
deleterData
|
||||
)
|
||||
|
||||
// Terminate the subscription in Recurly
|
||||
if (subscription.recurlySubscription_id) {
|
||||
try {
|
||||
await RecurlyClient.promises.terminateSubscriptionByUuid(
|
||||
subscription.recurlySubscription_id
|
||||
)
|
||||
} catch (err) {
|
||||
logger.error(
|
||||
{ err, subscriptionId: subscription._id },
|
||||
'terminating subscription failed'
|
||||
)
|
||||
}
|
||||
try {
|
||||
await Modules.promises.hooks.fire('terminateSubscription', subscription)
|
||||
} catch (err) {
|
||||
logger.error(
|
||||
{ err, subscriptionId: subscription._id },
|
||||
'terminating subscription failed'
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,15 @@ function _canHaveNoInitiatorId(operation, info) {
|
||||
}
|
||||
|
||||
// events that are visible to managed user admins in Group Audit Logs view
|
||||
const MANAGED_GROUP_USER_EVENTS = ['login', 'reset-password', 'update-password']
|
||||
const MANAGED_GROUP_USER_EVENTS = [
|
||||
'login',
|
||||
'reset-password',
|
||||
'update-password',
|
||||
'link-dropbox',
|
||||
'unlink-dropbox',
|
||||
'link-github',
|
||||
'unlink-github',
|
||||
]
|
||||
|
||||
/**
|
||||
* Add an audit log entry
|
||||
|
||||
@@ -3,15 +3,15 @@
|
||||
declare -a vitest_args=("$@")
|
||||
|
||||
has_mocha_test=0
|
||||
has_vitest_test=0
|
||||
has_sequential_test=0
|
||||
|
||||
for dir_path in "$@"; do
|
||||
if [ -n "$(find "$dir_path" -name "*.js" -type f -print -quit 2>/dev/null)" ]; then
|
||||
has_mocha_test=1
|
||||
fi
|
||||
|
||||
if [ -n "$(find "$dir_path" -name "*.test.mjs" -type f -print -quit 2>/dev/null)" ]; then
|
||||
has_vitest_test=1
|
||||
if [ -n "$(find "$dir_path" -name "*.sequential.test.mjs" -type f -print -quit 2>/dev/null)" ]; then
|
||||
has_sequential_test=1
|
||||
fi
|
||||
done
|
||||
|
||||
@@ -26,24 +26,26 @@ fi
|
||||
|
||||
echo "Running unit tests in directory: $*"
|
||||
|
||||
# Remove this if/else when we have converted all module tests to vitest.
|
||||
if (( has_vitest_test == 1 )); then
|
||||
npm run test:unit:esm -- "${vitest_args[@]}"
|
||||
vitest_status=$?
|
||||
|
||||
npm run test:unit:esm:parallel -- "${vitest_args[@]}"
|
||||
vitest_parallel_status=$?
|
||||
if (( has_sequential_test == 0 )); then
|
||||
echo "No sequential vitest tests found, skipping sequential vitest step."
|
||||
vitest_sequential_status=0
|
||||
else
|
||||
echo "No vitest tests found in $*, skipping vitest step."
|
||||
vitest_status=0
|
||||
npm run test:unit:esm:sequential -- "${vitest_args[@]}"
|
||||
vitest_sequential_status=$?
|
||||
fi
|
||||
|
||||
if (( has_mocha_test == 1 )); then
|
||||
mocha --recursive --timeout 25000 --exit --grep="$MOCHA_GREP" --require test/unit/bootstrap.js --extension=js "$@"
|
||||
mocha_status=$?
|
||||
else
|
||||
echo "No mocha tests found in $TARGET_DIR, skipping mocha step."
|
||||
echo "No mocha tests found, skipping mocha step."
|
||||
mocha_status=0
|
||||
fi
|
||||
|
||||
if [ "$mocha_status" -eq 0 ] && [ "$vitest_status" -eq 0 ]; then
|
||||
if [ "$mocha_status" -eq 0 ] && [ "$vitest_sequential_status" -eq 0 ] && [ "$vitest_parallel_status" -eq 0 ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@@ -53,8 +55,12 @@ if [ "$mocha_status" -ne 0 ]; then
|
||||
echo "Mocha tests failed with status: $mocha_status"
|
||||
fi
|
||||
|
||||
if [ "$vitest_status" -ne 0 ]; then
|
||||
echo "Vitest tests failed with status: $vitest_status"
|
||||
if [ "$vitest_parallel_status" -ne 0 ]; then
|
||||
echo "Vitest parallel tests failed with status: $vitest_parallel_status"
|
||||
fi
|
||||
|
||||
if [ "$vitest_sequential_status" -ne 0 ]; then
|
||||
echo "Vitest sequential tests failed with status: $vitest_sequential_status"
|
||||
fi
|
||||
|
||||
exit 1
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useSwitchEnableNewEditorState } from '@/features/ide-redesign/hooks/use
|
||||
import { useLayoutContext } from '@/shared/context/layout-context'
|
||||
import { useCallback } from 'react'
|
||||
import {
|
||||
canUseNewEditorViaNewUserFeatureFlag,
|
||||
canUseNewEditorAsNewUser,
|
||||
useIsNewEditorEnabled,
|
||||
} from '@/features/ide-redesign/utils/new-editor-utils'
|
||||
|
||||
@@ -13,7 +13,7 @@ export default function SettingsNewEditor() {
|
||||
const { setEditorRedesignStatus } = useSwitchEnableNewEditorState()
|
||||
const { setLeftMenuShown } = useLayoutContext()
|
||||
const enabled = useIsNewEditorEnabled()
|
||||
const show = canUseNewEditorViaNewUserFeatureFlag()
|
||||
const show = canUseNewEditorAsNewUser()
|
||||
|
||||
const onChange = useCallback(
|
||||
(newValue: boolean) => {
|
||||
|
||||
@@ -2,13 +2,13 @@ import { useCallback } from 'react'
|
||||
import OLButton from '../../shared/components/ol/ol-button'
|
||||
import { useIdeRedesignSwitcherContext } from '../ide-react/context/ide-redesign-switcher-context'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { canUseNewEditorViaPrimaryFeatureFlag } from '../ide-redesign/utils/new-editor-utils'
|
||||
import { canUseNewEditorAsExistingUser } from '../ide-redesign/utils/new-editor-utils'
|
||||
import { useSwitchEnableNewEditorState } from '../ide-redesign/hooks/use-switch-enable-new-editor-state'
|
||||
|
||||
const TryNewEditorButton = () => {
|
||||
const { t } = useTranslation()
|
||||
const { setShowSwitcherModal } = useIdeRedesignSwitcherContext()
|
||||
const showModal = canUseNewEditorViaPrimaryFeatureFlag()
|
||||
const showModal = canUseNewEditorAsExistingUser()
|
||||
const { loading, setEditorRedesignStatus } = useSwitchEnableNewEditorState()
|
||||
|
||||
const onClick = useCallback(() => {
|
||||
|
||||
@@ -11,7 +11,7 @@ import { FC, useCallback, useEffect } from 'react'
|
||||
import {
|
||||
canUseNewEditor,
|
||||
useIsNewEditorEnabled,
|
||||
useIsNewEditorEnabledViaPrimaryFeatureFlag,
|
||||
useIsNewEditorEnabledAsExistingUser,
|
||||
} from '../../utils/new-editor-utils'
|
||||
import Notification from '@/shared/components/notification'
|
||||
import { useSwitchEnableNewEditorState } from '../../hooks/use-switch-enable-new-editor-state'
|
||||
@@ -32,7 +32,7 @@ export const IdeRedesignIntroModal: FC = () => {
|
||||
name: TUTORIAL_KEY,
|
||||
}
|
||||
)
|
||||
const hasAccess = useIsNewEditorEnabledViaPrimaryFeatureFlag()
|
||||
const hasAccess = useIsNewEditorEnabledAsExistingUser()
|
||||
|
||||
useEffect(() => {
|
||||
if (!hasAccess) return
|
||||
|
||||
@@ -4,7 +4,7 @@ import OLTooltip from '@/shared/components/ol/ol-tooltip'
|
||||
import { useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { GiveFeedbackLink } from './give-feedback-link'
|
||||
import { useIsNewEditorEnabledViaPrimaryFeatureFlag } from '../../utils/new-editor-utils'
|
||||
import { useIsNewEditorEnabledAsExistingUser } from '../../utils/new-editor-utils'
|
||||
|
||||
export const BetaActions = () => {
|
||||
const { t } = useTranslation()
|
||||
@@ -12,7 +12,7 @@ export const BetaActions = () => {
|
||||
const openEditorRedesignSwitcherModal = useCallback(() => {
|
||||
setShowSwitcherModal(true)
|
||||
}, [setShowSwitcherModal])
|
||||
const showBetaActions = useIsNewEditorEnabledViaPrimaryFeatureFlag()
|
||||
const showBetaActions = useIsNewEditorEnabledAsExistingUser()
|
||||
|
||||
if (!showBetaActions) {
|
||||
return null
|
||||
|
||||
@@ -30,7 +30,7 @@ import { useSurveyUrl } from '../../hooks/use-survey-url'
|
||||
import getMeta from '@/utils/meta'
|
||||
import EditorCloneProjectModalWrapper from '@/features/clone-project-modal/components/editor-clone-project-modal-wrapper'
|
||||
import useOpenProject from '@/shared/hooks/use-open-project'
|
||||
import { canUseNewEditorViaPrimaryFeatureFlag } from '../../utils/new-editor-utils'
|
||||
import { canUseNewEditorAsExistingUser } from '../../utils/new-editor-utils'
|
||||
|
||||
export const ToolbarMenuBar = () => {
|
||||
const { t } = useTranslation()
|
||||
@@ -44,7 +44,7 @@ export const ToolbarMenuBar = () => {
|
||||
const [showWordCountModal, setShowWordCountModal] = useState(false)
|
||||
const [showCloneProjectModal, setShowCloneProjectModal] = useState(false)
|
||||
const openProject = useOpenProject()
|
||||
const showEditorSwitchMenuOption = canUseNewEditorViaPrimaryFeatureFlag()
|
||||
const showEditorSwitchMenuOption = canUseNewEditorAsExistingUser()
|
||||
|
||||
const anonymous = getMeta('ol-anonymous')
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ import FontFamilySetting from '../components/settings/appearance-settings/font-f
|
||||
import { AvailableUnfilledIcon } from '@/shared/components/material-icon'
|
||||
import { EditorLeftMenuProvider } from '@/features/editor-left-menu/components/editor-left-menu-context'
|
||||
import NewEditorSetting from '../components/settings/editor-settings/new-editor-setting'
|
||||
import { canUseNewEditorViaNewUserFeatureFlag } from '../utils/new-editor-utils'
|
||||
import { canUseNewEditorAsNewUser } from '../utils/new-editor-utils'
|
||||
|
||||
const [referenceSearchSettingModule] = importOverleafModules(
|
||||
'referenceSearchSetting'
|
||||
@@ -77,7 +77,7 @@ export const SettingsModalProvider: FC<React.PropsWithChildren> = ({
|
||||
children,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const showEditorSwitch = canUseNewEditorViaNewUserFeatureFlag()
|
||||
const showEditorSwitch = canUseNewEditorAsNewUser()
|
||||
|
||||
// TODO ide-redesign-cleanup: Rename this field and move it directly into this context
|
||||
const { leftMenuShown, setLeftMenuShown } = useLayoutContext()
|
||||
|
||||
@@ -2,13 +2,24 @@ import { useUserSettingsContext } from '@/shared/context/user-settings-context'
|
||||
import getMeta from '@/utils/meta'
|
||||
import { isSplitTestEnabled, getSplitTestVariant } from '@/utils/splitTestUtils'
|
||||
|
||||
export const ignoringUserCutoffDate =
|
||||
const ignoringUserCutoffDate =
|
||||
new URLSearchParams(window.location.search).get('skip-new-user-check') ===
|
||||
'true'
|
||||
|
||||
const NEW_USER_CUTOFF_DATE = new Date(Date.UTC(2025, 8, 23, 13, 0, 0)) // 2pm British Summer Time on September 23, 2025
|
||||
// For E2E tests, allow forcing a user to be treated as an existing user
|
||||
const existingUserOverride =
|
||||
new URLSearchParams(window.location.search).get('existing-user-override') ===
|
||||
'true'
|
||||
|
||||
// We don't want to enable the new editor on server-pro/CE until we have fully rolled it out on SaaS
|
||||
const { isOverleaf } = getMeta('ol-ExposedSettings')
|
||||
|
||||
const SPLIT_TEST_USER_CUTOFF_DATE = new Date(Date.UTC(2025, 8, 23, 13, 0, 0)) // 2pm British Summer Time on September 23, 2025
|
||||
const NEW_USER_CUTOFF_DATE = new Date(Date.UTC(2025, 10, 12, 12, 0, 0)) // 12pm GMT on November 12, 2025
|
||||
|
||||
export const isNewUser = () => {
|
||||
if (existingUserOverride) return false
|
||||
|
||||
if (ignoringUserCutoffDate) return true
|
||||
const user = getMeta('ol-user')
|
||||
|
||||
@@ -18,32 +29,37 @@ export const isNewUser = () => {
|
||||
return createdAt > NEW_USER_CUTOFF_DATE
|
||||
}
|
||||
|
||||
export const canUseNewEditorViaPrimaryFeatureFlag = () => {
|
||||
return isSplitTestEnabled('editor-redesign')
|
||||
export const isSplitTestUser = () => {
|
||||
if (existingUserOverride) return false
|
||||
|
||||
const user = getMeta('ol-user')
|
||||
if (!user.signUpDate) return false
|
||||
|
||||
const createdAt = new Date(user.signUpDate)
|
||||
return (
|
||||
createdAt > SPLIT_TEST_USER_CUTOFF_DATE && createdAt <= NEW_USER_CUTOFF_DATE
|
||||
)
|
||||
}
|
||||
|
||||
export const canUseNewEditorViaNewUserFeatureFlag = () => {
|
||||
const newUserTestVariant = getSplitTestVariant('editor-redesign-new-users')
|
||||
export const canUseNewEditorAsExistingUser = () => {
|
||||
return !canUseNewEditorAsNewUser() && isSplitTestEnabled('editor-redesign')
|
||||
}
|
||||
|
||||
export const canUseNewEditorAsNewUser = () => {
|
||||
const newUserTestVariant = getSplitTestVariant('editor-redesign-new-users')
|
||||
return (
|
||||
!canUseNewEditorViaPrimaryFeatureFlag() &&
|
||||
isNewUser() &&
|
||||
(newUserTestVariant === 'new-editor' ||
|
||||
newUserTestVariant === 'new-editor-old-logs' ||
|
||||
newUserTestVariant === 'new-editor-new-logs-old-position')
|
||||
isOverleaf &&
|
||||
(isNewUser() || (isSplitTestUser() && newUserTestVariant !== 'default'))
|
||||
)
|
||||
}
|
||||
|
||||
export const canUseNewEditor = () => {
|
||||
return (
|
||||
canUseNewEditorViaPrimaryFeatureFlag() ||
|
||||
canUseNewEditorViaNewUserFeatureFlag()
|
||||
)
|
||||
return canUseNewEditorAsExistingUser() || canUseNewEditorAsNewUser()
|
||||
}
|
||||
|
||||
export const useIsNewEditorEnabledViaPrimaryFeatureFlag = () => {
|
||||
export const useIsNewEditorEnabledAsExistingUser = () => {
|
||||
const { userSettings } = useUserSettingsContext()
|
||||
const hasAccess = canUseNewEditorViaPrimaryFeatureFlag()
|
||||
const hasAccess = canUseNewEditorAsExistingUser()
|
||||
const enabled = userSettings.enableNewEditor
|
||||
return hasAccess && enabled
|
||||
}
|
||||
@@ -54,9 +70,3 @@ export const useIsNewEditorEnabled = () => {
|
||||
const enabled = userSettings.enableNewEditor
|
||||
return hasAccess && enabled
|
||||
}
|
||||
|
||||
export function useNewEditorVariant() {
|
||||
const newEditor = useIsNewEditorEnabled()
|
||||
if (!newEditor) return 'default'
|
||||
return 'new-editor-new-logs-old-position'
|
||||
}
|
||||
|
||||
@@ -8,12 +8,9 @@ import OLButton from '@/shared/components/ol/ol-button'
|
||||
import * as eventTracking from '../../../infrastructure/event-tracking'
|
||||
import getMeta from '@/utils/meta'
|
||||
import { populateEditorRedesignSegmentation } from '@/shared/hooks/use-editor-analytics'
|
||||
import {
|
||||
isNewUser,
|
||||
useIsNewEditorEnabled,
|
||||
} from '@/features/ide-redesign/utils/new-editor-utils'
|
||||
import { getSplitTestVariant, isSplitTestEnabled } from '@/utils/splitTestUtils'
|
||||
import CompileTimeoutPaywallModal from '@/features/pdf-preview/components/compile-timeout-paywall-modal'
|
||||
import { useIsNewEditorEnabled } from '@/features/ide-redesign/utils/new-editor-utils'
|
||||
import { isSplitTestEnabled } from '@/utils/splitTestUtils'
|
||||
|
||||
function TimeoutUpgradePromptNew() {
|
||||
const {
|
||||
@@ -98,21 +95,12 @@ const CompileTimeout = memo(function CompileTimeout({
|
||||
isCompileTimeoutTargetPlansEnabled,
|
||||
}: CompileTimeoutProps) {
|
||||
const { t } = useTranslation()
|
||||
const newEditor = useIsNewEditorEnabled()
|
||||
const extraSearchParams = useMemo(() => {
|
||||
if (!isNewUser()) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const variant = getSplitTestVariant('editor-redesign-new-users')
|
||||
|
||||
if (!variant) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return {
|
||||
itm_content: variant,
|
||||
itm_content: newEditor ? 'new-editor' : 'old-editor',
|
||||
}
|
||||
}, [])
|
||||
}, [newEditor])
|
||||
|
||||
const handleFreeTrialClick = useCallback(
|
||||
(event: React.MouseEvent<HTMLButtonElement>) => {
|
||||
|
||||
@@ -41,10 +41,10 @@ function ProjectListTableRow({ project, selected }: ProjectListTableRowProps) {
|
||||
<InlineTags projectId={project.id} />
|
||||
</td>
|
||||
<td className="dash-cell-actions">
|
||||
<div className="d-none d-md-block">
|
||||
<div className="d-none d-lg-block">
|
||||
<ActionsCell project={project} />
|
||||
</div>
|
||||
<div className="d-md-none">
|
||||
<div className="d-lg-none">
|
||||
<ActionsDropdown project={project} />
|
||||
</div>
|
||||
</td>
|
||||
|
||||
60
services/web/frontend/js/shared/components/ds/ds-button.tsx
Normal file
60
services/web/frontend/js/shared/components/ds/ds-button.tsx
Normal file
@@ -0,0 +1,60 @@
|
||||
import { forwardRef, ReactNode } from 'react'
|
||||
import { Button, ButtonProps } from 'react-bootstrap'
|
||||
|
||||
type DSButtonProps = Pick<
|
||||
ButtonProps,
|
||||
| 'children'
|
||||
| 'disabled'
|
||||
| 'href'
|
||||
| 'id'
|
||||
| 'target'
|
||||
| 'rel'
|
||||
| 'onClick'
|
||||
| 'onMouseDown'
|
||||
| 'onMouseOver'
|
||||
| 'onMouseOut'
|
||||
| 'onFocus'
|
||||
| 'onBlur'
|
||||
| 'size'
|
||||
| 'active'
|
||||
| 'type'
|
||||
> & {
|
||||
leadingIcon?: ReactNode
|
||||
trailingIcon?: ReactNode
|
||||
variant?: 'primary' | 'secondary' | 'tertiary' | 'danger'
|
||||
}
|
||||
|
||||
const DSButton = forwardRef<HTMLButtonElement, DSButtonProps>(
|
||||
(
|
||||
{
|
||||
children,
|
||||
leadingIcon,
|
||||
trailingIcon,
|
||||
variant = 'primary',
|
||||
size,
|
||||
...props
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
return (
|
||||
<Button
|
||||
className="d-inline-grid btn-ds"
|
||||
variant={variant}
|
||||
size={size}
|
||||
{...props}
|
||||
ref={ref}
|
||||
role={undefined}
|
||||
>
|
||||
<span className="button-content">
|
||||
{leadingIcon}
|
||||
{children}
|
||||
{trailingIcon}
|
||||
</span>
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
DSButton.displayName = 'DSButton'
|
||||
|
||||
export default DSButton
|
||||
37
services/web/frontend/stories/shared/ds-button.stories.tsx
Normal file
37
services/web/frontend/stories/shared/ds-button.stories.tsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import { Meta } from '@storybook/react'
|
||||
import { figmaDesignUrl } from '../../../.storybook/utils/figma-design-url'
|
||||
import DSButton from '@/shared/components/ds/ds-button'
|
||||
|
||||
type Args = React.ComponentProps<typeof DSButton>
|
||||
|
||||
export const Button = (args: Args) => {
|
||||
return <DSButton {...args} />
|
||||
}
|
||||
|
||||
const meta: Meta<typeof DSButton> = {
|
||||
title: 'Shared / Components / DS Button',
|
||||
component: DSButton,
|
||||
args: {
|
||||
children: 'Button',
|
||||
},
|
||||
argTypes: {
|
||||
size: {
|
||||
control: 'radio',
|
||||
options: ['lg', 'md', 'sm'],
|
||||
},
|
||||
variant: {
|
||||
control: 'radio',
|
||||
options: ['primary', 'secondary', 'tertiary', 'danger'],
|
||||
},
|
||||
},
|
||||
parameters: {
|
||||
controls: {
|
||||
include: ['children', 'disabled', 'size', 'variant'],
|
||||
},
|
||||
...figmaDesignUrl(
|
||||
'https://www.figma.com/design/aJQlecvqCS9Ry8b6JA1lQN/DS---Components?node-id=4565-2932&m=dev'
|
||||
),
|
||||
},
|
||||
}
|
||||
|
||||
export default meta
|
||||
@@ -21,7 +21,8 @@
|
||||
$borderless: true,
|
||||
$disabled-color: $content-disabled,
|
||||
$disabled-background: $bg-light-disabled,
|
||||
$disabled-border: $bg-light-disabled
|
||||
$disabled-border: $disabled-background,
|
||||
$active-background: $hover-background
|
||||
) {
|
||||
--bs-btn-color: #{$color};
|
||||
--bs-btn-bg: #{$background};
|
||||
@@ -30,7 +31,7 @@
|
||||
--bs-btn-hover-bg: #{$hover-background};
|
||||
--bs-btn-hover-border-color: #{$hover-border};
|
||||
--bs-btn-active-color: #{$color};
|
||||
--bs-btn-active-bg: #{$hover-background};
|
||||
--bs-btn-active-bg: #{$active-background};
|
||||
--bs-btn-active-border-color: #{$hover-border};
|
||||
--bs-btn-disabled-color: #{$disabled-color};
|
||||
--bs-btn-disabled-bg: #{$disabled-background};
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
@import 'ciam-colors';
|
||||
@import '../ds/all'; // DS design system styles
|
||||
@import 'ciam-layout';
|
||||
@import 'ciam-mixins';
|
||||
@import 'ciam-spacing';
|
||||
@import 'ciam-variables';
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
.ciam-enabled {
|
||||
--ciam-color-neutral-50: #fafafa;
|
||||
--ciam-color-neutral-100: #f2f2f2;
|
||||
--ciam-color-neutral-200: #e6e6e6;
|
||||
--ciam-color-neutral-300: #d6d6d6;
|
||||
--ciam-color-neutral-400: #c7c7c7;
|
||||
--ciam-color-neutral-500: #b5b5b5;
|
||||
--ciam-color-neutral-600: #a1a1a1;
|
||||
--ciam-color-neutral-700: #8a8a8a;
|
||||
--ciam-color-neutral-800: #6b6b6b;
|
||||
--ciam-color-neutral-900: #383838;
|
||||
--ciam-color-neutral-950: #262626;
|
||||
--ciam-color-green-50: #f2f8f5;
|
||||
--ciam-color-green-100: #e3f2eb;
|
||||
--ciam-color-green-200: #c0e7d6;
|
||||
--ciam-color-green-300: #8adbb7;
|
||||
--ciam-color-green-400: #38cc89;
|
||||
--ciam-color-green-500: #26b072;
|
||||
--ciam-color-green-600: #158954;
|
||||
--ciam-color-green-700: #19754c;
|
||||
--ciam-color-green-800: #196241;
|
||||
--ciam-color-green-900: #164630;
|
||||
--ciam-color-green-950: #112c20;
|
||||
--ciam-color-yellow-50: #fffaeb;
|
||||
--ciam-color-yellow-100: #fff7db;
|
||||
--ciam-color-yellow-200: #ffeeb8;
|
||||
--ciam-color-yellow-300: #ffe58f;
|
||||
--ciam-color-yellow-400: #ffda61;
|
||||
--ciam-color-yellow-500: #ffcc20;
|
||||
--ciam-color-yellow-600: #f0b800;
|
||||
--ciam-color-yellow-700: #d1a000;
|
||||
--ciam-color-yellow-800: #ad8500;
|
||||
--ciam-color-yellow-900: #806200;
|
||||
--ciam-color-yellow-950: #574200;
|
||||
--ciam-color-red-50: #fff5f7;
|
||||
--ciam-color-red-100: #fee7eb;
|
||||
--ciam-color-red-200: #fdc9d3;
|
||||
--ciam-color-red-300: #fba7b7;
|
||||
--ciam-color-red-400: #f97b92;
|
||||
--ciam-color-red-500: #f51d43;
|
||||
--ciam-color-red-600: #e60a32;
|
||||
--ciam-color-red-700: #c3092b;
|
||||
--ciam-color-red-800: #a10723;
|
||||
--ciam-color-red-900: #75051a;
|
||||
--ciam-color-red-950: #530412;
|
||||
--ciam-color-blue-50: #f7fafd;
|
||||
--ciam-color-blue-100: #ecf2f9;
|
||||
--ciam-color-blue-200: #d4e3f2;
|
||||
--ciam-color-blue-300: #bdd4ea;
|
||||
--ciam-color-blue-400: #a2c3e2;
|
||||
--ciam-color-blue-500: #7facd7;
|
||||
--ciam-color-blue-600: #5893cb;
|
||||
--ciam-color-blue-700: #3470a8;
|
||||
--ciam-color-blue-800: #2b5d8c;
|
||||
--ciam-color-blue-900: #1e4161;
|
||||
--ciam-color-blue-950: #17314a;
|
||||
--ciam-color-teal-50: #f1f8f8;
|
||||
--ciam-color-teal-100: #e3f2f1;
|
||||
--ciam-color-teal-200: #c1e2df;
|
||||
--ciam-color-teal-300: #9ed1cd;
|
||||
--ciam-color-teal-400: #6dbab4;
|
||||
--ciam-color-teal-500: #4a9d96;
|
||||
--ciam-color-teal-600: #438e88;
|
||||
--ciam-color-teal-700: #3b7d77;
|
||||
--ciam-color-teal-800: #2f6460;
|
||||
--ciam-color-teal-900: #244c49;
|
||||
--ciam-color-teal-950: #193432;
|
||||
}
|
||||
@@ -1,18 +1,16 @@
|
||||
@import 'ciam-mixins';
|
||||
|
||||
.ciam-layout {
|
||||
padding: var(--ciam-spacing-350);
|
||||
padding: var(--ds-spacing-350);
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
flex-direction: column;
|
||||
|
||||
@include ciam-body-md-regular;
|
||||
@include ds-body-md-regular;
|
||||
}
|
||||
|
||||
.ciam-enabled {
|
||||
font-family: var(--ciam-font-family-sans), sans-serif;
|
||||
color: var(--ciam-color-text-primary);
|
||||
font-size: var(--ciam-font-size-400);
|
||||
font-family: var(--ds-font-family-sans), sans-serif;
|
||||
color: var(--ds-color-text-primary);
|
||||
font-size: var(--ds-font-size-400);
|
||||
line-height: 1.5;
|
||||
|
||||
.ciam-container {
|
||||
@@ -25,48 +23,48 @@
|
||||
background-size: contain;
|
||||
height: 64px;
|
||||
width: 130px;
|
||||
margin: var(--ciam-spacing-350) auto;
|
||||
margin: var(--ds-spacing-350) auto;
|
||||
display: block;
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
margin: var(--ciam-spacing-350) var(--ciam-spacing-800);
|
||||
margin: var(--ds-spacing-350) var(--ds-spacing-800);
|
||||
}
|
||||
}
|
||||
|
||||
h1 {
|
||||
@include ciam-heading-sm-semibold;
|
||||
@include ds-heading-sm-semibold;
|
||||
}
|
||||
|
||||
.ciam-card {
|
||||
box-shadow:
|
||||
0 4px 6px -4px rgb(0 0 0 / 10%),
|
||||
0 1px 29px -3px rgb(0 0 0 / 16%);
|
||||
padding: var(--ciam-spacing-800) var(--ciam-spacing-400);
|
||||
border-radius: var(--ciam-border-radius-400);
|
||||
padding: var(--ds-spacing-800) var(--ds-spacing-400);
|
||||
border-radius: var(--ds-border-radius-400);
|
||||
max-width: 460px;
|
||||
margin: var(--ciam-spacing-400) auto;
|
||||
margin: var(--ds-spacing-400) auto;
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
padding: var(--ciam-spacing-1300);
|
||||
padding: var(--ds-spacing-1300);
|
||||
}
|
||||
}
|
||||
|
||||
footer {
|
||||
display: flex;
|
||||
gap: var(--ciam-spacing-600);
|
||||
gap: var(--ds-spacing-600);
|
||||
text-transform: uppercase;
|
||||
justify-content: center;
|
||||
margin: var(--ciam-spacing-350) auto;
|
||||
margin: var(--ds-spacing-350) auto;
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
margin: var(--ciam-spacing-350) var(--ciam-spacing-800);
|
||||
margin: var(--ds-spacing-350) var(--ds-spacing-800);
|
||||
justify-content: start;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
|
||||
@include ciam-body-sm-regular;
|
||||
@include ds-body-sm-regular;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
@mixin ciam-body-xs-regular() {
|
||||
font-size: 0.75rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
|
||||
@mixin ciam-body-xs-semibold() {
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
|
||||
@mixin ciam-body-sm-regular() {
|
||||
font-size: 0.875rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
|
||||
@mixin ciam-body-sm-semibold() {
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
|
||||
@mixin ciam-body-md-regular() {
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.5rem;
|
||||
}
|
||||
|
||||
@mixin ciam-body-md-semibold() {
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.5rem;
|
||||
}
|
||||
|
||||
@mixin ciam-body-lg-regular() {
|
||||
font-size: 1.125rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.75rem;
|
||||
}
|
||||
|
||||
@mixin ciam-body-lg-semibold() {
|
||||
font-size: 1.125rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.75rem;
|
||||
}
|
||||
|
||||
@mixin ciam-heading-xs-regular() {
|
||||
font-size: 1.125rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.5rem;
|
||||
}
|
||||
|
||||
@mixin ciam-heading-xs-semibold() {
|
||||
font-size: 1.125rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.5rem;
|
||||
}
|
||||
|
||||
@mixin ciam-heading-sm-regular() {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.75rem;
|
||||
}
|
||||
|
||||
@mixin ciam-heading-sm-semibold() {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.75rem;
|
||||
}
|
||||
|
||||
@mixin ciam-heading-md-regular() {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 400;
|
||||
line-height: 2rem;
|
||||
}
|
||||
|
||||
@mixin ciam-heading-md-semibold() {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
line-height: 2rem;
|
||||
}
|
||||
|
||||
@mixin ciam-heading-lg-regular() {
|
||||
font-size: 2rem;
|
||||
font-weight: 400;
|
||||
line-height: 2.5rem;
|
||||
}
|
||||
|
||||
@mixin ciam-heading-lg-semibold() {
|
||||
font-size: 2rem;
|
||||
font-weight: 600;
|
||||
line-height: 2.5rem;
|
||||
}
|
||||
|
||||
@mixin ciam-heading-xl-regular() {
|
||||
font-size: 2.5rem;
|
||||
font-weight: 400;
|
||||
line-height: 3rem;
|
||||
}
|
||||
|
||||
@mixin ciam-heading-xl-semibold() {
|
||||
font-size: 2.5rem;
|
||||
font-weight: 600;
|
||||
line-height: 3rem;
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
.ciam-enabled {
|
||||
--ciam-font-weight-regular: 400;
|
||||
--ciam-font-weight-medium: 500;
|
||||
--ciam-font-weight-semibold: 600;
|
||||
--ciam-font-weight-bold: 700;
|
||||
--ciam-font-family-sans: inter, sans-serif;
|
||||
--ciam-spacing-50: 2px;
|
||||
--ciam-spacing-100: 4px;
|
||||
--ciam-spacing-150: 6px;
|
||||
--ciam-spacing-200: 8px;
|
||||
--ciam-spacing-250: 10px;
|
||||
--ciam-spacing-300: 12px;
|
||||
--ciam-spacing-350: 14px;
|
||||
--ciam-spacing-400: 16px;
|
||||
--ciam-spacing-500: 20px;
|
||||
--ciam-spacing-600: 24px;
|
||||
--ciam-spacing-700: 28px;
|
||||
--ciam-spacing-800: 32px;
|
||||
--ciam-spacing-900: 36px;
|
||||
--ciam-spacing-1000: 40px;
|
||||
--ciam-spacing-1100: 44px;
|
||||
--ciam-spacing-1200: 48px;
|
||||
--ciam-spacing-1300: 52px;
|
||||
--ciam-spacing-1400: 56px;
|
||||
--ciam-spacing-1500: 60px;
|
||||
--ciam-spacing-1600: 64px;
|
||||
--ciam-spacing-1700: 68px;
|
||||
--ciam-spacing-1800: 72px;
|
||||
--ciam-spacing-1900: 76px;
|
||||
--ciam-spacing-2000: 80px;
|
||||
--ciam-spacing-2100: 84px;
|
||||
--ciam-spacing-2200: 88px;
|
||||
--ciam-spacing-2300: 92px;
|
||||
--ciam-spacing-2400: 96px;
|
||||
--ciam-base-unit: 4px;
|
||||
--ciam-font-size-300: 12px;
|
||||
--ciam-font-size-350: 14px;
|
||||
--ciam-font-size-400: 16px;
|
||||
--ciam-font-size-450: 18px;
|
||||
--ciam-font-size-500: 20px;
|
||||
--ciam-font-size-600: 24px;
|
||||
--ciam-font-size-700: 28px;
|
||||
--ciam-font-size-800: 32px;
|
||||
--ciam-font-size-1000: 40px;
|
||||
--ciam-font-size-1400: 56px;
|
||||
--ciam-font-size-1800: 72px;
|
||||
--ciam-font-line-height-400: 16px;
|
||||
--ciam-font-line-height-500: 20px;
|
||||
--ciam-font-line-height-600: 24px;
|
||||
--ciam-font-line-height-700: 28px;
|
||||
--ciam-font-line-height-800: 32px;
|
||||
--ciam-font-line-height-900: 36px;
|
||||
--ciam-font-line-height-1000: 40px;
|
||||
--ciam-font-line-height-1200: 48px;
|
||||
--ciam-font-line-height-1600: 64px;
|
||||
--ciam-font-line-height-1800: 72px;
|
||||
--ciam-border-width-25: 1px;
|
||||
--ciam-border-width-50: 2px;
|
||||
--ciam-border-radius-50: 2px;
|
||||
--ciam-border-radius-100: 4px;
|
||||
--ciam-border-radius-200: 8px;
|
||||
--ciam-border-radius-300: 12px;
|
||||
--ciam-border-radius-400: 16px;
|
||||
--ciam-border-radius-600: 24px;
|
||||
--ciam-border-radius-full: 9999px;
|
||||
}
|
||||
@@ -1,17 +1,13 @@
|
||||
// TODO: Replace `fuchsia` by the correct colors.
|
||||
|
||||
.ciam-enabled {
|
||||
// Base variables
|
||||
--ciam-color-text-secondary: var(--ciam-color-neutral-800);
|
||||
--ciam-color-text-primary: var(--ciam-color-neutral-900);
|
||||
|
||||
// Links
|
||||
// used in services/web/frontend/stylesheets/base/links.scss
|
||||
--link-color: var(--ciam-color-text-secondary);
|
||||
--link-color: var(--ds-color-text-secondary);
|
||||
--link-hover-color: fuchsia;
|
||||
|
||||
// TODO: validate that this is correct
|
||||
--link-visited-color: var(--ciam-color-text-secondary);
|
||||
--link-visited-color: var(--ds-color-text-secondary);
|
||||
--link-color-dark: fuchsia;
|
||||
--link-hover-color-dark: fuchsia;
|
||||
--link-visited-color-dark: fuchsia;
|
||||
|
||||
7
services/web/frontend/stylesheets/ds/all.scss
Normal file
7
services/web/frontend/stylesheets/ds/all.scss
Normal file
@@ -0,0 +1,7 @@
|
||||
@import 'colors';
|
||||
@import 'typography';
|
||||
@import 'spacing';
|
||||
@import 'border';
|
||||
@import 'theme';
|
||||
@import 'mixins';
|
||||
@import 'components/all';
|
||||
13
services/web/frontend/stylesheets/ds/border.scss
Normal file
13
services/web/frontend/stylesheets/ds/border.scss
Normal file
@@ -0,0 +1,13 @@
|
||||
:root {
|
||||
--ds-border-width-25: 1px;
|
||||
--ds-border-width-50: 2px;
|
||||
|
||||
// Border radius
|
||||
--ds-border-radius-full: 9999px;
|
||||
--ds-border-radius-50: 2px;
|
||||
--ds-border-radius-100: 4px;
|
||||
--ds-border-radius-200: 8px;
|
||||
--ds-border-radius-300: 12px;
|
||||
--ds-border-radius-400: 16px;
|
||||
--ds-border-radius-600: 24px;
|
||||
}
|
||||
83
services/web/frontend/stylesheets/ds/colors.scss
Normal file
83
services/web/frontend/stylesheets/ds/colors.scss
Normal file
@@ -0,0 +1,83 @@
|
||||
:root {
|
||||
// Neutral/grey
|
||||
--ds-color-neutral-50: #fafafa;
|
||||
--ds-color-neutral-100: #f2f2f2;
|
||||
--ds-color-neutral-200: #e6e6e6;
|
||||
--ds-color-neutral-300: #d6d6d6;
|
||||
--ds-color-neutral-400: #c7c7c7;
|
||||
--ds-color-neutral-500: #b5b5b5;
|
||||
--ds-color-neutral-600: #a1a1a1;
|
||||
--ds-color-neutral-700: #8a8a8a;
|
||||
--ds-color-neutral-800: #6b6b6b;
|
||||
--ds-color-neutral-900: #383838;
|
||||
--ds-color-neutral-950: #262626;
|
||||
|
||||
// Green
|
||||
--ds-color-green-50: #f2f8f5;
|
||||
--ds-color-green-100: #e3f2eb;
|
||||
--ds-color-green-200: #c0e7d6;
|
||||
--ds-color-green-300: #8adbb7;
|
||||
--ds-color-green-400: #38cc89;
|
||||
--ds-color-green-500: #26b072;
|
||||
--ds-color-green-600: #158954;
|
||||
--ds-color-green-700: #19754c;
|
||||
--ds-color-green-800: #196241;
|
||||
--ds-color-green-900: #164630;
|
||||
--ds-color-green-950: #112c20;
|
||||
|
||||
// Yellow
|
||||
--ds-color-yellow-50: #fffaeb;
|
||||
--ds-color-yellow-100: #fff7db;
|
||||
--ds-color-yellow-200: #ffeeb8;
|
||||
--ds-color-yellow-300: #ffe58f;
|
||||
--ds-color-yellow-400: #ffda61;
|
||||
--ds-color-yellow-500: #ffcc20;
|
||||
--ds-color-yellow-600: #f0b800;
|
||||
--ds-color-yellow-700: #d1a000;
|
||||
--ds-color-yellow-800: #ad8500;
|
||||
--ds-color-yellow-900: #806200;
|
||||
--ds-color-yellow-950: #574200;
|
||||
|
||||
// Red
|
||||
--ds-color-red-50: #fff5f7;
|
||||
--ds-color-red-100: #fee7eb;
|
||||
--ds-color-red-200: #fdc9d3;
|
||||
--ds-color-red-300: #fba7b7;
|
||||
--ds-color-red-400: #f97b92;
|
||||
--ds-color-red-500: #f51d43;
|
||||
--ds-color-red-600: #e60a32;
|
||||
--ds-color-red-700: #c3092b;
|
||||
--ds-color-red-800: #a10723;
|
||||
--ds-color-red-900: #75051a;
|
||||
--ds-color-red-950: #530412;
|
||||
|
||||
// Blue
|
||||
--ds-color-blue-50: #f7fafd;
|
||||
--ds-color-blue-100: #ecf2f9;
|
||||
--ds-color-blue-200: #d4e3f2;
|
||||
--ds-color-blue-300: #bdd4ea;
|
||||
--ds-color-blue-400: #a2c3e2;
|
||||
--ds-color-blue-500: #7facd7;
|
||||
--ds-color-blue-600: #5893cb;
|
||||
--ds-color-blue-700: #3470a8;
|
||||
--ds-color-blue-800: #2b5d8c;
|
||||
--ds-color-blue-900: #1e4161;
|
||||
--ds-color-blue-950: #17314a;
|
||||
|
||||
// Teal
|
||||
--ds-color-teal-50: #f1f8f8;
|
||||
--ds-color-teal-100: #e3f2f1;
|
||||
--ds-color-teal-200: #c1e2df;
|
||||
--ds-color-teal-300: #9ed1cd;
|
||||
--ds-color-teal-400: #6dbab4;
|
||||
--ds-color-teal-500: #4a9d96;
|
||||
--ds-color-teal-600: #438e88;
|
||||
--ds-color-teal-700: #3b7d77;
|
||||
--ds-color-teal-800: #2f6460;
|
||||
--ds-color-teal-900: #244c49;
|
||||
--ds-color-teal-950: #193432;
|
||||
|
||||
// Black and white
|
||||
--ds-color-white: #fff;
|
||||
--ds-color-black: #000;
|
||||
}
|
||||
1
services/web/frontend/stylesheets/ds/components/all.scss
Normal file
1
services/web/frontend/stylesheets/ds/components/all.scss
Normal file
@@ -0,0 +1 @@
|
||||
@import 'button';
|
||||
81
services/web/frontend/stylesheets/ds/components/button.scss
Normal file
81
services/web/frontend/stylesheets/ds/components/button.scss
Normal file
@@ -0,0 +1,81 @@
|
||||
.btn.btn-ds {
|
||||
--bs-btn-font-family: var(--ds-font-family-sans);
|
||||
--bs-btn-border-radius: var(--ds-border-radius-200);
|
||||
|
||||
&:focus-visible {
|
||||
outline: 2px solid var(--ds-color-yellow-500);
|
||||
outline-offset: 2px;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
// Default size
|
||||
@include ol-button-size(
|
||||
$font-size: var(--ds-font-size-400),
|
||||
$line-height: var(--ds-font-line-height-600),
|
||||
$padding-x: var(--ds-spacing-400),
|
||||
$padding-y: var(--ds-spacing-100)
|
||||
);
|
||||
|
||||
&.btn-lg {
|
||||
@include ol-button-size(
|
||||
$font-size: var(--ds-font-size-400),
|
||||
$line-height: var(--ds-font-line-height-600),
|
||||
$padding-x: var(--ds-spacing-400),
|
||||
$padding-y: var(--ds-spacing-250)
|
||||
);
|
||||
}
|
||||
|
||||
&.btn-sm {
|
||||
@include ol-button-size(
|
||||
$font-size: var(--ds-font-size-350),
|
||||
$line-height: var(--ds-font-line-height-500),
|
||||
$padding-x: var(--ds-spacing-200),
|
||||
$padding-y: var(--ds-spacing-100)
|
||||
);
|
||||
}
|
||||
|
||||
// Variants
|
||||
&.btn-primary {
|
||||
@include ol-button-variant(
|
||||
$color: var(--ds-color-white),
|
||||
$background: var(--ds-color-neutral-950),
|
||||
$hover-background: var(--ds-color-neutral-900),
|
||||
$active-background: var(--ds-color-neutral-800),
|
||||
$disabled-color: var(--ds-color-neutral-700),
|
||||
$disabled-background: var(--ds-color-neutral-100)
|
||||
);
|
||||
}
|
||||
|
||||
&.btn-secondary {
|
||||
@include ol-button-variant(
|
||||
$color: var(--ds-color-neutral-950),
|
||||
$background: var(--ds-color-neutral-200),
|
||||
$hover-background: var(--ds-color-neutral-300),
|
||||
$active-background: var(--ds-color-neutral-400),
|
||||
$disabled-color: var(--ds-color-neutral-700),
|
||||
$disabled-background: var(--ds-color-neutral-100)
|
||||
);
|
||||
}
|
||||
|
||||
&.btn-tertiary {
|
||||
@include ol-button-variant(
|
||||
$color: var(--ds-color-neutral-950),
|
||||
$background: var(--ds-color-white),
|
||||
$hover-background: var(--ds-color-neutral-100),
|
||||
$active-background: var(--ds-color-neutral-200),
|
||||
$disabled-color: var(--ds-color-neutral-700),
|
||||
$disabled-background: var(--ds-color-neutral-100)
|
||||
);
|
||||
}
|
||||
|
||||
&.btn-danger {
|
||||
@include ol-button-variant(
|
||||
$color: var(--ds-color-white),
|
||||
$background: var(--ds-color-red-700),
|
||||
$hover-background: var(--ds-color-red-800),
|
||||
$active-background: var(--ds-color-red-900),
|
||||
$disabled-color: var(--ds-color-neutral-700),
|
||||
$disabled-background: var(--ds-color-neutral-100)
|
||||
);
|
||||
}
|
||||
}
|
||||
109
services/web/frontend/stylesheets/ds/mixins.scss
Normal file
109
services/web/frontend/stylesheets/ds/mixins.scss
Normal file
@@ -0,0 +1,109 @@
|
||||
// Typography mixins for consistent text styles
|
||||
|
||||
@mixin ds-body-xs-regular() {
|
||||
font-size: var(--ds-font-size-300);
|
||||
font-weight: var(--ds-font-weight-regular);
|
||||
line-height: var(--ds-font-line-height-500);
|
||||
}
|
||||
|
||||
@mixin ds-body-xs-semibold() {
|
||||
font-size: var(--ds-font-size-300);
|
||||
font-weight: var(--ds-font-weight-semibold);
|
||||
line-height: var(--ds-font-line-height-500);
|
||||
}
|
||||
|
||||
@mixin ds-body-sm-regular() {
|
||||
font-size: var(--ds-font-size-350);
|
||||
font-weight: var(--ds-font-weight-regular);
|
||||
line-height: var(--ds-font-line-height-500);
|
||||
}
|
||||
|
||||
@mixin ds-body-sm-semibold() {
|
||||
font-size: var(--ds-font-size-350);
|
||||
font-weight: var(--ds-font-weight-semibold);
|
||||
line-height: var(--ds-font-line-height-500);
|
||||
}
|
||||
|
||||
@mixin ds-body-md-regular() {
|
||||
font-size: var(--ds-font-size-400);
|
||||
font-weight: var(--ds-font-weight-regular);
|
||||
line-height: var(--ds-font-line-height-600);
|
||||
}
|
||||
|
||||
@mixin ds-body-md-semibold() {
|
||||
font-size: var(--ds-font-size-400);
|
||||
font-weight: var(--ds-font-weight-semibold);
|
||||
line-height: var(--ds-font-line-height-600);
|
||||
}
|
||||
|
||||
@mixin ds-body-lg-regular() {
|
||||
font-size: var(--ds-font-size-450);
|
||||
font-weight: var(--ds-font-weight-regular);
|
||||
line-height: var(--ds-font-line-height-700);
|
||||
}
|
||||
|
||||
@mixin ds-body-lg-semibold() {
|
||||
font-size: var(--ds-font-size-450);
|
||||
font-weight: var(--ds-font-weight-semibold);
|
||||
line-height: var(--ds-font-line-height-700);
|
||||
}
|
||||
|
||||
@mixin ds-heading-xs-regular() {
|
||||
font-size: var(--ds-font-size-450);
|
||||
font-weight: var(--ds-font-weight-regular);
|
||||
line-height: var(--ds-font-line-height-600);
|
||||
}
|
||||
|
||||
@mixin ds-heading-xs-semibold() {
|
||||
font-size: var(--ds-font-size-450);
|
||||
font-weight: var(--ds-font-weight-semibold);
|
||||
line-height: var(--ds-font-line-height-600);
|
||||
}
|
||||
|
||||
@mixin ds-heading-sm-regular() {
|
||||
font-size: var(--ds-font-size-500);
|
||||
font-weight: var(--ds-font-weight-regular);
|
||||
line-height: var(--ds-font-line-height-700);
|
||||
}
|
||||
|
||||
@mixin ds-heading-sm-semibold() {
|
||||
font-size: var(--ds-font-size-500);
|
||||
font-weight: var(--ds-font-weight-semibold);
|
||||
line-height: var(--ds-font-line-height-700);
|
||||
}
|
||||
|
||||
@mixin ds-heading-md-regular() {
|
||||
font-size: var(--ds-font-size-600);
|
||||
font-weight: var(--ds-font-weight-regular);
|
||||
line-height: var(--ds-font-line-height-800);
|
||||
}
|
||||
|
||||
@mixin ds-heading-md-semibold() {
|
||||
font-size: var(--ds-font-size-600);
|
||||
font-weight: var(--ds-font-weight-semibold);
|
||||
line-height: var(--ds-font-line-height-800);
|
||||
}
|
||||
|
||||
@mixin ds-heading-lg-regular() {
|
||||
font-size: var(--ds-font-size-800);
|
||||
font-weight: var(--ds-font-weight-regular);
|
||||
line-height: var(--ds-font-line-height-1000);
|
||||
}
|
||||
|
||||
@mixin ds-heading-lg-semibold() {
|
||||
font-size: var(--ds-font-size-800);
|
||||
font-weight: var(--ds-font-weight-semibold);
|
||||
line-height: var(--ds-font-line-height-1000);
|
||||
}
|
||||
|
||||
@mixin ds-heading-xl-regular() {
|
||||
font-size: var(--ds-font-size-1000);
|
||||
font-weight: var(--ds-font-weight-regular);
|
||||
line-height: var(--ds-font-line-height-1200);
|
||||
}
|
||||
|
||||
@mixin ds-heading-xl-semibold() {
|
||||
font-size: var(--ds-font-size-1000);
|
||||
font-weight: var(--ds-font-weight-semibold);
|
||||
line-height: var(--ds-font-line-height-1200);
|
||||
}
|
||||
31
services/web/frontend/stylesheets/ds/spacing.scss
Normal file
31
services/web/frontend/stylesheets/ds/spacing.scss
Normal file
@@ -0,0 +1,31 @@
|
||||
:root {
|
||||
--ds-base-unit: 4px;
|
||||
--ds-spacing-50: 2px;
|
||||
--ds-spacing-100: 4px;
|
||||
--ds-spacing-150: 6px;
|
||||
--ds-spacing-200: 8px;
|
||||
--ds-spacing-250: 10px;
|
||||
--ds-spacing-300: 12px;
|
||||
--ds-spacing-350: 14px;
|
||||
--ds-spacing-400: 16px;
|
||||
--ds-spacing-500: 20px;
|
||||
--ds-spacing-600: 24px;
|
||||
--ds-spacing-700: 28px;
|
||||
--ds-spacing-800: 32px;
|
||||
--ds-spacing-900: 36px;
|
||||
--ds-spacing-1000: 40px;
|
||||
--ds-spacing-1100: 44px;
|
||||
--ds-spacing-1200: 48px;
|
||||
--ds-spacing-1300: 52px;
|
||||
--ds-spacing-1400: 56px;
|
||||
--ds-spacing-1500: 60px;
|
||||
--ds-spacing-1600: 64px;
|
||||
--ds-spacing-1700: 68px;
|
||||
--ds-spacing-1800: 72px;
|
||||
--ds-spacing-1900: 76px;
|
||||
--ds-spacing-2000: 80px;
|
||||
--ds-spacing-2100: 84px;
|
||||
--ds-spacing-2200: 88px;
|
||||
--ds-spacing-2300: 92px;
|
||||
--ds-spacing-2400: 96px;
|
||||
}
|
||||
30
services/web/frontend/stylesheets/ds/theme.scss
Normal file
30
services/web/frontend/stylesheets/ds/theme.scss
Normal file
@@ -0,0 +1,30 @@
|
||||
:root {
|
||||
// Default to the light theme
|
||||
--ds-color-bg-default: var(--ds-color-white);
|
||||
--ds-color-text-primary: var(--ds-color-neutral-900);
|
||||
--ds-color-text-secondary: var(--ds-color-neutral-800);
|
||||
--ds-color-text-disabled: var(--ds-color-neutral-500);
|
||||
--ds-color-text-danger-default: var(--ds-color-red-700);
|
||||
--ds-color-text-danger-hover: var(--ds-color-red-800);
|
||||
--ds-color-text-warning-default: var(--ds-color-yellow-900);
|
||||
--ds-color-text-warning-hover: var(--ds-color-yellow-950);
|
||||
--ds-color-text-info-default: var(--ds-color-blue-700);
|
||||
--ds-color-text-info-hover: var(--ds-color-blue-800);
|
||||
--ds-color-text-success-default: var(--ds-color-green-700);
|
||||
--ds-color-text-success-hover: var(--ds-color-green-800);
|
||||
|
||||
.ds-theme-dark {
|
||||
--ds-color-bg-default: var(--ds-color-neutral-950);
|
||||
--ds-color-text-primary: var(--ds-color-white);
|
||||
--ds-color-text-secondary: var(--ds-color-neutral-50);
|
||||
--ds-color-text-disabled: var(--ds-color-neutral-500);
|
||||
--ds-color-text-danger-default: var(--ds-color-red-700);
|
||||
--ds-color-text-danger-hover: var(--ds-color-red-800);
|
||||
--ds-color-text-warning-default: var(--ds-color-yellow-900);
|
||||
--ds-color-text-warning-hover: var(--ds-color-yellow-950);
|
||||
--ds-color-text-info-default: var(--ds-color-blue-700);
|
||||
--ds-color-text-info-hover: var(--ds-color-blue-800);
|
||||
--ds-color-text-success-default: var(--ds-color-green-700);
|
||||
--ds-color-text-success-hover: var(--ds-color-green-800);
|
||||
}
|
||||
}
|
||||
34
services/web/frontend/stylesheets/ds/typography.scss
Normal file
34
services/web/frontend/stylesheets/ds/typography.scss
Normal file
@@ -0,0 +1,34 @@
|
||||
:root {
|
||||
--ds-font-family-sans: 'Inter';
|
||||
|
||||
// Font weight
|
||||
--ds-font-weight-regular: 400;
|
||||
--ds-font-weight-medium: 500;
|
||||
--ds-font-weight-semibold: 600;
|
||||
--ds-font-weight-bold: 700;
|
||||
|
||||
// Font size
|
||||
--ds-font-size-300: 0.75rem; // 12px
|
||||
--ds-font-size-350: 0.875rem; // 14px
|
||||
--ds-font-size-400: 1rem; // 16px
|
||||
--ds-font-size-450: 1.125rem; // 18px
|
||||
--ds-font-size-500: 1.25rem; // 20px
|
||||
--ds-font-size-600: 1.5rem; // 24px
|
||||
--ds-font-size-700: 1.75rem; // 28px
|
||||
--ds-font-size-800: 2rem; // 32px
|
||||
--ds-font-size-1000: 2.5rem; // 40px
|
||||
--ds-font-size-1400: 3.5rem; // 56px
|
||||
--ds-font-size-1800: 4.5rem; // 72px
|
||||
|
||||
// Line height
|
||||
--ds-font-line-height-400: 1rem; // 16px
|
||||
--ds-font-line-height-500: 1.25rem; // 20px
|
||||
--ds-font-line-height-600: 1.5rem; // 24px
|
||||
--ds-font-line-height-700: 1.75rem; // 28px
|
||||
--ds-font-line-height-800: 2rem; // 32px
|
||||
--ds-font-line-height-1000: 2.5rem; // 40px
|
||||
--ds-font-line-height-1200: 3rem; // 48px
|
||||
--ds-font-line-height-1600: 4rem; // 64px
|
||||
--ds-font-line-height-1800: 4.5rem; // 72px
|
||||
--ds-font-line-height-900: 2.25rem; // 36px
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
import { expect } from 'chai'
|
||||
import { mockScope } from './scope'
|
||||
import { EditorProviders } from '../../helpers/editor-providers'
|
||||
import { renderHook } from '@testing-library/react'
|
||||
import { useNewEditorVariant } from '@/features/ide-redesign/utils/new-editor-utils'
|
||||
|
||||
describe('new-editor-utils', function () {
|
||||
describe('useNewEditorVariant', function () {
|
||||
const newEditorVariants = [
|
||||
{ splitTestVariant: 'default', uiVariant: 'default' },
|
||||
{
|
||||
splitTestVariant: 'new-editor',
|
||||
uiVariant: 'new-editor-new-logs-old-position',
|
||||
},
|
||||
{
|
||||
splitTestVariant: 'new-editor-old-logs',
|
||||
uiVariant: 'new-editor-new-logs-old-position',
|
||||
},
|
||||
{
|
||||
splitTestVariant: 'new-editor-new-logs-old-position',
|
||||
uiVariant: 'new-editor-new-logs-old-position',
|
||||
},
|
||||
]
|
||||
for (const variant of newEditorVariants) {
|
||||
it(`forwards ?editor-redesign-new-users=${variant}`, function () {
|
||||
window.metaAttributesCache.set('ol-splitTestVariants', {
|
||||
'editor-redesign-new-users': variant.splitTestVariant,
|
||||
})
|
||||
|
||||
const scope = mockScope()
|
||||
|
||||
const { result } = renderHook(() => useNewEditorVariant(), {
|
||||
wrapper: ({ children }) => (
|
||||
<EditorProviders
|
||||
scope={scope}
|
||||
userSettings={{ enableNewEditor: true }}
|
||||
>
|
||||
{children}
|
||||
</EditorProviders>
|
||||
),
|
||||
})
|
||||
expect(result.current).to.equal(variant.uiVariant)
|
||||
})
|
||||
}
|
||||
for (const variant of newEditorVariants) {
|
||||
it(`ignores ?editor-redesign-new-users=${variant} when disabled by user`, function () {
|
||||
window.metaAttributesCache.set('ol-splitTestVariants', {
|
||||
'editor-redesign-new-users': variant.splitTestVariant,
|
||||
})
|
||||
|
||||
const scope = mockScope()
|
||||
|
||||
const { result } = renderHook(() => useNewEditorVariant(), {
|
||||
wrapper: ({ children }) => (
|
||||
<EditorProviders
|
||||
scope={scope}
|
||||
userSettings={{ enableNewEditor: false }}
|
||||
>
|
||||
{children}
|
||||
</EditorProviders>
|
||||
),
|
||||
})
|
||||
expect(result.current).to.equal('default')
|
||||
})
|
||||
}
|
||||
it(`handles ?editor-redesign=enabled`, function () {
|
||||
window.metaAttributesCache.set('ol-splitTestVariants', {
|
||||
'editor-redesign': 'enabled',
|
||||
})
|
||||
|
||||
const scope = mockScope()
|
||||
|
||||
const { result } = renderHook(() => useNewEditorVariant(), {
|
||||
wrapper: ({ children }) => (
|
||||
<EditorProviders
|
||||
scope={scope}
|
||||
userSettings={{ enableNewEditor: true }}
|
||||
>
|
||||
{children}
|
||||
</EditorProviders>
|
||||
),
|
||||
})
|
||||
expect(result.current).to.equal('new-editor-new-logs-old-position')
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -499,8 +499,9 @@ describe('TeamInvitesHandler', function () {
|
||||
{ id: ctx.user.id, ip: ctx.ipAddress }
|
||||
)
|
||||
sinon.assert.calledWith(
|
||||
ctx.RecurlyClient.promises.terminateSubscriptionByUuid,
|
||||
ctx.user_subscription.recurlySubscription_id
|
||||
ctx.Modules.promises.hooks.fire,
|
||||
'terminateSubscription',
|
||||
ctx.user_subscription
|
||||
)
|
||||
sinon.assert.calledWith(
|
||||
ctx.Modules.promises.hooks.fire,
|
||||
|
||||
Reference in New Issue
Block a user