mirror of
https://github.com/cupcakearmy/cryptgeon.git
synced 2025-09-05 17:00:39 +00:00
Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
53c7c9d9e2 | |||
df9c60c29e | |||
f29b6b23f0 | |||
cc88fa6763 | |||
19022e7cb5 | |||
44f43dbc2c | |||
45f6f3af32 | |||
9bd544f0d5 |
12
CHANGELOG.md
12
CHANGELOG.md
@@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [1.5.1] - 2022-05-15
|
||||
|
||||
### Fixed
|
||||
|
||||
- Remove double note content
|
||||
|
||||
## [1.5.0] - 2022-05-14
|
||||
|
||||
### Added
|
||||
|
||||
- Links in notes are not highlighted and can be directly clicked #30.
|
||||
|
||||
## [1.4.1] - 2022-03-05
|
||||
|
||||
### Fixed
|
||||
|
37
README.md
37
README.md
@@ -49,9 +49,12 @@ of the notes even if it tried to.
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Default | Description |
|
||||
| ------------ | ----------------- | --------------------------------------------------------------------------------------- |
|
||||
| ---------------- | ----------------- | --------------------------------------------------------------------------------------- |
|
||||
| `MEMCACHE` | `memcached:11211` | Memcached URL to connect to. |
|
||||
| `SIZE_LIMIT` | `1 KiB` | Max size for body. Accepted values according to [byte-unit](https://docs.rs/byte-unit/) |
|
||||
| `MAX_VIEWS` | `100` | Maximal number of views. |
|
||||
| `MAX_EXPIRATION` | `360` | Maximal expiration in minutes. |
|
||||
| `ALLOW_ADVANCED` | `true` | Allow custom configuration. If set to `false` all notes will be one view only. |
|
||||
|
||||
## Deployment
|
||||
|
||||
@@ -124,11 +127,35 @@ services:
|
||||
|
||||
## Development
|
||||
|
||||
1. Clone
|
||||
2. run `pnpm i` in the root and and client `client/` folders.
|
||||
3. Run `pnpm run dev` to start development.
|
||||
**Requirements**
|
||||
|
||||
Running `npm run dev` in the root folder will start the following things
|
||||
- `pnpm`: `>=6`
|
||||
- `node`: `>=14`
|
||||
- `rust`: edition `2021`
|
||||
|
||||
**Install**
|
||||
|
||||
```bash
|
||||
pnpm install
|
||||
pnpm --prefix frontend 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.
|
||||
|
||||
> If you are on `macOS` you might need to disable AirPlay Receiver as it uses port 5000 (So stupid...)
|
||||
> https://developer.apple.com/forums/thread/682332
|
||||
|
||||
```bash
|
||||
pnpm run dev
|
||||
```
|
||||
|
||||
Running `pnpm run dev` in the root folder will start the following things:
|
||||
|
||||
- a memcache docker container
|
||||
- rust backend with hot reload
|
||||
|
2
backend/Cargo.lock
generated
2
backend/Cargo.lock
generated
@@ -398,7 +398,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cryptgeon"
|
||||
version = "1.4.1"
|
||||
version = "1.5.1"
|
||||
dependencies = [
|
||||
"actix-files",
|
||||
"actix-web",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "cryptgeon"
|
||||
version = "1.4.1"
|
||||
version = "1.5.1"
|
||||
authors = ["cupcakearmy <hi@nicco.io>"]
|
||||
edition = "2021"
|
||||
|
||||
|
161
examples/scratch/README.md
Normal file
161
examples/scratch/README.md
Normal file
@@ -0,0 +1,161 @@
|
||||
# Install from scratch.
|
||||
|
||||
This is a tiny guide to install cryptgeon on (probably) any unix system (and maybe windows?) from scratch using traefik as the proxy, which will manage certificates and handle https for us.
|
||||
|
||||
1. Install Docker & Docker Compose.
|
||||
2. Install Traefik.
|
||||
3. Run the cryptgeon.
|
||||
4. [Optional] install watchtower to keep up to date.
|
||||
|
||||
## Install Docker & DOcker Compose
|
||||
|
||||
- [Docker](https://docs.docker.com/engine/install/)
|
||||
- [Compose](https://docs.docker.com/compose/install/)
|
||||
|
||||
## Install Traefik 2.0
|
||||
|
||||
[Traefik](https://doc.traefik.io/traefik/) is a router & proxy that makes deployment of containers incredibly easy. It will manage all the https certificates, routing, etc.
|
||||
|
||||
```sh
|
||||
/foo/bar/traefik/
|
||||
├── docker-compose.yaml
|
||||
└── traefik.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# docker-compose.yaml
|
||||
|
||||
version: '3.8'
|
||||
services:
|
||||
traefik:
|
||||
image: traefik:2.6
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- '80:80'
|
||||
- '443:443'
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- ./traefik.yaml:/etc/traefik/traefik.yaml:ro
|
||||
- ./data:/data
|
||||
labels:
|
||||
- 'traefik.enable=true'
|
||||
|
||||
# HTTP to HTTPS redirection
|
||||
- 'traefik.http.routers.http_catchall.rule=HostRegexp(`{any:.+}`)'
|
||||
- 'traefik.http.routers.http_catchall.entrypoints=insecure'
|
||||
- 'traefik.http.routers.http_catchall.middlewares=https_redirect'
|
||||
- 'traefik.http.middlewares.https_redirect.redirectscheme.scheme=https'
|
||||
- 'traefik.http.middlewares.https_redirect.redirectscheme.permanent=true'
|
||||
|
||||
networks:
|
||||
default:
|
||||
external: true
|
||||
name: proxy
|
||||
```
|
||||
|
||||
```yaml
|
||||
# traefik.yaml
|
||||
|
||||
api:
|
||||
dashboard: true
|
||||
|
||||
# Define HTTP and HTTPS entrypoint
|
||||
entryPoints:
|
||||
insecure:
|
||||
address: ':80'
|
||||
secure:
|
||||
address: ':443'
|
||||
|
||||
# Dynamic configuration will come from docker labels
|
||||
providers:
|
||||
docker:
|
||||
endpoint: 'unix:///var/run/docker.sock'
|
||||
network: 'proxy'
|
||||
exposedByDefault: false
|
||||
|
||||
# Enable acme with http file challenge
|
||||
certificatesResolvers:
|
||||
le:
|
||||
acme:
|
||||
email: me@example.org
|
||||
storage: /data/acme.json
|
||||
httpChallenge:
|
||||
entryPoint: insecure
|
||||
```
|
||||
|
||||
**Run**
|
||||
|
||||
```sh
|
||||
docker network create proxy
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
## Cryptgeon
|
||||
|
||||
Create another docker-compose.yaml file in another folder. We will assume that the domain is `cryptgeon.example.org`.
|
||||
|
||||
```sh
|
||||
/foo/bar/cryptgeon/
|
||||
└── docker-compose.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
version: '3.8'
|
||||
|
||||
networks:
|
||||
proxy:
|
||||
external: true
|
||||
|
||||
services:
|
||||
memcached:
|
||||
image: memcached:1-alpine
|
||||
restart: unless-stopped
|
||||
entrypoint: memcached -m 256M -I 4M # Limit to 128 MB Ram, customize at free will.
|
||||
|
||||
app:
|
||||
image: cupcakearmy/cryptgeon:latest
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- memcached
|
||||
environment:
|
||||
SIZE_LIMIT: 4 MiB
|
||||
networks:
|
||||
- default
|
||||
- proxy
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.cryptgeon.rule=Host(`cryptgeon.example.org`)
|
||||
- traefik.http.routers.cryptgeon.entrypoints=secure
|
||||
- traefik.http.routers.cryptgeon.tls.certresolver=le
|
||||
```
|
||||
|
||||
**Run**
|
||||
|
||||
```sh
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
## Watchtower
|
||||
|
||||
> A container-based solution for automating Docker container base image updates.
|
||||
|
||||
[Watchtower](https://containrrr.dev/watchtower/) will keep our containers up to date. The interval is set to once a day and also configured to delete old images to prevent cluttering.
|
||||
|
||||
```sh
|
||||
/foo/bar/watchtower/
|
||||
└── docker-compose.yaml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# docker-compose.yaml
|
||||
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
watchtower:
|
||||
image: containrrr/watchtower
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
command: --cleanup --interval 86400
|
||||
```
|
@@ -14,6 +14,7 @@
|
||||
"@sveltejs/adapter-static": "^1.0.0-next.28",
|
||||
"@sveltejs/kit": "1.0.0-next.288",
|
||||
"@types/file-saver": "^2.0.5",
|
||||
"@types/sanitize-html": "^2.6.2",
|
||||
"adm-zip": "^0.5.9",
|
||||
"dotenv": "^16.0.0",
|
||||
"svelte": "^3.46.4",
|
||||
@@ -28,6 +29,7 @@
|
||||
"@fontsource/fira-mono": "^4.5.3",
|
||||
"copy-to-clipboard": "^3.3.1",
|
||||
"file-saver": "^2.0.5",
|
||||
"pretty-bytes": "^5.6.0"
|
||||
"pretty-bytes": "^5.6.0",
|
||||
"sanitize-html": "^2.7.0"
|
||||
}
|
||||
}
|
||||
|
80
frontend/pnpm-lock.yaml
generated
80
frontend/pnpm-lock.yaml
generated
@@ -6,11 +6,13 @@ specifiers:
|
||||
'@sveltejs/adapter-static': ^1.0.0-next.28
|
||||
'@sveltejs/kit': 1.0.0-next.288
|
||||
'@types/file-saver': ^2.0.5
|
||||
'@types/sanitize-html': ^2.6.2
|
||||
adm-zip: ^0.5.9
|
||||
copy-to-clipboard: ^3.3.1
|
||||
dotenv: ^16.0.0
|
||||
file-saver: ^2.0.5
|
||||
pretty-bytes: ^5.6.0
|
||||
sanitize-html: ^2.7.0
|
||||
svelte: ^3.46.4
|
||||
svelte-check: ^2.4.5
|
||||
svelte-intl-precompile: ^0.8.1
|
||||
@@ -24,12 +26,14 @@ dependencies:
|
||||
copy-to-clipboard: 3.3.1
|
||||
file-saver: 2.0.5
|
||||
pretty-bytes: 5.6.0
|
||||
sanitize-html: 2.7.0
|
||||
|
||||
devDependencies:
|
||||
'@lokalise/node-api': 7.1.1
|
||||
'@sveltejs/adapter-static': 1.0.0-next.28
|
||||
'@sveltejs/kit': 1.0.0-next.288_svelte@3.46.4
|
||||
'@types/file-saver': 2.0.5
|
||||
'@types/sanitize-html': 2.6.2
|
||||
adm-zip: 0.5.9
|
||||
dotenv: 16.0.0
|
||||
svelte: 3.46.4
|
||||
@@ -212,6 +216,8 @@ packages:
|
||||
resolution: {integrity: sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
'@babel/types': 7.17.0
|
||||
dev: true
|
||||
|
||||
/@babel/template/7.16.7:
|
||||
@@ -429,6 +435,12 @@ packages:
|
||||
'@types/node': 17.0.21
|
||||
dev: true
|
||||
|
||||
/@types/sanitize-html/2.6.2:
|
||||
resolution: {integrity: sha512-7Lu2zMQnmHHQGKXVvCOhSziQMpa+R2hMHFefzbYoYMHeaXR0uXqNeOc3JeQQQ8/6Xa2Br/P1IQTLzV09xxAiUQ==}
|
||||
dependencies:
|
||||
htmlparser2: 6.1.0
|
||||
dev: true
|
||||
|
||||
/@types/sass/1.43.1:
|
||||
resolution: {integrity: sha512-BPdoIt1lfJ6B7rw35ncdwBZrAssjcwzI5LByIrYs+tpXlj/CAkuVdRsgZDdP4lq5EjyWzwxZCqAoFyHKFwp32g==}
|
||||
dependencies:
|
||||
@@ -610,6 +622,11 @@ packages:
|
||||
mimic-response: 3.1.0
|
||||
dev: true
|
||||
|
||||
/deepmerge/4.2.2:
|
||||
resolution: {integrity: sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/defer-to-connect/2.0.1:
|
||||
resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -620,6 +637,29 @@ packages:
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/dom-serializer/1.4.1:
|
||||
resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==}
|
||||
dependencies:
|
||||
domelementtype: 2.3.0
|
||||
domhandler: 4.3.1
|
||||
entities: 2.2.0
|
||||
|
||||
/domelementtype/2.3.0:
|
||||
resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==}
|
||||
|
||||
/domhandler/4.3.1:
|
||||
resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==}
|
||||
engines: {node: '>= 4'}
|
||||
dependencies:
|
||||
domelementtype: 2.3.0
|
||||
|
||||
/domutils/2.8.0:
|
||||
resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==}
|
||||
dependencies:
|
||||
dom-serializer: 1.4.1
|
||||
domelementtype: 2.3.0
|
||||
domhandler: 4.3.1
|
||||
|
||||
/dotenv/16.0.0:
|
||||
resolution: {integrity: sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q==}
|
||||
engines: {node: '>=12'}
|
||||
@@ -635,6 +675,9 @@ packages:
|
||||
once: 1.4.0
|
||||
dev: true
|
||||
|
||||
/entities/2.2.0:
|
||||
resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==}
|
||||
|
||||
/es6-promise/3.3.1:
|
||||
resolution: {integrity: sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=}
|
||||
dev: true
|
||||
@@ -857,6 +900,11 @@ packages:
|
||||
engines: {node: '>=0.8.0'}
|
||||
dev: true
|
||||
|
||||
/escape-string-regexp/4.0.0:
|
||||
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
|
||||
engines: {node: '>=10'}
|
||||
dev: false
|
||||
|
||||
/estree-walker/2.0.2:
|
||||
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
|
||||
dev: true
|
||||
@@ -981,6 +1029,14 @@ packages:
|
||||
function-bind: 1.1.1
|
||||
dev: true
|
||||
|
||||
/htmlparser2/6.1.0:
|
||||
resolution: {integrity: sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==}
|
||||
dependencies:
|
||||
domelementtype: 2.3.0
|
||||
domhandler: 4.3.1
|
||||
domutils: 2.8.0
|
||||
entities: 2.2.0
|
||||
|
||||
/http-cache-semantics/4.1.0:
|
||||
resolution: {integrity: sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==}
|
||||
dev: true
|
||||
@@ -1042,6 +1098,11 @@ packages:
|
||||
engines: {node: '>=0.12.0'}
|
||||
dev: true
|
||||
|
||||
/is-plain-object/5.0.0:
|
||||
resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/js-tokens/4.0.0:
|
||||
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
||||
dev: true
|
||||
@@ -1151,7 +1212,6 @@ packages:
|
||||
resolution: {integrity: sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==}
|
||||
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/node-releases/2.0.2:
|
||||
resolution: {integrity: sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==}
|
||||
@@ -1185,6 +1245,10 @@ packages:
|
||||
callsites: 3.1.0
|
||||
dev: true
|
||||
|
||||
/parse-srcset/1.0.2:
|
||||
resolution: {integrity: sha1-8r0iH2zJcKk42IVWq8WJyqqiveE=}
|
||||
dev: false
|
||||
|
||||
/path-is-absolute/1.0.1:
|
||||
resolution: {integrity: sha1-F0uSaHNVNP+8es5r9TpanhtcX18=}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -1201,7 +1265,6 @@ packages:
|
||||
|
||||
/picocolors/1.0.0:
|
||||
resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
|
||||
dev: true
|
||||
|
||||
/picomatch/2.3.1:
|
||||
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
|
||||
@@ -1215,7 +1278,6 @@ packages:
|
||||
nanoid: 3.3.1
|
||||
picocolors: 1.0.0
|
||||
source-map-js: 1.0.2
|
||||
dev: true
|
||||
|
||||
/precompile-intl-runtime/0.4.15_svelte@3.46.4:
|
||||
resolution: {integrity: sha512-B05lHn02+68hOHZkUo35vNo0K/IRiVCT7dkWmjI9tpzAn/2zbGjllU6EwqsQXxXrf2CKj1fAD5wgUbapNO+RXQ==}
|
||||
@@ -1323,6 +1385,17 @@ packages:
|
||||
rimraf: 2.7.1
|
||||
dev: true
|
||||
|
||||
/sanitize-html/2.7.0:
|
||||
resolution: {integrity: sha512-jfQelabOn5voO7FAfnQF7v+jsA6z9zC/O4ec0z3E35XPEtHYJT/OdUziVWlKW4irCr2kXaQAyXTXDHWAibg1tA==}
|
||||
dependencies:
|
||||
deepmerge: 4.2.2
|
||||
escape-string-regexp: 4.0.0
|
||||
htmlparser2: 6.1.0
|
||||
is-plain-object: 5.0.0
|
||||
parse-srcset: 1.0.2
|
||||
postcss: 8.4.7
|
||||
dev: false
|
||||
|
||||
/semver/6.3.0:
|
||||
resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==}
|
||||
hasBin: true
|
||||
@@ -1341,7 +1414,6 @@ packages:
|
||||
/source-map-js/1.0.2:
|
||||
resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/source-map/0.5.7:
|
||||
resolution: {integrity: sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=}
|
||||
|
@@ -4,11 +4,13 @@
|
||||
import copy from 'copy-to-clipboard'
|
||||
import { saveAs } from 'file-saver'
|
||||
import prettyBytes from 'pretty-bytes'
|
||||
import sanitize from 'sanitize-html'
|
||||
import { t } from 'svelte-intl-precompile'
|
||||
import Button from './Button.svelte'
|
||||
|
||||
export let note: NotePublic
|
||||
|
||||
const RE_URL = /[A-Za-z]+:\/\/([A-Z a-z0-9\-._~:\/?#\[\]@!$&'()*+,;%=])+/g
|
||||
let files: FileDTO[] = []
|
||||
|
||||
$: if (note.meta.type === 'file') {
|
||||
@@ -27,12 +29,20 @@
|
||||
})
|
||||
saveAs(f)
|
||||
}
|
||||
|
||||
function contentWithLinks(content: string): string {
|
||||
const replaced = note.contents.replace(
|
||||
RE_URL,
|
||||
(url) => `<a href="${url}" rel="noreferrer">${url}</a>`
|
||||
)
|
||||
return sanitize(replaced, { allowedTags: ['a'], allowedAttributes: { a: ['href', 'rel'] } })
|
||||
}
|
||||
</script>
|
||||
|
||||
<p class="error-text">{@html $t('show.warning_will_not_see_again')}</p>
|
||||
{#if note.meta.type === 'text'}
|
||||
<div class="note">
|
||||
{note.contents}
|
||||
{@html contentWithLinks(note.contents)}
|
||||
</div>
|
||||
<Button on:click={() => copy(note.contents)}>{$t('common.copy_clipboard')}</Button>
|
||||
{:else}
|
||||
|
Reference in New Issue
Block a user