Compare commits

..

1 Commits

Author SHA1 Message Date
cupcakearmy 7e70c81d81 cleanup 2026-05-31 21:39:37 +02:00
30 changed files with 2257 additions and 2778 deletions
+9 -9
View File
@@ -10,10 +10,10 @@ jobs:
cli: cli:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- uses: pnpm/action-setup@v6 - uses: pnpm/action-setup@v2
- uses: actions/setup-node@v4 - uses: actions/setup-node@v3
with: with:
cache: 'pnpm' cache: 'pnpm'
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
@@ -31,14 +31,14 @@ jobs:
docker: docker:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
- uses: docker/setup-qemu-action@v4 - uses: docker/setup-qemu-action@v2
- uses: docker/setup-buildx-action@v4 - uses: docker/setup-buildx-action@v2
with: with:
install: true install: true
- name: Docker Labels - name: Docker Labels
id: meta id: meta
uses: docker/metadata-action@v6 uses: docker/metadata-action@v4
with: with:
images: cupcakearmy/cryptgeon images: cupcakearmy/cryptgeon
tags: | tags: |
@@ -46,12 +46,12 @@ jobs:
type=semver,pattern={{major}}.{{minor}} type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}} type=semver,pattern={{major}}
- name: Login to DockerHub - name: Login to DockerHub
uses: docker/login-action@v4 uses: docker/login-action@v2
with: with:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push - name: Build and push
uses: docker/build-push-action@v7 uses: docker/build-push-action@v4
with: with:
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
push: true push: true
+3 -3
View File
@@ -13,15 +13,15 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
# Node # Node
- uses: pnpm/action-setup@v6 - uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
cache: 'pnpm' cache: 'pnpm'
node-version-file: '.nvmrc' node-version-file: '.nvmrc'
# Docker # Docker
- uses: docker/setup-qemu-action@v4 - uses: docker/setup-qemu-action@v3
- uses: docker/setup-buildx-action@v4 - uses: docker/setup-buildx-action@v3
with: with:
install: true install: true
+1 -1
View File
@@ -1 +1 @@
v24 v22.14.0
-47
View File
@@ -1,47 +0,0 @@
# Contributing
## Requirements
- [mise](https://mise.jdx.dev) — manages pnpm, rust, node (see `mise.toml`)
- docker or [colima](https://github.com/abiosoft/colima) (for redis)
## Setup
```bash
mise install
pnpm install
```
## Development
```bash
pnpm run dev
```
Make sure docker/colima is running. This starts redis, the rust backend, the web client, and the CLI. The app is at [localhost:3000](http://localhost:3000).
## Tests
End-to-end tests with Playwright.
```sh
pnpm run test:prepare
pnpm run test:local
```
## Release
1. Update version across packages:
```sh
./version.mjs <semver>
```
2. Create and push the tag:
```sh
git tag v<semver>
git push --tags
```
The CI workflow publishes the CLI to npm and the Docker image to Docker Hub automatically.
+3 -3
View File
@@ -1,5 +1,5 @@
# FRONTEND # FRONTEND
FROM node:24-alpine AS client FROM node:22-alpine as client
ENV PNPM_HOME="/pnpm" ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH" ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable RUN corepack enable
@@ -11,7 +11,7 @@ RUN pnpm run build
# BACKEND # BACKEND
FROM rust:1.95-alpine AS backend FROM rust:1.85-alpine as backend
WORKDIR /tmp WORKDIR /tmp
RUN apk add --no-cache libc-dev openssl-dev alpine-sdk RUN apk add --no-cache libc-dev openssl-dev alpine-sdk
COPY ./packages/backend ./ COPY ./packages/backend ./
@@ -19,7 +19,7 @@ RUN RUSTFLAGS="-Ctarget-feature=-crt-static" cargo build --release
# RUNNER # RUNNER
FROM alpine:3 FROM alpine:3.19
WORKDIR /app WORKDIR /app
RUN apk add --no-cache curl libgcc RUN apk add --no-cache curl libgcc
COPY --from=backend /tmp/target/release/cryptgeon . COPY --from=backend /tmp/target/release/cryptgeon .
+50 -6
View File
@@ -105,12 +105,12 @@ version: '3.8'
services: services:
redis: redis:
image: redis:7-alpine image: valkey/valkey:7-alpine
# This is required to stay in RAM only. # This is required to stay in RAM only.
command: redis-server --save "" --appendonly no command: valkey-server --save "" --appendonly no
# Set a size limit. See link below on how to customise. # Set a size limit. See link below on how to customise.
# https://redis.io/docs/latest/operate/rs/databases/memory-performance/eviction-policy/ # https://valkey.io/topics/lru-cache/
# --maxmemory 1gb --maxmemory-policy allkeys-lrulpine # --maxmemory 1gb --maxmemory-policy allkeys-lru
# This prevents the creation of an anonymous volume. # This prevents the creation of an anonymous volume.
tmpfs: tmpfs:
- /data - /data
@@ -162,9 +162,53 @@ There is a [guide](https://mariushosting.com/how-to-install-cryptgeon-on-your-sy
- Italian by [@nicfab](https://notes.nicfab.eu/it/posts/cryptgeon/) - Italian by [@nicfab](https://notes.nicfab.eu/it/posts/cryptgeon/)
- English by [@nicfab](https://notes.nicfab.eu/en/posts/cryptgeon/) - English by [@nicfab](https://notes.nicfab.eu/en/posts/cryptgeon/)
## Contributing ## Development
See [CONTRIBUTING.md](./CONTRIBUTING.md). **Requirements**
- `pnpm`: `>=9`
- `node`: `>=22`
- `rust`: edition `2021`
**Install**
```bash
pnpm install
# Also you need cargo watch if you don't already have it installed.
# https://lib.rs/crates/cargo-watch
cargo install cargo-watch
```
**Run**
Make sure you have docker running.
```bash
pnpm run dev
```
Running `pnpm run dev` in the root folder will start the following things:
- valkey docker container
- rust backend
- client
- cli
You can see the app under [localhost:3000](http://localhost:3000).
> There is a Postman collection with some example requests [available in the repo](./Cryptgeon.postman_collection.json)
### Tests
Tests are end to end tests written with Playwright.
```sh
pnpm run test:prepare
# Use the test or test:local script. The local version only runs in one browser for quicker development.
pnpm run test:local
```
## Security ## Security
+56 -12
View File
@@ -43,7 +43,7 @@ Puedes revisar la documentación sobre el CLI en este [readme](./packages/cli/RE
- enviar texto o archivos - enviar texto o archivos
- el servidor no puede desencriptar el contenido debido a que la encriptación se hace del lado del cliente - el servidor no puede desencriptar el contenido debido a que la encriptación se hace del lado del cliente
- restricción de vistas o de tiempo - restriccion de vistas o de tiempo
- en memoria, sin persistencia - en memoria, sin persistencia
- compatibilidad obligatoria con el modo oscuro - compatibilidad obligatoria con el modo oscuro
@@ -66,7 +66,7 @@ se usa para guardar y recuperar la nota. Después la nota es encriptada con la <
| `MAX_VIEWS` | `100` | Número máximo de vistas. | | `MAX_VIEWS` | `100` | Número máximo de vistas. |
| `MAX_EXPIRATION` | `360` | Tiempo máximo de expiración en minutos. | | `MAX_EXPIRATION` | `360` | Tiempo máximo de expiración en minutos. |
| `ALLOW_ADVANCED` | `true` | Permitir configuración personalizada. Si se establece en `false` todas las notas serán de una sola vista. | | `ALLOW_ADVANCED` | `true` | Permitir configuración personalizada. Si se establece en `false` todas las notas serán de una sola vista. |
| `ID_LENGTH` | `32` | Establece el tamaño en bytes de la `id` de la nota. Por defecto es de `32` bytes. Esto es útil para reducir el tamaño del link. _Esta configuración no afecta el nivel de encriptación_. | | `ID_LENGTH` | `32` | Establece el tamaño en bytes de la `id` de la nota. Por defecto es de `32` bytes. Esto es util para reducir el tamaño del link. _Esta configuración no afecta el nivel de encriptación_. |
| `VERBOSITY` | `warn` | Nivel de verbosidad del backend. [Posibles valores](https://docs.rs/env_logger/latest/env_logger/#enabling-logging): `error`, `warn`, `info`, `debug`, `trace` | | `VERBOSITY` | `warn` | Nivel de verbosidad del backend. [Posibles valores](https://docs.rs/env_logger/latest/env_logger/#enabling-logging): `error`, `warn`, `info`, `debug`, `trace` |
| `THEME_IMAGE` | `""` | Imagen personalizada para reemplazar el logo. Debe ser accesible públicamente. | | `THEME_IMAGE` | `""` | Imagen personalizada para reemplazar el logo. Debe ser accesible públicamente. |
| `THEME_TEXT` | `""` | Texto personalizado para reemplazar la descripción bajo el logo. | | `THEME_TEXT` | `""` | Texto personalizado para reemplazar la descripción bajo el logo. |
@@ -75,27 +75,27 @@ se usa para guardar y recuperar la nota. Después la nota es encriptada con la <
## Despliegue ## Despliegue
> ️ Se requiere `https` de lo contrario el navegador no soportará las funciones de encriptación. > ️ Se requiere `https` de lo contrario el navegador no soportará las funciones de encriptacón.
> ️ Hay un endpoint para verificar el estado, lo encontramos en `/api/health/`. Regresa un código 200 o 503. > ️ Hay un endpoint para verificar el estado, lo encontramos en `/api/health/`. Regresa un código 200 o 503.
### Docker ### Docker
Docker es la manera más fácil. Aquí encontramos [la imagen oficial](https://hub.docker.com/r/cupcakearmy/cryptgeon). Docker es la manera más fácil. Aquí encontramos [la imágen oficial](https://hub.docker.com/r/cupcakearmy/cryptgeon).
```yaml ```yaml
# docker-compose.yml # docker-compose.yml
version: "3.8" version: '3.8'
services: services:
redis: redis:
image: redis:7-alpine image: valkey/valkey:7-alpine
# This is required to stay in RAM only. # This is required to stay in RAM only.
command: redis-server --save "" --appendonly no command: valkey-server --save "" --appendonly no
# Set a size limit. See link below on how to customise. # Set a size limit. See link below on how to customise.
# https://redis.io/docs/latest/operate/rs/databases/memory-performance/eviction-policy/ # https://valkey.io/topics/lru-cache/
# --maxmemory 1gb --maxmemory-policy allkeys-lrulpine # --maxmemory 1gb --maxmemory-policy allkeys-lru
# This prevents the creation of an anonymous volume. # This prevents the creation of an anonymous volume.
tmpfs: tmpfs:
- /data - /data
@@ -141,13 +141,57 @@ Hay una [guía](https://mariushosting.com/how-to-install-cryptgeon-on-your-synol
- En inglés, por [DB Tech](https://www.youtube.com/watch?v=S0jx7wpOfNM) [Previous Video](https://www.youtube.com/watch?v=JhpIatD06vE) - En inglés, por [DB Tech](https://www.youtube.com/watch?v=S0jx7wpOfNM) [Previous Video](https://www.youtube.com/watch?v=JhpIatD06vE)
- En alemán, por [ApfelCast](https://www.youtube.com/watch?v=84ZMbE9AkHg) - En alemán, por [ApfelCast](https://www.youtube.com/watch?v=84ZMbE9AkHg)
## Contribuir ## Desarrollo
Ver [CONTRIBUTING.md](./CONTRIBUTING.md). **Requisitos**
- `pnpm`: `>=6`
- `node`: `>=18`
- `rust`: edition `2021`
**Instalación**
```bash
pnpm install
# También necesitas cargo-watch, si no lo tienes instalado.
# https://lib.rs/crates/cargo-watch
cargo install cargo-watch
```
**Ejecutar**
Asegurate de que docker se esté ejecutando.
```bash
pnpm run dev
```
Ejecutando `pnpm run dev` en la carpeta raíz iniciará lo siguiente:
- redis docker container
- rust backend
- client
- cli
Puedes ver la app en [localhost:3000](http://localhost:3000).
> Existe una colección de Postman con algunas peticiones de ejemplo [disponible en el repo](./Cryptgeon.postman_collection.json)
### Tests
Los tests son end-to-end tests escritos con Playwright.
```sh
pnpm run test:prepare
# Usa el script test o test:local. La versión local solo corre en el navegador para acelerar el desarrollo.
pnpm run test:local
```
## Seguridad ## Seguridad
Por favor dirígete a la sección de seguridad [aquí](./SECURITY.md). Por favor dirigite a la sección de seguridad [aquí](./SECURITY.md).
--- ---
+58 -13
View File
@@ -48,7 +48,7 @@ _加密鸽_ 是一个受 [_PrivNote_](https://privnote.com)项目启发的安全
## 环境变量 ## 环境变量
| 变量名称 | 默认值 | 描述 | | 变量名称 | 默认值 | 描述 |
| ---------------- | ---------------- | --------------------------------------------------------------------------------- | | ----------------- | ---------------- | --------------------------------------------------------------------------------- |
| `REDIS` | `redis://redis/` | Redis 连接 URL。 | | `REDIS` | `redis://redis/` | Redis 连接 URL。 |
| `SIZE_LIMIT` | `1 KiB` | 最大请求体(body)限制。有关支持的数值请查看 [字节单位](https://docs.rs/byte-unit/) | | `SIZE_LIMIT` | `1 KiB` | 最大请求体(body)限制。有关支持的数值请查看 [字节单位](https://docs.rs/byte-unit/) |
| `MAX_VIEWS` | `100` | 密信最多查看次数限制 | | `MAX_VIEWS` | `100` | 密信最多查看次数限制 |
@@ -69,16 +69,16 @@ Docker 是最简单的部署方式。这里是[官方镜像的地址](https://hu
```yaml ```yaml
# docker-compose.yml # docker-compose.yml
version: "3.8" version: '3.8'
services: services:
redis: redis:
image: redis:7-alpine image: valkey/valkey:7-alpine
# This is required to stay in RAM only. # This is required to stay in RAM only.
command: redis-server --save "" --appendonly no command: valkey-server --save "" --appendonly no
# Set a size limit. See link below on how to customise. # Set a size limit. See link below on how to customise.
# https://redis.io/docs/latest/operate/rs/databases/memory-performance/eviction-policy/ # https://valkey.io/topics/lru-cache/
# --maxmemory 1gb --maxmemory-policy allkeys-lrulpine # --maxmemory 1gb --maxmemory-policy allkeys-lru
# This prevents the creation of an anonymous volume. # This prevents the creation of an anonymous volume.
tmpfs: tmpfs:
- /data - /data
@@ -107,7 +107,7 @@ services:
- 域名 `example.org` - 域名 `example.org`
```yaml ```yaml
version: "3.8" version: '3.8'
networks: networks:
proxy: proxy:
@@ -115,12 +115,12 @@ networks:
services: services:
redis: redis:
image: redis:7-alpine image: valkey/valkey:7-alpine
# This is required to stay in RAM only. # This is required to stay in RAM only.
command: redis-server --save "" --appendonly no command: valkey-server --save "" --appendonly no
# Set a size limit. See link below on how to customise. # Set a size limit. See link below on how to customise.
# https://redis.io/docs/latest/operate/rs/databases/memory-performance/eviction-policy/ # https://valkey.io/topics/lru-cache/
# --maxmemory 1gb --maxmemory-policy allkeys-lrulpine # --maxmemory 1gb --maxmemory-policy allkeys-lru
# This prevents the creation of an anonymous volume. # This prevents the creation of an anonymous volume.
tmpfs: tmpfs:
- /data - /data
@@ -140,9 +140,54 @@ services:
- traefik.http.routers.cryptgeon.tls.certresolver=le - traefik.http.routers.cryptgeon.tls.certresolver=le
``` ```
## 贡献 ## 开发
参见 [CONTRIBUTING.md](./CONTRIBUTING.md)。 **环境要求**
- `pnpm`: `>=6`
- `node`: `>=14`
- `rust`: edition `2021`
**安装**
```bash
pnpm install
pnpm --prefix frontend install
# 你还需要安装CargoWatch.
# https://lib.rs/crates/cargo-watch
cargo install cargo-watch
```
**运行**
确保你的 Docker 正在运行
```bash
pnpm run dev
```
在根目录执行 `pnpm run dev` 会开启下列服务:
- 一个 redis docker 容器
- 无热重载的 rust 后端
- 可热重载的客户端
你可以通过 3000 端口进入该应用,即 [localhost:3000](http://localhost:3000).
## 测试
这些测试是用 Playwright 实现的一些端到端测试用例。
```sh
pnpm run test:prepare
docker compose up redis -d
pnpm run test:server
# 在另一个终端中:
# 使用test或者test:local script。为了更快的开发,本地版本只会在一个浏览器中运行。
pnpm run test:local
```
###### Attributions ###### Attributions
+3 -3
View File
@@ -7,8 +7,8 @@ services:
# This is required to stay in RAM only. # This is required to stay in RAM only.
command: valkey-server --save "" --appendonly no command: valkey-server --save "" --appendonly no
# Set a size limit. See link below on how to customise. # Set a size limit. See link below on how to customise.
# https://valkey.io/docs/latest/operate/rs/databases/memory-performance/eviction-policy/ # https://valkey.io/topics/lru-cache/
# --maxmemory 1gb --maxmemory-policy allkeys-lrulpine # --maxmemory 1gb --maxmemory-policy allkeys-lru
# This prevents the creation of an anonymous volume. # This prevents the creation of an anonymous volume.
tmpfs: tmpfs:
- /data - /data
@@ -25,7 +25,7 @@ services:
- 3000:8000 - 3000:8000
healthcheck: healthcheck:
test: ['CMD', 'curl', '--fail', 'http://127.0.0.1:8000/api/live/'] test: ["CMD", "curl", "--fail", "http://127.0.0.1:8000/api/live/"]
interval: 1m interval: 1m
timeout: 3s timeout: 3s
retries: 2 retries: 2
+2 -2
View File
@@ -4,8 +4,8 @@ services:
# This is required to stay in RAM only. # This is required to stay in RAM only.
command: valkey-server --save "" --appendonly no command: valkey-server --save "" --appendonly no
# Set a size limit. See link below on how to customise. # Set a size limit. See link below on how to customise.
# https://valkey.io/docs/latest/operate/rs/databases/memory-performance/eviction-policy/ # https://valkey.io/topics/lru-cache/
# --maxmemory 1gb --maxmemory-policy allkeys-lrulpine # --maxmemory 1gb --maxmemory-policy allkeys-lru
# This prevents the creation of an anonymous volume. # This prevents the creation of an anonymous volume.
tmpfs: tmpfs:
- /data - /data
-8
View File
@@ -1,8 +0,0 @@
[tools]
pnpm = "11.5.0"
rust = "1.95"
watchexec = "latest"
# Node loaded below from .nvmrc
[settings]
idiomatic_version_file_enable_tools = ["node"]
+4 -5
View File
@@ -8,15 +8,14 @@
"test": "playwright test --project=chrome --project=firefox --project=safari", "test": "playwright test --project=chrome --project=firefox --project=safari",
"test:local": "playwright test --project=chrome", "test:local": "playwright test --project=chrome",
"test:server": "run-s docker:up", "test:server": "run-s docker:up",
"test:dl-browsers": "playwright install", "test:prepare": "run-p build docker:build",
"test:prepare": "run-p test:dl-browsers build docker:build",
"build": "pnpm run --recursive --filter=!@cryptgeon/backend build" "build": "pnpm run --recursive --filter=!@cryptgeon/backend build"
}, },
"devDependencies": { "devDependencies": {
"@playwright/test": "^1.60.0", "@playwright/test": "^1.46.1",
"@types/node": "^24.12.4", "@types/node": "^22.5.0",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"shelljs": "^0.8.5" "shelljs": "^0.8.5"
}, },
"packageManager": "pnpm@11.5.0" "packageManager": "pnpm@10.3.0"
} }
+421 -648
View File
File diff suppressed because it is too large Load Diff
+8 -8
View File
@@ -2,8 +2,8 @@
name = "cryptgeon" name = "cryptgeon"
version = "2.9.1" version = "2.9.1"
authors = ["cupcakearmy <hi@nicco.io>"] authors = ["cupcakearmy <hi@nicco.io>"]
edition = "2024" edition = "2021"
rust-version = "1.95" rust-version = "1.85"
[[bin]] [[bin]]
name = "cryptgeon" name = "cryptgeon"
@@ -11,12 +11,12 @@ path = "src/main.rs"
[dependencies] [dependencies]
# Core # Core
axum = "0.8" axum = "0.7.5"
serde = { version = "1", features = ["derive"] } serde = { version = "1.0.208", features = ["derive"] }
tokio = { version = "1", features = ["full"] } tokio = { version = "1.39.3", features = ["full"] }
tower = "0.5" tower = "0.5.0"
tower-http = { version = "0.6", features = ["full"] } tower-http = { version = "0.5.2", features = ["full"] }
redis = { version = "1", features = ["tls-native-tls"] } redis = { version = "0.25.2", features = ["tls-native-tls"] }
# Utility # Utility
serde_json = "1" serde_json = "1"
+1 -1
View File
@@ -2,7 +2,7 @@
"private": true, "private": true,
"name": "@cryptgeon/backend", "name": "@cryptgeon/backend",
"scripts": { "scripts": {
"dev": "watchexec -r -e rs cargo run", "dev": "cargo watch -x 'run --bin cryptgeon'",
"build": "cargo build --release", "build": "cargo build --release",
"test:server": "SIZE_LIMIT=10MiB LISTEN_ADDR=0.0.0.0:3000 cargo run", "test:server": "SIZE_LIMIT=10MiB LISTEN_ADDR=0.0.0.0:3000 cargo run",
"test:prepare": "cargo build" "test:prepare": "cargo build"
+5 -5
View File
@@ -1,9 +1,9 @@
use std::{collections::HashMap, sync::Arc}; use std::{collections::HashMap, sync::Arc};
use axum::{ use axum::{
Router, ServiceExt,
extract::{DefaultBodyLimit, Request}, extract::{DefaultBodyLimit, Request},
routing::{delete, get, post}, routing::{delete, get, post},
Router, ServiceExt,
}; };
use dotenv::dotenv; use dotenv::dotenv;
use lock::SharedState; use lock::SharedState;
@@ -41,14 +41,14 @@ async fn main() {
let notes_routes = Router::new() let notes_routes = Router::new()
.route("/", post(note::create)) .route("/", post(note::create))
.route("/{id}", delete(note::delete)) .route("/:id", delete(note::delete))
.route("/{id}", get(note::preview)); .route("/:id", get(note::preview));
let health_routes = Router::new().route("/live", get(health::report_health)); let health_routes = Router::new().route("/live", get(health::report_health));
let status_routes = Router::new().route("/status", get(status::get_status)); let status_routes = Router::new().route("/status", get(status::get_status));
let api_routes = Router::new() let api_routes = Router::new()
.nest("/notes", notes_routes) .nest("/notes", notes_routes)
.merge(health_routes) .nest("/", health_routes)
.merge(status_routes); .nest("/", status_routes);
let index = format!("{}{}", config::FRONTEND_PATH.to_string(), "/index.html"); let index = format!("{}{}", config::FRONTEND_PATH.to_string(), "/index.html");
let serve_dir = let serve_dir =
+6 -6
View File
@@ -30,16 +30,16 @@
}, },
"devDependencies": { "devDependencies": {
"@commander-js/extra-typings": "^12.1.0", "@commander-js/extra-typings": "^12.1.0",
"@types/inquirer": "^9.0.9", "@types/inquirer": "^9.0.7",
"@types/mime": "^4.0.0", "@types/mime": "^4.0.0",
"@types/node": "^20.19.41", "@types/node": "^20.11.24",
"commander": "^12.1.0", "commander": "^12.1.0",
"inquirer": "^9.3.8", "inquirer": "^9.2.15",
"mime": "^4.1.0", "mime": "^4.0.1",
"occulto": "^2.0.6", "occulto": "^2.0.6",
"pretty-bytes": "^6.1.1", "pretty-bytes": "^6.1.1",
"tsup": "^8.5.1", "tsup": "^8.2.4",
"typescript": "^5.9.3" "typescript": "^5.3.3"
}, },
"engines": { "engines": {
"node": ">=18" "node": ">=18"
+1 -1
View File
@@ -5,7 +5,7 @@
"advanced": "avanzato", "advanced": "avanzato",
"create": "crea", "create": "crea",
"loading": "carica", "loading": "carica",
"mode": "modalità", "mode": "modalita",
"views": "{n, plural, =0 {viste} =1 {1 vista} other {# viste}}", "views": "{n, plural, =0 {viste} =1 {1 vista} other {# viste}}",
"minutes": "{n, plural, =0 {minuti} =1 {1 minuto} other {# minuti}}", "minutes": "{n, plural, =0 {minuti} =1 {1 minuto} other {# minuti}}",
"max": "max", "max": "max",
+2 -2
View File
@@ -17,7 +17,7 @@
"uploading": "アップロード中", "uploading": "アップロード中",
"downloading": "ダウンロード中", "downloading": "ダウンロード中",
"qr_code": "QRコード", "qr_code": "QRコード",
"password": "パスワード" "password": "暗号"
}, },
"home": { "home": {
"intro": "<i>完全に暗号化された</i> 、安全なメモやファイルをワンクリックで簡単に送信できます。メモを作成してリンクを共有するだけです。", "intro": "<i>完全に暗号化された</i> 、安全なメモやファイルをワンクリックで簡単に送信できます。メモを作成してリンクを共有するだけです。",
@@ -46,7 +46,7 @@
}, },
"explanation": "カウンターが上限に達した場合、ノートの表示と削除を行うには、以下をクリックします。", "explanation": "カウンターが上限に達した場合、ノートの表示と削除を行うには、以下をクリックします。",
"show_note": "メモを表示", "show_note": "メモを表示",
"warning_will_not_see_again": "このノートを再度表示することは<b>できません</b>", "warning_will_not_see_again": "あなた <b>できません</b> このノートをもう一度見る",
"download_all": "すべてダウンロード", "download_all": "すべてダウンロード",
"links_found": "メモ内にあるリンク:" "links_found": "メモ内にあるリンク:"
}, },
+3 -3
View File
@@ -26,7 +26,7 @@
"new_note_notice": "<b>доступность:</b><br />сохранение заметки не гарантируется, поскольку все хранится в оперативной памяти; если она заполнится, самые старые заметки будут удалены.<br />( вероятно, все будет в порядке, просто будьте осторожны.)", "new_note_notice": "<b>доступность:</b><br />сохранение заметки не гарантируется, поскольку все хранится в оперативной памяти; если она заполнится, самые старые заметки будут удалены.<br />( вероятно, все будет в порядке, просто будьте осторожны.)",
"errors": { "errors": {
"note_to_big": "нельзя создать новую заметку. заметка слишком большая", "note_to_big": "нельзя создать новую заметку. заметка слишком большая",
"note_error": "нельзя создать новую заметку. пожалуйста попробуйте позже.", "note_error": "нельзя создать новую заметку. пожалйста попробуйте позднее.",
"max": "макс: {n}", "max": "макс: {n}",
"empty_content": "пустая заметка." "empty_content": "пустая заметка."
}, },
@@ -41,10 +41,10 @@
"show": { "show": {
"errors": { "errors": {
"not_found": "заметка не найдена или была удалена.", "not_found": "заметка не найдена или была удалена.",
"decryption_failed": "неправильный пароль. не смог расшифровать. возможно ссылка битая. заметка уничтожена.", "decryption_failed": "неправильный пароль. не смог расшифровать. возможно ссылка битая. записка уничтожена.",
"unsupported_type": "неподдерживаемый тип заметки." "unsupported_type": "неподдерживаемый тип заметки."
}, },
"explanation": "щелкните ниже, чтобы показать и удалить заметку, если счетчик достиг предела", "explanation": "щелкните ниже, чтобы показать и удалить примечание, если счетчик достиг предела",
"show_note": "показать заметку", "show_note": "показать заметку",
"warning_will_not_see_again": "вы <b>не сможете</b> больше просмотреть заметку.", "warning_will_not_see_again": "вы <b>не сможете</b> больше просмотреть заметку.",
"download_all": "скачать всё", "download_all": "скачать всё",
+12 -12
View File
@@ -14,24 +14,24 @@
"type": "module", "type": "module",
"devDependencies": { "devDependencies": {
"@lokalise/node-api": "^13.2.1", "@lokalise/node-api": "^13.2.1",
"@sveltejs/adapter-static": "^3.0.10", "@sveltejs/adapter-static": "^3.0.8",
"@sveltejs/kit": "^2.61.1", "@sveltejs/kit": "^2.17.3",
"@sveltejs/vite-plugin-svelte": "^7.1.2", "@sveltejs/vite-plugin-svelte": "^5.0.3",
"@zerodevx/svelte-toast": "^0.9.6", "@zerodevx/svelte-toast": "^0.9.6",
"adm-zip": "^0.5.17", "adm-zip": "^0.5.16",
"dotenv": "^17.4.2", "dotenv": "^16.4.7",
"svelte": "^5.55.9", "svelte": "^5.20.5",
"svelte-check": "^4.4.8", "svelte-check": "^4.1.4",
"svelte-intl-precompile": "^0.12.3", "svelte-intl-precompile": "^0.12.3",
"tslib": "^2.8.1", "tslib": "^2.8.1",
"typescript": "^6.0.3", "typescript": "^5.7.3",
"vite": "^8.0.14" "vite": "^6.2.0"
}, },
"dependencies": { "dependencies": {
"@fontsource/fira-mono": "^5.2.7", "@fontsource/fira-mono": "^5.1.1",
"cryptgeon": "workspace:*", "cryptgeon": "workspace:*",
"occulto": "^2.0.6", "occulto": "^2.0.6",
"pretty-bytes": "^7.1.0", "pretty-bytes": "^6.1.1",
"uqr": "^0.1.3" "qrious": "^4.0.2"
} }
} }
@@ -1,7 +1,9 @@
<script lang="ts"> <script lang="ts">
import { getCSSVariable } from '$lib/utils' // @ts-ignore
import QR from 'qrious'
import { t } from 'svelte-intl-precompile' import { t } from 'svelte-intl-precompile'
import { renderSVG } from 'uqr'
import { getCSSVariable } from '$lib/utils'
interface Props { interface Props {
value: string value: string
@@ -9,36 +11,35 @@
let { value }: Props = $props() let { value }: Props = $props()
let qr: string | null = $state(null) let canvas: HTMLCanvasElement | null = $state(null)
$effect(() => { $effect(() => {
qr = renderSVG(value, { new QR({
ecc: 'Q', value,
blackColor: getCSSVariable('--ui-bg-0'), level: 'Q',
whiteColor: getCSSVariable('--ui-text-0'), size: 800,
background: getCSSVariable('--ui-bg-0'),
foreground: getCSSVariable('--ui-text-0'),
element: canvas,
}) })
}) })
</script> </script>
<small>{$t('common.qr_code')}</small> <small>{$t('common.qr_code')}</small>
<div> <div>
{#if qr} <canvas bind:this={canvas}></canvas>
{@html qr}
{/if}
</div> </div>
<style> <style>
div { div {
padding: 0.25rem; padding: 0.5rem;
width: fit-content; width: fit-content;
border: 2px solid var(--ui-bg-1); border: 2px solid var(--ui-bg-1);
background-color: var(--ui-bg-0); background-color: var(--ui-bg-0);
margin-top: 0.125rem; margin-top: 0.125rem;
overflow: hidden;
aspect-ratio: 1;
} }
div :global(svg) { canvas {
width: 100%; width: 100%;
height: auto; height: auto;
} }
@@ -10,7 +10,7 @@
import { status } from '$lib/stores/status' import { status } from '$lib/stores/status'
import Button from '$lib/ui/Button.svelte' import Button from '$lib/ui/Button.svelte'
import TextInput from '$lib/ui/TextInput.svelte' import TextInput from '$lib/ui/TextInput.svelte'
import QR from './QR.svelte' import Canvas from './Canvas.svelte'
interface Props { interface Props {
result: NoteResult result: NoteResult
@@ -18,11 +18,8 @@
let { result }: Props = $props() let { result }: Props = $props()
let url = $derived.by(() => { let url = $state(`${window.location.origin}/note/${result.id}`)
let url = `${window.location.origin}/note/${result.id}`
if (result.password) url += `#${result.password}` if (result.password) url += `#${result.password}`
return url
})
function reset() { function reset() {
window.location.reload() window.location.reload()
@@ -39,7 +36,7 @@
/> />
<div> <div>
<QR value={url} /> <Canvas value={url} />
</div> </div>
{#if $status?.theme_new_note_notice} {#if $status?.theme_new_note_notice}
@@ -32,7 +32,6 @@
let files: FileDTO[] = $state([]) let files: FileDTO[] = $state([])
async function downloadFile(file: FileDTO) { async function downloadFile(file: FileDTO) {
// @ts-ignore
const f = new File([file.contents], file.name, { const f = new File([file.contents], file.name, {
type: file.type, type: file.type,
}) })
@@ -21,7 +21,6 @@
...rest ...rest
}: HTMLInputAttributes & Props = $props() }: HTMLInputAttributes & Props = $props()
// svelte-ignore state_referenced_locally
const initialType = $state(rest.type) const initialType = $state(rest.type)
const isPassword = initialType === 'password' const isPassword = initialType === 'password'
let hidden = $state(true) let hidden = $state(true)
@@ -16,7 +16,7 @@
let { data }: Props = $props() let { data }: Props = $props()
let id = $derived(data.id) let id = data.id
let password: string | null = $state<string | null>(null) let password: string | null = $state<string | null>(null)
let note: DecryptedNote | null = $state(null) let note: DecryptedNote | null = $state(null)
let exists = $state(false) let exists = $state(false)
+2 -3
View File
@@ -2,7 +2,6 @@
"extends": "./.svelte-kit/tsconfig.json", "extends": "./.svelte-kit/tsconfig.json",
"compilerOptions": { "compilerOptions": {
"strict": true, "strict": true,
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true
"skipLibCheck": true, }
},
} }
+1523 -1884
View File
File diff suppressed because it is too large Load Diff
-5
View File
@@ -1,7 +1,2 @@
packages: packages:
- "packages/**" - "packages/**"
allowBuilds:
esbuild: true
minimumReleaseAge: 10080 # One week