Compare commits

...

76 Commits

Author SHA1 Message Date
Elian Doran
6734d765c9 Bump to 0.90.11-beta 2024-11-11 19:48:50 +02:00
Elian Doran
470594b1c7 Merge pull request #573 from TriliumNext/perfectra1n-patch-2
Update README to mention MacOS command fix
2024-11-11 19:42:56 +02:00
Elian Doran
782d34566d Merge pull request #577 from hasecilu/i18n/Spanish_mini
i18n: Update Spanish translations, 100%
2024-11-11 19:41:32 +02:00
hasecilu
1b2a772612 i18n: Update Spanish translations, 100% 2024-11-11 10:35:54 -06:00
Elian Doran
46218d6ab4 Merge pull request #574 from TriliumNext/fix-version-update-check
More reliably check for version updates
2024-11-11 00:47:51 +02:00
perf3ct
1d2366fa06 fix "click to download" button 2024-11-10 17:18:26 +00:00
perf3ct
0acba0eac4 add docstring for func 2024-11-09 22:23:02 +00:00
perf3ct
48d53e276e more reliably check for version numbers 2024-11-09 22:16:00 +00:00
Elian Doran
47baa02bca i18n: Translate 100% of Romanian 2024-11-09 23:34:18 +02:00
Elian Doran
bc35c3c641 i18n: Remove some German-only messages 2024-11-09 23:31:45 +02:00
Jon Fuller
790b87f23f Update README to mention MacOS command fix 2024-11-09 13:28:45 -08:00
Elian Doran
48ba15ad88 i18n: Fix incorrect IDs for German 2024-11-09 23:25:34 +02:00
Elian Doran
cda28cfd65 Merge pull request #561 from j13055/develop
added german translation
2024-11-09 23:17:23 +02:00
Elian Doran
7ffe145481 Merge pull request #569 from TriliumNext/perfectra1n-patch-2
Update README.md for incremented sync version
2024-11-09 23:14:53 +02:00
Elian Doran
ac2bca790b Fix duplicate title for Trilium toolbar item (fixes #525) 2024-11-09 23:12:10 +02:00
Elian Doran
774966e640 client: Allow more link protocols (fixes #122) 2024-11-09 23:06:26 +02:00
Elian Doran
81310d33b0 Merge pull request #571 from TriliumNext/feature/classic_editor
Classic editor for text notes (with fixed toolbar)
2024-11-09 22:40:38 +02:00
Jon Fuller
34e6430977 Update README.md
Co-authored-by: Elian Doran <contact@eliandoran.me>
2024-11-09 12:30:52 -08:00
Elian Doran
15b4eacdca client: Change design of editor settings slightly 2024-11-09 21:35:37 +02:00
Elian Doran
7c342aed9e client: Use translations for editor settings 2024-11-09 21:34:09 +02:00
Elian Doran
8c69d47aed client,server: Implement shortcut for toggle classic editor toolbar 2024-11-09 18:36:38 +02:00
Elian Doran
f88d3220b5 client: Repair attribute editor 2024-11-09 18:09:05 +02:00
Elian Doran
70a98a3d33 client: Use refactored version of CKEditor 2024-11-09 15:40:14 +02:00
Elian Doran
6e0a10cf2c client: Hide ribbon tab when classic editor is off 2024-11-09 14:54:04 +02:00
Elian Doran
c421e75f55 client: Respect editor type choice 2024-11-09 14:49:05 +02:00
Elian Doran
89420eafa3 client: Set up ui for selecting editor UI 2024-11-09 14:33:20 +02:00
Elian Doran
7a70fc14b3 server: Set up editor type option 2024-11-09 14:33:14 +02:00
Elian Doran
d2008e7e5f client: Use different method to highlight disabled buttons 2024-11-09 14:15:03 +02:00
Elian Doran
745c9846a6 client: Use better method to expose CK watchdog 2024-11-09 14:13:08 +02:00
Elian Doran
3972bb2ecf client: Use build of CKEditor containing both types 2024-11-09 14:11:15 +02:00
Elian Doran
06262adf91 client: Use translation for classic toolbar title 2024-11-09 13:40:13 +02:00
Elian Doran
5771060b57 client: Reorganize classic toolbar 2024-11-09 13:39:24 +02:00
Elian Doran
6a11f9c073 client: Add some JSDoc 2024-11-09 10:46:12 +02:00
Elian Doran
85ee7def84 client: Improve loading feel for classic toolbar 2024-11-09 10:37:14 +02:00
Elian Doran
b88f0e0109 client: Hide ribbon for non text or read-only notes 2024-11-09 10:33:45 +02:00
Elian Doran
787aa6f5a6 client: Remove background for decoupled editor 2024-11-09 09:56:25 +02:00
Elian Doran
4f39188198 client: Use decoupled CKEditor 2024-11-09 09:43:37 +02:00
Elian Doran
dd6e762dab client: Activate ribbon toolbar by default 2024-11-09 09:19:38 +02:00
Elian Doran
48bc9204ac client: Create empty toolbar ribbon 2024-11-09 09:18:59 +02:00
Elian Doran
918f425e1f client: Group options for classic editor 2024-11-09 09:12:46 +02:00
Elian Doran
821af8dc11 client: Integrate block toolbar into classic options 2024-11-09 08:29:58 +02:00
Elian Doran
44734435ea client: Remove block toolbar in classic mode 2024-11-09 00:32:26 +02:00
Elian Doran
01c53b6d9f client: Use same config as bubble editor for classic 2024-11-09 00:21:27 +02:00
Elian Doran
9a5de0d4c8 client: Basic integration of classic editor w/ no attribute editor 2024-11-09 00:15:19 +02:00
Elian Doran
5116bddc5f client: Group image align buttons in CKEditor 2024-11-08 23:44:52 +02:00
Elian Doran
92aa671ec7 client: Support inline images in CKEditor (fixes #531) 2024-11-08 23:29:56 +02:00
Elian Doran
1f4d09f6f0 client: Patch CKEditor to fix IME (fixes #568)
See https://github.com/ckeditor/ckeditor5/pull/16289
2024-11-08 22:49:07 +02:00
Elian Doran
29e83b97e6 client: Fix rendering notes if hljs is not loaded 2024-11-08 21:50:22 +02:00
Jon Fuller
18de0857b3 Update README.md for incremented sync version 2024-11-08 10:43:45 -08:00
Elian Doran
2048a30aa5 Merge pull request #547 from TriliumNext/smaller-container
Make the container smaller
2024-11-08 19:20:48 +02:00
Elian Doran
78017e4d36 client: Improve classic toolbar layout on mobile 2024-11-08 00:26:20 +02:00
Elian Doran
35fe5845a3 client: Fix classic editor on mobile 2024-11-08 00:20:51 +02:00
Elian Doran
1261bdbb29 client: Use correct background for code note preview 2024-11-07 23:58:10 +02:00
Elian Doran
91fa1a6cb1 client: Add syntax highlight for code note previews 2024-11-07 23:53:02 +02:00
Elian Doran
1816fcd3ac client: force-graph: 1.45.0 -> 1.46.0 2024-11-07 23:11:22 +02:00
Elian Doran
d13044b972 client: mind-elixir: 4.3.0 -> 4.3.1 2024-11-07 23:09:59 +02:00
Elian Doran
f5205fdd30 electron: Fix code block theme loading in dev mode 2024-11-07 23:09:53 +02:00
Elian Doran
930b8e0ce2 Merge pull request #555 from rom1dep/mouse_scroll_dir
fix: mouse scroll wheel direction for zoom level
2024-11-07 22:25:24 +02:00
Elian Doran
b5988ba7c2 Merge pull request #559 from TriliumNext/siriusxt-test
Make attachments open in a new tab/browser
2024-11-07 22:22:42 +02:00
j13055
75e2ceed5d added german translation 2024-11-06 13:52:23 +01:00
SiriusXT
d2ee3738a2 Make attachments open in a new tab/browser 2024-11-06 10:02:42 +08:00
perf3ct
8a548f6589 also update the Alpine Dockerfile 2024-11-05 16:41:00 +00:00
perf3ct
0859a955b1 Results in a much smaller container 2024-11-04 17:38:05 -08:00
Elian Doran
a02146df17 server: Fix loading of code block theme on server builds 2024-11-05 02:58:21 +02:00
Elian Doran
a6385557b5 Merge pull request #545 from TriliumNext/latest-is-stable-container
Explicitly manage the "latest" tag, and have it point to the same tag as "stable"
2024-11-05 02:41:03 +02:00
Elian Doran
00aebfcdf0 Merge pull request #530 from Potjoe-97/patch-1
Patch fr translation
2024-11-05 02:38:53 +02:00
Elian Doran
c6b3ace807 client: mind-elixir: 4.2.4 -> 4.3.0 2024-11-05 02:33:12 +02:00
Elian Doran
6799544950 Update package-lock.json 2024-11-05 02:31:42 +02:00
Romain DEP.
21cfb64f83 fix: mouse scroll wheel direction 2024-11-03 23:01:01 +01:00
Potjoe-97
80e6276d31 Merge branch 'develop' into patch-1 2024-11-03 10:48:00 +01:00
Potjoe-97
0192060ad2 Update fr server.json : all strings translated 2024-11-03 10:44:56 +01:00
Potjoe-97
e41ff54c0d Update translation.json : all strings translated 2024-11-03 10:43:15 +01:00
perf3ct
bdece7216f have the latest tag be the same as stable tag
get rid of this annoying default "latest" tag useage

to squash

to squash, I love whitespace

don't need to verify
2024-11-02 21:51:06 +00:00
Potjoe-97
88d8f57697 Merge pull request #3 from Potjoe-97/patch-2
Update translation.json
2024-10-28 16:03:33 +01:00
Potjoe-97
b7e254975f Update translation.json 2024-10-28 16:02:17 +01:00
Potjoe-97
97b2ba2da1 Update server.json 2024-10-28 16:01:04 +01:00
41 changed files with 2113 additions and 175 deletions

View File

@@ -129,6 +129,8 @@ jobs:
type=ref,event=branch
type=ref,event=tag
type=sha
flavor: |
latest=false
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
@@ -213,7 +215,9 @@ jobs:
images: |
${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}
${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}
flavor: |
latest=false
- name: Login to GHCR
uses: docker/login-action@v2
with:
@@ -246,6 +250,7 @@ jobs:
# If the ref is a tag, also tag the image as stable as this is part of a 'release'
# and only go in the `if` if there is NOT a `-` in the tag's name, due to tagging of `-alpha`, `-beta`, etc...
if [[ "${GITHUB_REF}" == refs/tags/* && ! "${REF_NAME}" =~ - ]]; then
# First create stable tags
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
-t ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:stable \
$(printf '${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *)
@@ -253,6 +258,19 @@ jobs:
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
-t ${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:stable \
$(printf '${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *)
# Small delay to ensure stable tag is fully propagated
sleep 5
# Now update latest tags
docker buildx imagetools create \
-t ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:latest \
${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:stable
docker buildx imagetools create \
-t ${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:latest \
${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:stable
fi
- name: Inspect image

View File

@@ -1,7 +1,7 @@
# !!! Don't try to build this Dockerfile directly, run it through bin/build-docker.sh script !!!
FROM node:20.15.1-bullseye-slim
# Build stage
FROM node:20.15.1-bullseye-slim AS builder
# Configure system dependencies
# Configure build dependencies in a single layer
RUN apt-get update && apt-get install -y --no-install-recommends \
autoconf \
automake \
@@ -12,49 +12,52 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
nasm \
libpng-dev \
python3 \
gosu \
&& rm -rf /var/lib/apt/lists/*
# Create app directory
WORKDIR /usr/src/app
# Bundle app source
# Copy only necessary files for build
COPY . .
COPY server-package.json package.json
# Copy TypeScript build artifacts into the original directory structure.
# Copy the healthcheck
# Build and cleanup in a single layer
RUN cp -R build/src/* src/. && \
cp build/docker_healthcheck.js . && \
rm -r build && \
rm docker_healthcheck.ts
# Install app dependencies
RUN apt-get purge -y --auto-remove \
autoconf \
automake \
g++ \
gcc \
libtool \
make \
nasm \
libpng-dev \
python3 \
&& rm -rf /var/lib/apt/lists/*
RUN npm install && \
rm docker_healthcheck.ts && \
npm install && \
npm run webpack && \
npm prune --omit=dev
RUN cp src/public/app/share.js src/public/app-dist/. && \
npm prune --omit=dev && \
npm cache clean --force && \
cp src/public/app/share.js src/public/app-dist/. && \
cp -r src/public/app/doc_notes src/public/app-dist/. && \
rm -rf src/public/app && rm src/services/asset_path.ts
rm -rf src/public/app && \
rm src/services/asset_path.ts
# Some setup tools need to be kept
# Runtime stage
FROM node:20.15.1-bullseye-slim
# Install only runtime dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
gosu \
&& rm -rf /var/lib/apt/lists/*
&& rm -rf /var/lib/apt/lists/* && \
rm -rf /var/cache/apt/*
# Start the application
WORKDIR /usr/src/app
# Copy only necessary files from builder
COPY --from=builder /usr/src/app/node_modules ./node_modules
COPY --from=builder /usr/src/app/src ./src
COPY --from=builder /usr/src/app/db ./db
COPY --from=builder /usr/src/app/docker_healthcheck.js .
COPY --from=builder /usr/src/app/start-docker.sh .
COPY --from=builder /usr/src/app/package.json .
COPY --from=builder /usr/src/app/config-sample.ini .
COPY --from=builder /usr/src/app/images ./images
COPY --from=builder /usr/src/app/translations ./translations
COPY --from=builder /usr/src/app/libraries ./libraries
# Configure container
EXPOSE 8080
CMD [ "./start-docker.sh" ]
HEALTHCHECK --start-period=10s CMD exec gosu node node docker_healthcheck.js

View File

@@ -1,7 +1,7 @@
# !!! Don't try to build this Dockerfile directly, run it through bin/build-docker.sh script !!!
FROM node:20.15.1-alpine
# Build stage
FROM node:20.15.1-alpine AS builder
# Configure system dependencies
# Configure build dependencies
RUN apk add --no-cache --virtual .build-dependencies \
autoconf \
automake \
@@ -11,43 +11,52 @@ RUN apk add --no-cache --virtual .build-dependencies \
make \
nasm \
libpng-dev \
python3
python3
# Create app directory
WORKDIR /usr/src/app
# Bundle app source
# Copy only necessary files for build
COPY . .
COPY server-package.json package.json
# Copy TypeScript build artifacts into the original directory structure.
# Copy the healthcheck
# Build and cleanup in a single layer
RUN cp -R build/src/* src/. && \
cp build/docker_healthcheck.js . && \
rm -r build && \
rm docker_healthcheck.ts
# Install app dependencies
RUN set -x && \
rm docker_healthcheck.ts && \
npm install && \
apk del .build-dependencies && \
npm run webpack && \
npm prune --omit=dev && \
npm cache clean --force && \
cp src/public/app/share.js src/public/app-dist/. && \
cp -r src/public/app/doc_notes src/public/app-dist/. && \
rm -rf src/public/app && \
rm src/services/asset_path.ts
# Runtime stage
FROM node:20.15.1-alpine
# Some setup tools need to be kept
# Install runtime dependencies
RUN apk add --no-cache su-exec shadow
# Add application user and setup proper volume permissions
WORKDIR /usr/src/app
# Copy only necessary files from builder
COPY --from=builder /usr/src/app/node_modules ./node_modules
COPY --from=builder /usr/src/app/src ./src
COPY --from=builder /usr/src/app/db ./db
COPY --from=builder /usr/src/app/docker_healthcheck.js .
COPY --from=builder /usr/src/app/start-docker.sh .
COPY --from=builder /usr/src/app/package.json .
COPY --from=builder /usr/src/app/config-sample.ini .
COPY --from=builder /usr/src/app/images ./images
COPY --from=builder /usr/src/app/translations ./translations
COPY --from=builder /usr/src/app/libraries ./libraries
# Add application user
RUN adduser -s /bin/false node; exit 0
# Start the application
# Configure container
EXPOSE 8080
CMD [ "./start-docker.sh" ]
HEALTHCHECK --start-period=10s CMD exec su-exec node node docker_healthcheck.js
HEALTHCHECK --start-period=10s CMD exec su-exec node node docker_healthcheck.js

View File

@@ -18,6 +18,8 @@ See [screenshots](https://triliumnext.github.io/Docs/Wiki/screenshot-tour) for q
There are no special migration steps to migrate from a zadam/Trilium instance to a TriliumNext/Notes instance. Just upgrade your Trilium instance to the latest version and [install TriliumNext/Notes as usual](#-installation)
Versions up to and including [v0.90.4](https://github.com/TriliumNext/Notes/releases/tag/v0.90.4) are compatible with the latest zadam/trilium version of [v0.63.7](https://github.com/zadam/trilium/releases/tag/v0.63.7). Any later versions of TriliumNext have their sync versions incremented.
## 💬 Discuss with us
Feel free to join our official conversations. We would love to hear what features, suggestions, or issues you may have!
@@ -65,6 +67,16 @@ To use TriliumNext on your desktop machine (Linux, MacOS, and Windows) you have
* Currently only the latest versions of Chrome & Firefox are supported (and tested).
* (Coming Soon) TriliumNext will also be provided as a Flatpak
#### MacOS
Currently when running TriliumNext/Notes on MacOS, you may get the following error:
> Apple could not verify "TriliumNext Notes" is free of malware and may harm your Mac or compromise your privacy.
You will need to run the command on your shell to resolve the error (documented [here](https://github.com/TriliumNext/Notes/issues/329#issuecomment-2287164137)):
```bash
xattr -c "/path/to/Trilium Next.app"
```
### Mobile
To use TriliumNext on a mobile device:

49
libraries/ckeditor/ckeditor.d.ts vendored Normal file
View File

@@ -0,0 +1,49 @@
/**
* @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/
import { DecoupledEditor as DecoupledEditorBase } from '@ckeditor/ckeditor5-editor-decoupled';
import { Essentials } from '@ckeditor/ckeditor5-essentials';
import { Alignment } from '@ckeditor/ckeditor5-alignment';
import { FontSize, FontFamily, FontColor, FontBackgroundColor } from '@ckeditor/ckeditor5-font';
import { CKFinderUploadAdapter } from '@ckeditor/ckeditor5-adapter-ckfinder';
import { Autoformat } from '@ckeditor/ckeditor5-autoformat';
import { Bold, Italic, Strikethrough, Underline } from '@ckeditor/ckeditor5-basic-styles';
import { BlockQuote } from '@ckeditor/ckeditor5-block-quote';
import { CKBox } from '@ckeditor/ckeditor5-ckbox';
import { CKFinder } from '@ckeditor/ckeditor5-ckfinder';
import { EasyImage } from '@ckeditor/ckeditor5-easy-image';
import { Heading } from '@ckeditor/ckeditor5-heading';
import { Image, ImageCaption, ImageResize, ImageStyle, ImageToolbar, ImageUpload, PictureEditing } from '@ckeditor/ckeditor5-image';
import { Indent, IndentBlock } from '@ckeditor/ckeditor5-indent';
import { Link } from '@ckeditor/ckeditor5-link';
import { List, ListProperties } from '@ckeditor/ckeditor5-list';
import { MediaEmbed } from '@ckeditor/ckeditor5-media-embed';
import { Paragraph } from '@ckeditor/ckeditor5-paragraph';
import { PasteFromOffice } from '@ckeditor/ckeditor5-paste-from-office';
import { Table, TableToolbar } from '@ckeditor/ckeditor5-table';
import { TextTransformation } from '@ckeditor/ckeditor5-typing';
import { CloudServices } from '@ckeditor/ckeditor5-cloud-services';
export default class DecoupledEditor extends DecoupledEditorBase {
static builtinPlugins: (typeof TextTransformation | typeof Essentials | typeof Alignment | typeof FontBackgroundColor | typeof FontColor | typeof FontFamily | typeof FontSize | typeof CKFinderUploadAdapter | typeof Paragraph | typeof Heading | typeof Autoformat | typeof Bold | typeof Italic | typeof Strikethrough | typeof Underline | typeof BlockQuote | typeof Image | typeof ImageCaption | typeof ImageResize | typeof ImageStyle | typeof ImageToolbar | typeof ImageUpload | typeof CloudServices | typeof CKBox | typeof CKFinder | typeof EasyImage | typeof List | typeof ListProperties | typeof Indent | typeof IndentBlock | typeof Link | typeof MediaEmbed | typeof PasteFromOffice | typeof Table | typeof TableToolbar | typeof PictureEditing)[];
static defaultConfig: {
toolbar: {
items: string[];
};
image: {
resizeUnit: "px";
toolbar: string[];
};
table: {
contentToolbar: string[];
};
list: {
properties: {
styles: boolean;
startIndex: boolean;
reversed: boolean;
};
};
language: string;
};
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

20
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "trilium",
"version": "0.90.9-beta",
"version": "0.90.11-beta",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "trilium",
"version": "0.90.9-beta",
"version": "0.90.11-beta",
"license": "AGPL-3.0-only",
"dependencies": {
"@braintree/sanitize-url": "7.1.0",
@@ -40,7 +40,7 @@
"express-partial-content": "1.0.2",
"express-rate-limit": "7.4.1",
"express-session": "1.18.1",
"force-graph": "1.45.0",
"force-graph": "1.46.0",
"fs-extra": "11.2.0",
"helmet": "7.1.0",
"html": "1.0.0",
@@ -67,7 +67,7 @@
"marked": "14.1.3",
"mermaid": "11.4.0",
"mime-types": "2.1.35",
"mind-elixir": "4.2.4",
"mind-elixir": "4.3.1",
"multer": "1.4.5-lts.1",
"node-abi": "3.67.0",
"normalize-strings": "1.1.1",
@@ -9144,9 +9144,9 @@
}
},
"node_modules/force-graph": {
"version": "1.45.0",
"resolved": "https://registry.npmjs.org/force-graph/-/force-graph-1.45.0.tgz",
"integrity": "sha512-QM/J72Vji5D3ug+TDu8wH+qne0zEKE9Cn7m9ocH/1RtaVY0BBqZQ4Mn6MiwNRyxwl28lsUd0F54kDpINnagvOA==",
"version": "1.46.0",
"resolved": "https://registry.npmjs.org/force-graph/-/force-graph-1.46.0.tgz",
"integrity": "sha512-RR4XIsMgKMquEmN6me2MoDeqMr85Cv1cpXDFha6gwEczaaC3RWDH4YmXQXnI8/egRiIKFMq4HKjBjWXZwyy/9Q==",
"dependencies": {
"@tweenjs/tween.js": "18 - 25",
"accessor-fn": "1",
@@ -12330,9 +12330,9 @@
}
},
"node_modules/mind-elixir": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/mind-elixir/-/mind-elixir-4.2.4.tgz",
"integrity": "sha512-wYJN45TcdznUaX8lKBbHqgiKd6jY4aK+JoCCT82m8uKB9DiOv4RGf4O5MrziH6mkP1/fAZHQztFfr49PUILAzQ=="
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/mind-elixir/-/mind-elixir-4.3.1.tgz",
"integrity": "sha512-9dHqiNRlAFUlGUKHwPwLC+Dka2cEaNunzHbZkOw+mafz8pqeZbmmm7Xxlk2S2zbKPGxeayxTYrDDg2tmNAXe3Q=="
},
"node_modules/minimalistic-assert": {
"version": "1.0.1",

View File

@@ -2,7 +2,7 @@
"name": "trilium",
"productName": "TriliumNext Notes",
"description": "Build your personal knowledge base with TriliumNext Notes",
"version": "0.90.10-beta",
"version": "0.90.11-beta",
"license": "AGPL-3.0-only",
"main": "./dist/electron-main.js",
"author": {
@@ -81,7 +81,7 @@
"express-partial-content": "1.0.2",
"express-rate-limit": "7.4.1",
"express-session": "1.18.1",
"force-graph": "1.45.0",
"force-graph": "1.46.0",
"fs-extra": "11.2.0",
"helmet": "7.1.0",
"html": "1.0.0",
@@ -108,7 +108,7 @@
"marked": "14.1.3",
"mermaid": "11.4.0",
"mime-types": "2.1.35",
"mind-elixir": "4.2.4",
"mind-elixir": "4.3.1",
"multer": "1.4.5-lts.1",
"node-abi": "3.67.0",
"normalize-strings": "1.1.1",

View File

@@ -16,7 +16,7 @@ class ZoomComponent extends Component {
window.addEventListener("wheel", event => {
if (event.ctrlKey) {
this.setZoomFactorAndSave(this.getCurrentZoom() + event.deltaY * 0.001);
this.setZoomFactorAndSave(this.getCurrentZoom() - event.deltaY * 0.001);
}
});
}
@@ -56,7 +56,7 @@ class ZoomComponent extends Component {
zoomResetEvent() {
this.setZoomFactorAndSave(1);
}
setZoomFactorAndSaveEvent({zoomFactor}) {
this.setZoomFactorAndSave(zoomFactor);
}

View File

@@ -82,6 +82,7 @@ import MovePaneButton from "../widgets/buttons/move_pane_button.js";
import UploadAttachmentsDialog from "../widgets/dialogs/upload_attachments.js";
import CopyImageReferenceButton from "../widgets/floating_buttons/copy_image_reference_button.js";
import ScrollPaddingWidget from "../widgets/scroll_padding.js";
import ClassicEditorToolbar from "../widgets/ribbon_widgets/classic_editor_toolbar.js";
export default class DesktopLayout {
constructor(customWidgets) {
@@ -140,6 +141,7 @@ export default class DesktopLayout {
// the order of the widgets matter. Some of these want to "activate" themselves
// when visible. When this happens to multiple of them, the first one "wins".
// promoted attributes should always win.
.ribbon(new ClassicEditorToolbar())
.ribbon(new PromotedAttributesWidget())
.ribbon(new ScriptExecutorWidget())
.ribbon(new SearchDefinitionWidget())

View File

@@ -23,6 +23,7 @@ import LauncherContainer from "../widgets/containers/launcher_container.js";
import RootContainer from "../widgets/containers/root_container.js";
import SharedInfoWidget from "../widgets/shared_info.js";
import PromotedAttributesWidget from "../widgets/ribbon_widgets/promoted_attributes.js";
import ClassicEditorToolbar from "../widgets/ribbon_widgets/classic_editor_toolbar.js";
const MOBILE_CSS = `
<style>
@@ -167,6 +168,7 @@ export default class MobileLayout {
.child(new NoteListWidget())
.child(new FilePropertiesWidget().css('font-size','smaller'))
)
.child(new ClassicEditorToolbar())
)
.child(new ProtectedSessionPasswordDialog())
.child(new ConfirmDialog())

View File

@@ -10,7 +10,8 @@ import treeService from "./tree.js";
import FNote from "../entities/fnote.js";
import FAttachment from "../entities/fattachment.js";
import imageContextMenuService from "../menus/image_context_menu.js";
import { applySyntaxHighlight } from "./syntax_highlight.js";
import { applySingleBlockSyntaxHighlight, applySyntaxHighlight } from "./syntax_highlight.js";
import mime_types from "./mime_types.js";
let idCounter = 1;
@@ -113,11 +114,18 @@ async function renderText(note, $renderedContent) {
}
}
/** @param {FNote} note */
/**
* Renders a code note, by displaying its content and applying syntax highlighting based on the selected MIME type.
*
* @param {FNote} note
*/
async function renderCode(note, $renderedContent) {
const blob = await note.getBlob();
$renderedContent.append($("<pre>").text(blob.content));
const $codeBlock = $("<code>");
$codeBlock.text(blob.content);
$renderedContent.append($("<pre>").append($codeBlock));
await applySingleBlockSyntaxHighlight($codeBlock, mime_types.normalizeMimeTypeForCKEditor(note.mime));
}
function renderImage(entity, $renderedContent, options = {}) {

View File

@@ -371,7 +371,8 @@ class NoteListRenderer {
$content.append($renderedContent);
$content.addClass(`type-${type}`);
} catch (e) {
console.log(`Caught error while rendering note '${note.noteId}' of type '${note.type}': ${e.message}, stack: ${e.stack}`);
console.warn(`Caught error while rendering note '${note.noteId}' of type '${note.type}'`);
console.error(e);
$content.append("rendering error");
}

View File

@@ -23,33 +23,48 @@ export function getStylesheetUrl(theme) {
export async function applySyntaxHighlight($container) {
if (!isSyntaxHighlightEnabled()) {
return;
}
await library_loader.requireLibrary(library_loader.HIGHLIGHT_JS);
}
const codeBlocks = $container.find("pre code");
for (const codeBlock of codeBlocks) {
$(codeBlock).parent().toggleClass("hljs");
const text = codeBlock.innerText;
const normalizedMimeType = extractLanguageFromClassList(codeBlock);
if (!normalizedMimeType) {
continue;
}
let highlightedText = null;
if (normalizedMimeType === mime_types.MIME_TYPE_AUTO) {
highlightedText = hljs.highlightAuto(text);
} else if (normalizedMimeType) {
const language = mime_types.getHighlightJsNameForMime(normalizedMimeType);
highlightedText = hljs.highlight(text, { language });
}
if (highlightedText) {
codeBlock.innerHTML = highlightedText.value;
applySingleBlockSyntaxHighlight($(codeBlock, normalizedMimeType));
}
}
/**
* Applies syntax highlight to the given code block (assumed to be <pre><code>), using highlight.js.
*
* @param {*} $codeBlock
* @param {*} normalizedMimeType
*/
export async function applySingleBlockSyntaxHighlight($codeBlock, normalizedMimeType) {
$codeBlock.parent().toggleClass("hljs");
const text = $codeBlock.text();
if (!window.hljs) {
await library_loader.requireLibrary(library_loader.HIGHLIGHT_JS);
}
let highlightedText = null;
if (normalizedMimeType === mime_types.MIME_TYPE_AUTO) {
highlightedText = hljs.highlightAuto(text);
} else if (normalizedMimeType) {
const language = mime_types.getHighlightJsNameForMime(normalizedMimeType);
if (language) {
highlightedText = hljs.highlight(text, { language });
} else {
console.warn(`Unknown mime type: ${normalizedMimeType}.`);
}
}
if (highlightedText) {
$codeBlock.html(highlightedText.value);
}
}
/**

View File

@@ -527,6 +527,58 @@ function downloadSvg(nameWithoutExtension, svgContent) {
document.body.removeChild(element);
}
/**
* Compares two semantic version strings.
* Returns:
* 1 if v1 is greater than v2
* 0 if v1 is equal to v2
* -1 if v1 is less than v2
*
* @param {string} v1 First version string
* @param {string} v2 Second version string
* @returns {number}
*/
function compareVersions(v1, v2) {
// Remove 'v' prefix and everything after dash if present
v1 = v1.replace(/^v/, '').split('-')[0];
v2 = v2.replace(/^v/, '').split('-')[0];
const v1parts = v1.split('.').map(Number);
const v2parts = v2.split('.').map(Number);
// Pad shorter version with zeros
while (v1parts.length < 3) v1parts.push(0);
while (v2parts.length < 3) v2parts.push(0);
// Compare major version
if (v1parts[0] !== v2parts[0]) {
return v1parts[0] > v2parts[0] ? 1 : -1;
}
// Compare minor version
if (v1parts[1] !== v2parts[1]) {
return v1parts[1] > v2parts[1] ? 1 : -1;
}
// Compare patch version
if (v1parts[2] !== v2parts[2]) {
return v1parts[2] > v2parts[2] ? 1 : -1;
}
return 0;
}
/**
* Compares two semantic version strings and returns `true` if the latest version is greater than the current version.
* @param {string} latestVersion
* @param {string} currentVersion
* @returns {boolean}
*/
function isUpdateAvailable(latestVersion, currentVersion) {
return compareVersions(latestVersion, currentVersion) > 0;
}
export default {
reloadFrontendApp,
parseDate,
@@ -567,5 +619,7 @@ export default {
areObjectsEqual,
copyHtmlToClipboard,
createImageSrcUrl,
downloadSvg
downloadSvg,
compareVersions,
isUpdateAvailable
};

View File

@@ -347,8 +347,7 @@ export default class AttributeEditorWidget extends NoteContextAwareWidget {
this.$editor.on("click", e => this.handleEditorClick(e));
/** @property {BalloonEditor} */
this.textEditor = await BalloonEditor.create(this.$editor[0], editorConfig);
this.textEditor = await CKEditor.BalloonEditor.create(this.$editor[0], editorConfig);
this.textEditor.model.document.on('change:data', () => this.dataChanged());
this.textEditor.editing.view.document.on('enter', (event, data) => {
// disable entering new line - see https://github.com/ckeditor/ckeditor5/issues/9422
@@ -358,9 +357,6 @@ export default class AttributeEditorWidget extends NoteContextAwareWidget {
// disable spellcheck for attribute editor
this.textEditor.editing.view.change(writer => writer.setAttribute('spellcheck', 'false', this.textEditor.editing.view.document.getRoot()));
//await import(/* webpackIgnore: true */'../../libraries/ckeditor/inspector');
//CKEditorInspector.attach(this.textEditor);
}
dataChanged() {

View File

@@ -333,7 +333,8 @@ export default class GlobalMenuWidget extends BasicWidget {
const latestVersion = await this.fetchLatestVersion();
this.updateAvailableWidget.updateVersionStatus(latestVersion);
this.$updateToLatestVersionButton.toggle(latestVersion > glob.triliumVersion);
// Show "click to download" button in options menu if there's a new version available
this.$updateToLatestVersionButton.toggle(utils.isUpdateAvailable(latestVersion, glob.triliumVersion));
this.$updateToLatestVersionButton.find(".version-text").text(`Version ${latestVersion} is available, click to download.`);
}

View File

@@ -1,5 +1,6 @@
import { t } from "../../services/i18n.js";
import BasicWidget from "../basic_widget.js";
import utils from "../../services/utils.js";
const TPL = `
<div style="display: none;">
@@ -34,6 +35,6 @@ export default class UpdateAvailableWidget extends BasicWidget {
}
updateVersionStatus(latestVersion) {
this.$widget.toggle(latestVersion > glob.triliumVersion);
this.$widget.toggle(utils.isUpdateAvailable(latestVersion, glob.triliumVersion));
}
}

View File

@@ -216,7 +216,7 @@ export default class RibbonContainer extends NoteContextAwareWidget {
this.$tabContainer.empty();
for (const ribbonWidget of this.ribbonWidgets) {
const ret = ribbonWidget.getTitle(note);
const ret = await ribbonWidget.getTitle(note);
if (!ret.show) {
continue;
@@ -351,6 +351,16 @@ export default class RibbonContainer extends NoteContextAwareWidget {
}
}
/**
* Executed as soon as the user presses the "Edit" floating button in a read-only text note.
*
* <p>
* We need to refresh the ribbon for cases such as the classic editor which relies on the read-only state.
*/
readOnlyTemporarilyDisabledEvent() {
this.refresh();
}
getActiveRibbonWidget() {
return this.ribbonWidgets.find(ch => ch.componentId === this.lastActiveComponentId)
}

View File

@@ -0,0 +1,83 @@
import { t } from "../../services/i18n.js";
import options from "../../services/options.js";
import NoteContextAwareWidget from "../note_context_aware_widget.js";
const TPL = `\
<div class="classic-toolbar-widget"></div>
<style>
.classic-toolbar-widget {
--ck-color-toolbar-background: transparent;
--ck-color-button-default-background: transparent;
--ck-color-button-default-disabled-background: transparent;
min-height: 39px;
}
.classic-toolbar-widget .ck.ck-toolbar {
border: none;
}
.classic-toolbar-widget .ck.ck-button.ck-disabled {
opacity: 0.3;
}
body.mobile .classic-toolbar-widget {
position: relative;
overflow-x: auto;
}
body.mobile .classic-toolbar-widget .ck.ck-toolbar {
position: absolute;
}
</style>
`;
/**
* Handles the editing toolbar when the CKEditor is in decoupled mode.
*
* <p>
* This toolbar is only enabled if the user has selected the classic CKEditor.
*
* <p>
* The ribbon item is active by default for text notes, as long as they are not in read-only mode.
*/
export default class ClassicEditorToolbar extends NoteContextAwareWidget {
get name() {
return "classicEditor";
}
get toggleCommand() {
return "toggleRibbonTabClassicEditor";
}
doRender() {
this.$widget = $(TPL);
this.contentSized();
}
async getTitle() {
return {
show: await this.#shouldDisplay(),
activate: true,
title: t("classic_editor_toolbar.title"),
icon: "bx bx-edit-alt"
};
}
async #shouldDisplay() {
if (options.get("textNoteEditorType") !== "ckeditor-classic") {
return false;
}
if (this.note.type !== "text") {
return false;
}
if (await this.noteContext.isReadOnly()) {
return false;
}
return true;
}
}

View File

@@ -32,7 +32,7 @@ export default class AbstractTextTypeWidget extends TypeWidget {
async openImageInCurrentTab($img) {
const { noteId, viewScope } = await this.parseFromImage($img);
if (noteId) {
appContext.tabManager.getActiveContext().setNote(noteId, { viewScope });
} else {
@@ -40,8 +40,8 @@ export default class AbstractTextTypeWidget extends TypeWidget {
}
}
openImageInNewTab($img) {
const { noteId, viewScope } = this.parseFromImage($img);
async openImageInNewTab($img) {
const { noteId, viewScope } = await this.parseFromImage($img);
if (noteId) {
appContext.tabManager.openTabWithNoteWithHoisting(noteId, { viewScope });

View File

@@ -35,6 +35,7 @@ import AttachmentErasureTimeoutOptions from "./options/other/attachment_erasure_
import RibbonOptions from "./options/appearance/ribbon.js";
import LocalizationOptions from "./options/appearance/i18n.js";
import CodeBlockOptions from "./options/appearance/code_block.js";
import EditorOptions from "./options/text_notes/editor.js";
const TPL = `<div class="note-detail-content-widget note-detail-printable">
<style>
@@ -68,6 +69,7 @@ const CONTENT_WIDGETS = {
],
_optionsShortcuts: [ KeyboardShortcutsOptions ],
_optionsTextNotes: [
EditorOptions,
HeadingStyleOptions,
TableOfContentsOptions,
HighlightsListOptions,

View File

@@ -12,7 +12,6 @@ import appContext from "../../components/app_context.js";
import dialogService from "../../services/dialog.js";
import { initSyntaxHighlighting } from "./ckeditor/syntax_highlight.js";
import options from "../../services/options.js";
import { isSyntaxHighlightEnabled } from "../../services/syntax_highlight.js";
const ENABLE_INSPECTOR = false;
@@ -107,6 +106,12 @@ function buildListOfLanguages() {
];
}
/**
* The editor can operate into two distinct modes:
*
* - Ballon block mode, in which there is a floating toolbar for the selected text, but another floating button for the entire block (i.e. paragraph).
* - Decoupled mode, in which the editing toolbar is actually added on the client side (in {@link ClassicEditorToolbar}), see https://ckeditor.com/docs/ckeditor5/latest/examples/framework/bottom-toolbar-editor.html for an example on how the decoupled editor works.
*/
export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
static getType() { return "editableText"; }
@@ -125,6 +130,8 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
async initEditor() {
await libraryLoader.requireLibrary(libraryLoader.CKEDITOR);
const isClassicEditor = (options.get("textNoteEditorType") === "ckeditor-classic")
const editorClass = (isClassicEditor ? CKEditor.DecoupledEditor : CKEditor.BalloonEditor);
const codeBlockLanguages = buildListOfLanguages();
@@ -133,7 +140,7 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
// display of $widget in both branches.
this.$widget.show();
this.watchdog = new EditorWatchdog(BalloonEditor, {
this.watchdog = new CKEditor.EditorWatchdog(editorClass, {
// An average number of milliseconds between the last editor errors (defaults to 5000).
// When the period of time between errors is lower than that and the crashNumberLimit
// is also reached, the watchdog changes its state to crashedPermanently, and it stops
@@ -169,10 +176,23 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
});
this.watchdog.setCreator(async (elementOrData, editorConfig) => {
const editor = await BalloonEditor.create(elementOrData, editorConfig);
const editor = await editorClass.create(elementOrData, editorConfig);
await initSyntaxHighlighting(editor);
if (isClassicEditor) {
let $classicToolbarWidget;
if (!utils.isMobile()) {
const $parentSplit = this.$widget.parents(".note-split.type-text");
$classicToolbarWidget = $parentSplit.find("> .ribbon-container .classic-toolbar-widget");
} else {
$classicToolbarWidget = $("body").find(".classic-toolbar-widget");
}
$classicToolbarWidget.empty();
$classicToolbarWidget[0].appendChild(editor.ui.view.toolbar.element);
}
editor.model.document.on('change:data', () => this.spacedUpdate.scheduleUpdate());
if (glob.isDev && ENABLE_INSPECTOR) {

View File

@@ -0,0 +1,30 @@
import { t } from "../../../../services/i18n.js";
import utils from "../../../../services/utils.js";
import OptionsWidget from "../options_widget.js";
const TPL = `
<div class="options-section">
<h4>${t("editing.editor_type.label")}</h4>
<select class="editor-type-select form-select">
<option value="ckeditor-balloon">${t("editing.editor_type.floating")}</option>
<option value="ckeditor-classic">${t("editing.editor_type.fixed")}</option>
</select>
</div>`;
export default class EditorOptions extends OptionsWidget {
doRender() {
this.$widget = $(TPL);
this.$body = $("body");
this.$editorType = this.$widget.find(".editor-type-select");
this.$editorType.on('change', async () => {
const newEditorType = this.$editorType.val();
await this.updateOption('textNoteEditorType', newEditorType);
utils.reloadFrontendApp("editor type change");
});
}
async optionsLoaded(options) {
this.$editorType.val(options.textNoteEditorType);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1508,5 +1508,18 @@
},
"code_block": {
"word_wrapping": "Word wrapping"
},
"classic_editor_toolbar": {
"title": "Formatting"
},
"editor": {
"title": "Editor"
},
"editing": {
"editor_type": {
"label": "Formatting toolbar",
"floating": "Floating (editing tools appear near the cursor)",
"fixed": "Fixed (editing tools appear in the \"Formatting\" ribbon tab)"
}
}
}

View File

@@ -1508,5 +1508,18 @@
},
"code_block": {
"word_wrapping": "Ajuste de palabras"
},
"classic_editor_toolbar": {
"title": "Formato"
},
"editor": {
"title": "Editor"
},
"editing": {
"editor_type": {
"label": "Barra de herramientas de formato",
"floating": "Flotante (las herramientas de edición aparecen cerca del cursor)",
"fixed": "Fijo (las herramientas de edición aparecen en la pestaña de la cinta \"Formato\")"
}
}
}

View File

@@ -15,7 +15,13 @@
"message": "Une erreur critique s'est produite qui empêche l'application client de démarrer :\n\n{{message}}\n\nCeci est probablement dû à un échec inattendu d'un script. Essayez de démarrer l'application en mode sans échec et de résoudre le problème."
},
"widget-error": {
"title": "Impossible d'initialiser un widget"
"title": "Impossible d'initialiser un widget",
"message-custom": "Le widget personnalisé de la note avec l'ID \"{{id}}\", intitulée \"{{title}}\" n'a pas pu être initialisé en raison de\n\n{{message}}",
"message-unknown": "Le widget inconnu n'a pas pu être initialisé :\n\n{{message}}"
},
"bundle-error": {
"title": "Echec du chargement d'un script personnalisé",
"message": "Le script de la note avec l'ID \"{{id}}\", intitulé \"{{title}}\" n'a pas pu être exécuté à cause de\n\n{{message}}"
}
},
"add_link": {
@@ -51,7 +57,7 @@
"clone_notes_to": "Cloner des notes dans...",
"help_on_links": "Aide sur les liens",
"notes_to_clone": "Notes à cloner",
"target_parent_note": "Note parent cible",
"target_parent_note": "Note parent de destination",
"search_for_note_by_its_name": "rechercher une note par son nom",
"cloned_note_prefix_title": "La note clonée sera affichée dans l'arbre des notes avec le préfixe donné",
"prefix_optional": "Préfixe (facultatif)",
@@ -68,8 +74,8 @@
"also_delete_note": "Supprimer également la note"
},
"delete_notes": {
"delete_notes_preview": "Supprimer l'aperçu des notes",
"delete_all_clones_description": "Supprime également tous les clones (peut être annulé depuis les Modifications récentes)",
"delete_notes_preview": "Supprimer la note",
"delete_all_clones_description": "supprime également tous les clones (peut être annulé depuis les Modifications récentes)",
"erase_notes_description": "La suppression normale (douce) marque uniquement les notes comme supprimées et elles peuvent être restaurées (dans la boîte de dialogue des Modifications récentes) dans un délai donné. Cocher cette option effacera les notes immédiatement et il ne sera pas possible de les restaurer.",
"erase_notes_warning": "Efface les notes de manière permanente (ne peut pas être annulée), y compris tous les clones. Cela forcera le rechargement de lapplication.",
"notes_to_be_deleted": "Les notes suivantes seront supprimées ({{- noteCount}})",
@@ -164,7 +170,8 @@
"textImportedAsText": "Importez HTML, Markdown et TXT sous forme de notes de texte si les métadonnées ne sont pas claires",
"codeImportedAsCode": "Importez des fichiers de code reconnus (par exemple <code>.json</code>) en tant que notes de code si cela n'est pas clair à partir des métadonnées",
"replaceUnderscoresWithSpaces": "Remplacez les tirets bas par des espaces dans les noms de notes importées",
"import": "Importer"
"import": "Importer",
"failed": "Échec de l'importation : {{message}}."
},
"include_note": {
"dialog_title": "Inclure une note",
@@ -194,7 +201,7 @@
"move_to": {
"dialog_title": "Déplacer les notes vers...",
"notes_to_move": "Notes à déplacer",
"target_parent_note": "Note parent cible",
"target_parent_note": "Note parent de destination",
"search_placeholder": "rechercher une note par son nom",
"move_button": "Déplacer vers la note sélectionnée <kbd>entrer</kbd>",
"error_no_path": "Aucun chemin vers lequel déplacer.",
@@ -231,7 +238,7 @@
"confirm_undelete": "Voulez-vous restaurer cette note et ses sous-notes ?"
},
"revisions": {
"note_revisions": "Versions des notes",
"note_revisions": "Versions de la note",
"delete_all_revisions": "Supprimer toutes les versions de cette note",
"delete_all_button": "Supprimer toutes les versions",
"help_title": "Aide sur les versions de notes",
@@ -245,7 +252,7 @@
"revisions_deleted": "Les versions de notes ont été supprimées.",
"revision_restored": "La version de la note a été restaurée.",
"revision_deleted": "La version de la note a été supprimée.",
"snapshot_interval": "Intervalle d'instantané des versions de notes : {{seconds}}s.",
"snapshot_interval": "Intervalle d'enregistrement des versions de notes : {{seconds}}s.",
"maximum_revisions": "Nombre maximal de versions pour la note actuelle : {{number}}.",
"settings": "Paramètres pour les versions de notes",
"download_button": "Télécharger",
@@ -396,7 +403,7 @@
"share_js": "Note JavaScript qui sera injectée dans la page de partage. La note JS doit également figurer dans le sous-arbre partagé. Pensez à utiliser 'share_hidden_from_tree'.",
"share_template": "Note JavaScript intégrée qui sera utilisée comme modèle pour afficher la note partagée. Revient au modèle par défaut. Pensez à utiliser 'share_hidden_from_tree'.",
"share_favicon": "Favicon de la note à définir dans la page partagée. En règle générale, vous souhaitez le configurer pour partager la racine et le rendre héritable. La note Favicon doit également figurer dans le sous-arbre partagé. Pensez à utiliser 'share_hidden_from_tree'.",
"is_owned_by_note": "appartient à la note",
"is_owned_by_note": "appartenant à la note",
"other_notes_with_name": "Autres notes portant le nom {{attributeType}} \"{{attributeName}}\"",
"and_more": "... et {{count}} plus."
},
@@ -425,7 +432,7 @@
"add_label": "Ajouter un label",
"label_name_placeholder": "nom du label",
"label_name_title": "Les caractères autorisés sont : caractères alphanumériques, les tirets bas et les deux-points.",
"to_value": "modifié par",
"to_value": "égal à",
"new_value_placeholder": "nouvelle valeur",
"help_text": "Pour toutes les notes correspondantes :",
"help_text_item1": "créer un label donné si la note ne le possède pas encore",
@@ -468,7 +475,7 @@
"move_note": {
"move_note": "Déplacer la note",
"to": "vers",
"target_parent_note": "note parent cible",
"target_parent_note": "note parent de destination",
"on_all_matched_notes": "Pour toutes les notes correspondantes",
"move_note_new_parent": "déplacer la note vers le nouveau parent si la note n'a qu'un seul parent (c.-à-d. l'ancienne branche est supprimée et une nouvelle branche est créée dans le nouveau parent)",
"clone_note_new_parent": "cloner la note vers le nouveau parent si la note a plusieurs clones/branches (il n'est pas clair quelle branche doit être supprimée)",
@@ -476,7 +483,7 @@
},
"rename_note": {
"rename_note": "Renommer la note",
"rename_note_title_to": "Renommer le titre de la note en",
"rename_note_title_to": "Renommer la note en",
"new_note_title": "nouveau titre de note",
"click_help_icon": "Cliquez sur l'icône d'aide à droite pour voir toutes les options",
"evaluated_as_js_string": "La valeur donnée est évaluée comme une chaîne JavaScript et peut ainsi être enrichie de contenu dynamique via la variable <code>note</code> injectée (la note étant renommée). Exemples :",
@@ -551,7 +558,7 @@
"febuary": "Février",
"march": "Mars",
"april": "Avril",
"may": "Peut",
"may": "Mai",
"june": "Juin",
"july": "Juillet",
"august": "Août",
@@ -619,18 +626,21 @@
},
"note_actions": {
"convert_into_attachment": "Convertir en pièce jointe",
"re_render_note": "Re-rendre la note",
"re_render_note": "Recharger la note",
"search_in_note": "Rechercher dans la note",
"note_source": "Source de la note",
"note_source": "Code source",
"note_attachments": "Pièces jointes",
"open_note_externally": "Ouverture externe",
"open_note_externally_title": "Le fichier sera ouvert dans une application externe et les modifications apportées seront surveillées. Vous pourrez ensuite téléverser la version modifiée dans Trilium.",
"open_note_custom": "Ouvrir la note avec",
"import_files": "Importer des fichiers",
"export_note": "Exporter la note",
"export_note": "Exporter",
"delete_note": "Supprimer la note",
"print_note": "Imprimer la note",
"save_revision": "Enregistrer la version"
"print_note": "Imprimer",
"save_revision": "Enregistrer une version",
"convert_into_attachment_failed": "La conversion de la note '{{title}}' a échoué.",
"convert_into_attachment_successful": "La note '{{title}}' a été convertie en pièce jointe.",
"convert_into_attachment_prompt": "Êtes-vous sûr de vouloir convertir la note '{{title}}' en une pièce jointe de la note parente ?"
},
"onclick_button": {
"no_click_handler": "Le widget bouton '{{componentId}}' n'a pas de gestionnaire de clic défini"
@@ -640,13 +650,13 @@
"inactive": "Cliquez pour accéder à une session protégée"
},
"revisions_button": {
"note_revisions": "Versions des Notes"
"note_revisions": "Versions de la note"
},
"update_available": {
"update_available": "Mise à jour disponible"
},
"note_launcher": {
"this_launcher_doesnt_define_target_note": "Ce lanceur ne définit pas de note cible."
"this_launcher_doesnt_define_target_note": "Ce raccourci ne définit pas de note cible."
},
"code_buttons": {
"execute_button_title": "Exécuter le script",
@@ -693,7 +703,7 @@
"basic_properties": {
"note_type": "Type de note",
"editable": "Modifiable",
"basic_properties": "Propriétés de base"
"basic_properties": "Propriétés basiques"
},
"book_properties": {
"view_type": "Type d'affichage",
@@ -703,7 +713,7 @@
"expand_all_children": "Développer tous les enfants",
"collapse": "Réduire",
"expand": "Développer",
"book_properties": "Propriétés du livre",
"book_properties": "Propriétés basiques",
"invalid_view_type": "Type de vue non valide '{{type}}'"
},
"edited_notes": {
@@ -740,9 +750,9 @@
"no_inherited_attributes": "Aucun attribut hérité."
},
"note_info_widget": {
"note_id": "Identifiant de la note",
"created": "Créé",
"modified": "Modifié",
"note_id": "ID de la note",
"created": "Créée le",
"modified": "Modifiée le",
"type": "Type",
"note_size": "Taille de la note",
"note_size_info": "La taille de la note fournit une estimation approximative des besoins de stockage pour cette note. Il prend en compte le contenu de la note et de ses versions.",
@@ -751,12 +761,12 @@
"title": "Infos sur la Note"
},
"note_map": {
"open_full": "Développer au maximum",
"open_full": "Agrandir au maximum",
"collapse": "Réduire à la taille normale",
"title": "Carte de la Note"
"title": "Liens de la note"
},
"note_paths": {
"title": "Chemins de la Note",
"title": "Chemins de la note",
"clone_button": "Cloner la note vers un nouvel emplacement...",
"intro_placed": "Cette note est située dans les chemins suivants :",
"intro_not_placed": "Cette note n'est pas encore située dans l'arbre des notes.",
@@ -787,7 +797,7 @@
"execute_script": "Exécuter le script"
},
"search_definition": {
"add_search_option": "Ajouter une option de recherche :",
"add_search_option": "Options de recherche :",
"search_string": "chaîne de caractères à rechercher",
"search_script": "script de recherche",
"ancestor": "ancêtre",
@@ -885,7 +895,8 @@
"label_rock_or_pop": "un seul des labels doit être présent",
"label_year_comparison": "comparaison numérique (également >, >=, <).",
"label_date_created": "notes créées le mois dernier",
"error": "Erreur de recherche : {{error}}"
"error": "Erreur de recherche : {{error}}",
"search_prefix": "Recherche :"
},
"attachment_detail": {
"open_help_page": "Ouvrir la page d'aide sur les pièces jointes",
@@ -919,7 +930,15 @@
},
"protected_session": {
"enter_password_instruction": "L'affichage de la note protégée nécessite la saisie de votre mot de passe :",
"start_session_button": "Démarrer une session protégée"
"start_session_button": "Démarrer une session protégée",
"started": "La session protégée a démarré.",
"wrong_password": "Mot de passe incorrect.",
"protecting-finished-successfully": "La protection de la note s'est terminée avec succès.",
"unprotecting-finished-successfully": "La protection de la note a été retirée avec succès.",
"protecting-in-progress": "Protection en cours : {{count}}",
"unprotecting-in-progress-count": "Retrait de la protection en cours : {{count}}",
"protecting-title": "Statut de la protection",
"unprotecting-title": "Statut de la non-protection"
},
"relation_map": {
"open_in_new_tab": "Ouvrir dans un nouvel onglet",
@@ -974,7 +993,7 @@
"error_creating_anonymized_database": "Impossible de créer une base de données anonymisée, vérifiez les journaux backend pour plus de détails",
"successfully_created_fully_anonymized_database": "Base de données entièrement anonymisée crée dans {{anonymizedFilePath}}",
"successfully_created_lightly_anonymized_database": "Base de données partiellement anonymisée crée dans {{anonymizedFilePath}}",
"no_anonymized_database_yet": "Aucune base de données anonymisée"
"no_anonymized_database_yet": "Aucune base de données anonymisée."
},
"database_integrity_check": {
"title": "Vérification de l'intégrité de la base de données",
@@ -990,7 +1009,9 @@
"fill_entity_changes_button": "Remplir les enregistrements de modifications d'entité",
"full_sync_triggered": "Synchronisation complète déclenchée",
"filling_entity_changes": "Remplissage changements de ligne d'entité ...",
"sync_rows_filled_successfully": "Synchronisation avec succès des lignes remplies"
"sync_rows_filled_successfully": "Synchronisation avec succès des lignes remplies",
"finished-successfully": "Synchronisation terminée avec succès.",
"failed": "Échec de la synchronisation : {{message}}"
},
"vacuum_database": {
"title": "Nettoyage la base de donnée",
@@ -1000,7 +1021,7 @@
"database_vacuumed": "La base de données a été nettoyée"
},
"fonts": {
"theme_defined": "Thème défini",
"theme_defined": "Défini par le thème",
"fonts": "Polices",
"main_font": "Police principale",
"font_family": "Famille de polices",
@@ -1008,14 +1029,14 @@
"note_tree_font": "Police de l'arborescence",
"note_detail_font": "Police du contenu des notes",
"monospace_font": "Police Monospace (code)",
"note_tree_and_detail_font_sizing": "Notez que la taille de la police de larborescence et des détails est relative au paramètre de taille de police principal.",
"not_all_fonts_available": "Toutes les polices répertoriées peuvent ne pas être disponibles sur votre système.",
"note_tree_and_detail_font_sizing": "Notez que la taille de la police de larborescence et du contenu est relative au paramètre de taille de police principal.",
"not_all_fonts_available": "Toutes les polices répertoriées ne sont peut-être pas disponibles sur votre système.",
"apply_font_changes": "Pour appliquer les modifications de police, cliquez sur",
"reload_frontend": "recharger l'interface"
},
"max_content_width": {
"title": "Largeur du contenu",
"default_description": "Trilium limite par défaut la largeur maximale du contenu pour améliorer la lisibilité sur des écrans larges.",
"default_description": "Trilium limite par défaut la largeur maximale du contenu pour améliorer la lisibilité sur les écrans larges.",
"max_width_label": "Largeur maximale du contenu en pixels",
"apply_changes_description": "Pour appliquer les modifications de largeur du contenu, cliquez sur",
"reload_button": "recharger l'interface",
@@ -1035,7 +1056,7 @@
"title": "Thème",
"theme_label": "Thème",
"override_theme_fonts_label": "Remplacer les polices du thème",
"light_theme": "Lumière",
"light_theme": "Clair",
"dark_theme": "Sombre"
},
"zoom_factor": {
@@ -1087,16 +1108,16 @@
"deleted_notes_erased": "Les notes supprimées ont été effacées."
},
"revisions_snapshot_interval": {
"note_revisions_snapshot_interval_title": "Intervalle dinstantané des Versions de notes",
"note_revisions_snapshot_description": "L'intervalle de temps de l'instantané de version de note est le temps en secondes après lequel une nouvelle version de note est créée pour une note. Consultez le <a href=\"https://triliumnext.github.io/Docs/Wiki/note-revisions.html\" class=\"external\">wiki</a> pour plus d'informations.",
"snapshot_time_interval_label": "Intervalle de temps entre deux instantanés de version de note (en secondes) :"
"note_revisions_snapshot_interval_title": "Intervalle d'enregistrement automatique des versions des notes",
"note_revisions_snapshot_description": "L'intervalle d'enregistrement automatique des versions de note est le temps en secondes après lequel une nouvelle version de note est créée pour une note. Consultez le <a href=\"https://triliumnext.github.io/Docs/Wiki/note-revisions.html\" class=\"external\">wiki</a> pour plus d'informations.",
"snapshot_time_interval_label": "Intervalle de temps entre deux enregistrements de version de note (en secondes) :"
},
"revisions_snapshot_limit": {
"note_revisions_snapshot_limit_title": "Limite des instantanés de version de note",
"note_revisions_snapshot_limit_description": "La limite du nombre dinstantanés de version de note désigne le nombre maximum de versions pouvant être enregistrées pour chaque note. -1 signifie aucune limite, 0 signifie supprimer toutes les versions. Vous pouvez définir le nombre maximal de versions pour une seule note via le label #versioningLimit.",
"snapshot_number_limit_label": "Nombre limite d'instantanés de version de la note :",
"erase_excess_revision_snapshots": "Effacez maintenant les instantanés de version en excès",
"erase_excess_revision_snapshots_prompt": "Les instantanés de version en excès ont été effacés."
"note_revisions_snapshot_limit_title": "Limite des enregistrements de version de note",
"note_revisions_snapshot_limit_description": "La limite du nombre d'enregistrements de version de note désigne le nombre maximum de versions pouvant être enregistrées pour chaque note. -1 signifie aucune limite, 0 signifie supprimer toutes les versions. Vous pouvez définir le nombre maximal de versions pour une seule note via le label #versioningLimit.",
"snapshot_number_limit_label": "Nombre limite d'enregistrements de version de la note :",
"erase_excess_revision_snapshots": "Effacez maintenant les versions en excès",
"erase_excess_revision_snapshots_prompt": "Les versions en excès ont été effacées."
},
"search_engine": {
"title": "Moteur de recherche",
@@ -1109,7 +1130,7 @@
"custom_name_label": "Nom du moteur de recherche personnalisé",
"custom_name_placeholder": "Personnaliser le nom du moteur de recherche",
"custom_url_label": "L'URL du moteur de recherche personnalisé doit inclure {keyword} comme espace réservé pour le terme de recherche.",
"custom_url_placeholder": "Personnaliser l'URL du moteur de recherche",
"custom_url_placeholder": "Personnaliser l'url du moteur de recherche",
"save_button": "Sauvegarder"
},
"tray": {
@@ -1146,7 +1167,7 @@
"label": "Taille automatique en lecture seule (notes de texte)"
},
"i18n": {
"title": "Localisation",
"title": "Paramètres régionaux",
"language": "Langue",
"first-day-of-the-week": "Premier jour de la semaine",
"sunday": "Dimanche",
@@ -1197,7 +1218,7 @@
"password": {
"heading": "Mot de passe",
"alert_message": "Prenez soin de mémoriser votre nouveau mot de passe. Le mot de passe est utilisé pour se connecter à l'interface Web et pour crypter les notes protégées. Si vous oubliez votre mot de passe, toutes vos notes protégées seront définitivement perdues.",
"reset_link": "cliquez ici pour le réinitialiser.",
"reset_link": "Cliquez ici pour le réinitialiser.",
"old_password": "Ancien mot de passe",
"new_password": "Nouveau mot de passe",
"new_password_confirmation": "Confirmation du nouveau mot de passe",
@@ -1265,7 +1286,7 @@
"unrecognized_role": "Rôle de pièce jointe « {{role}} » non reconnu."
},
"bookmark_switch": {
"bookmark": "Favoris",
"bookmark": "Favori",
"bookmark_this_note": "Ajouter cette note à vos favoris dans le panneau latéral gauche",
"remove_bookmark": "Supprimer le favori"
},
@@ -1279,7 +1300,7 @@
},
"note-map": {
"button-link-map": "Carte des liens",
"button-tree-map": "Carte de l'arborescence"
"button-tree-map": "Carte arborescente"
},
"tree-context-menu": {
"open-in-a-new-tab": "Ouvrir dans un nouvel onglet",
@@ -1288,6 +1309,8 @@
"insert-child-note": "Insérer une note enfant",
"delete": "Supprimer",
"search-in-subtree": "Rechercher dans le sous-arbre",
"hoist-note": "Focus sur la note",
"unhoist-note": "Ne plus focus la note",
"edit-branch-prefix": "Modifier le préfixe de branche",
"advanced": "Avancé",
"expand-subtree": "Développer le sous-arbre",
@@ -1307,7 +1330,9 @@
"duplicate-subtree": "Dupliquer le sous-arbre",
"export": "Exporter",
"import-into-note": "Importer dans la note",
"apply-bulk-actions": "Appliquer des Actions groupées"
"apply-bulk-actions": "Actions groupées",
"converted-to-attachments": "Les notes {{count}} ont été converties en pièces jointes.",
"convert-to-attachment-confirm": "Êtes-vous sûr de vouloir convertir les notes sélectionnées en pièces jointes de leurs notes parentes ?"
},
"shared_info": {
"shared_publicly": "Cette note est partagée publiquement sur",
@@ -1320,7 +1345,7 @@
"saved-search": "Recherche enregistrée",
"relation-map": "Carte des relations",
"note-map": "Carte de notes",
"render-note": "Rendu HTML",
"render-note": "Rendre la note",
"book": "Livre",
"mermaid-diagram": "Diagramme Mermaid",
"canvas": "Canevas",
@@ -1330,7 +1355,8 @@
"image": "Image",
"launcher": "Raccourci",
"doc": "Doc",
"widget": "Widget"
"widget": "Widget",
"confirm-change": "Il n'est pas recommandé de modifier le type de note lorsque son contenu n'est pas vide. Voulez-vous continuer ?"
},
"protect_note": {
"toggle-on": "Protéger la note",
@@ -1353,7 +1379,7 @@
"open-help-page": "Ouvrir la page d'aide",
"find": {
"case_sensitive": "sensible aux majuscules et minuscules",
"match_words": "faire correspondre les mots"
"match_words": "correspondance exacte"
},
"highlights_list_2": {
"title": "Accentuations",
@@ -1376,10 +1402,12 @@
"hide-archived-notes": "Masquer les notes archivées",
"automatically-collapse-notes": "Réduire automatiquement les notes",
"automatically-collapse-notes-title": "Les notes seront réduites après une période d'inactivité pour désencombrer l'arborescence.",
"save-changes": "Enregistrer et appliquer les modifications"
"save-changes": "Enregistrer et appliquer les modifications",
"auto-collapsing-notes-after-inactivity": "Réduction automatique des notes après inactivité...",
"saved-search-note-refreshed": "Note de recherche enregistrée actualisée."
},
"title_bar_buttons": {
"window-on-top": "Gardez cette fenêtre au premier plan."
"window-on-top": "Épingler cette fenêtre au premier plan."
},
"note_detail": {
"could_not_find_typewidget": "Impossible de trouver typeWidget pour le type '{{type}}'"
@@ -1399,5 +1427,74 @@
},
"sql_table_schemas": {
"tables": "Tableaux"
},
"tab_row": {
"close_tab": "Fermer l'onglet",
"add_new_tab": "Ajouter un nouvel onglet",
"close": "Fermer",
"close_other_tabs": "Fermer les autres onglets",
"close_all_tabs": "Fermer tous les onglets",
"move_tab_to_new_window": "Déplacer cet onglet vers une nouvelle fenêtre",
"new_tab": "Nouvel onglet"
},
"toc": {
"table_of_contents": "Table des matières",
"options": "Options"
},
"watched_file_update_status": {
"file_last_modified": "Le fichier <code class=\"file-path\"></code> a été modifié pour la dernière fois le <span class=\"file-last-modified\"></span>.",
"upload_modified_file": "Téléverser le fichier modifié",
"ignore_this_change": "Ignorer ce changement"
},
"app_context": {
"please_wait_for_save": "Veuillez patienter quelques secondes la fin de la sauvegarde, puis réessayer."
},
"note_create": {
"duplicated": "La note «{{title}}» a été dupliquée."
},
"image": {
"copied-to-clipboard": "Une référence à l'image a été copiée dans le presse-papiers. Elle peut être collée dans n'importe quelle note texte.",
"cannot-copy": "Impossible de copier la référence d'image dans le presse-papiers."
},
"clipboard": {
"cut": "Les note(s) ont été coupées dans le presse-papiers.",
"copied": "Les note(s) ont été coupées dans le presse-papiers."
},
"entrypoints": {
"note-revision-created": "La version de la note a été créée.",
"note-executed": "Note exécutée.",
"sql-error": "Erreur lors de l'exécution de la requête SQL: {{message}}"
},
"branches": {
"cannot-move-notes-here": "Impossible de déplacer les notes ici.",
"delete-status": "Etat de la suppression",
"delete-notes-in-progress": "Suppression des notes en cours : {{count}}",
"delete-finished-successfully": "Suppression terminée avec succès.",
"undeleting-notes-in-progress": "Restauration des notes en cours : {{count}}",
"undeleting-notes-finished-successfully": "Restauration des notes terminée avec succès."
},
"frontend_script_api": {
"async_warning": "Vous passez une fonction asynchrone à `api.runOnBackend()`, ce qui ne fonctionnera probablement pas comme vous le souhaitez.\\n Rendez la fonction synchronisée (en supprimant le mot-clé `async`), ou bien utilisez `api.runAsyncOnBackendWithManualTransactionHandling()`.",
"sync_warning": "Vous passez une fonction synchrone à `api.runAsyncOnBackendWithManualTransactionHandling()`,\\nalors que vous devriez probablement utiliser `api.runOnBackend()` à la place."
},
"ws": {
"sync-check-failed": "Le test de synchronisation a échoué !",
"consistency-checks-failed": "Les tests de cohérence ont échoué ! Consultez les journaux pour plus de détails.",
"encountered-error": "Erreur \"{{message}}\", consultez la console."
},
"hoisted_note": {
"confirm_unhoisting": "La note demandée «{{requestedNote}}» est en dehors du sous-arbre de la note focus «{{hoistedNote}}». Le focus doit être désactivé pour accéder à la note. Voulez-vous enlever le focus ?"
},
"launcher_context_menu": {
"reset_launcher_confirm": "Voulez-vous vraiment réinitialiser \"{{title}}\" ? Toutes les données / paramètres de cette note (et de ses enfants) seront perdus et le raccourci retrouvera son emplacement d'origine.",
"add-note-launcher": "Ajouter un raccourci de note",
"add-script-launcher": "Ajouter un raccourci de script",
"add-custom-widget": "Ajouter un widget personnalisé",
"add-spacer": "Ajouter un séparateur",
"delete": "Supprimer",
"reset": "Réinitialiser",
"move-to-visible-launchers": "Déplacer vers les raccourcis visibles",
"move-to-available-launchers": "Déplacer vers les raccourcis disponibles",
"duplicate-launcher": "Dupliquer le raccourci"
}
}

View File

@@ -1508,5 +1508,18 @@
},
"code_block": {
"word_wrapping": "Încadrare text"
},
"classic_editor_toolbar": {
"title": "Formatare"
},
"editing": {
"editor_type": {
"fixed": "Editor cu bară fixă (uneltele de editare vor apărea în tab-ul „Formatare” din panglică)",
"floating": "Editor cu bară flotantă (uneltele de editare vor apărea lângă cursor)",
"label": "Bară de formatare"
}
},
"editor": {
"title": "Editor"
}
}

View File

@@ -65,7 +65,8 @@ const ALLOWED_OPTIONS = new Set([
'promotedAttributesOpenInRibbon',
'editedNotesOpenInRibbon',
'locale',
'firstDayOfWeek'
'firstDayOfWeek',
'textNoteEditorType'
]);
function getOptions() {
@@ -152,6 +153,10 @@ function getSupportedLocales() {
"id": "en",
"name": "English"
},
{
"id": "de",
"name": "Deutsch"
},
{
"id": "es",
"name": "Español"

View File

@@ -8,7 +8,7 @@ import fs from "fs";
import themeNames from "./code_block_theme_names.json" with { type: "json" }
import { t } from "i18next";
import { join } from "path";
import { getResourceDir } from "./utils.js";
import utils from "./utils.js";
import env from "./env.js";
/**
@@ -31,8 +31,7 @@ interface ColorTheme {
* @returns the supported themes, grouped.
*/
export function listSyntaxHighlightingThemes() {
const stylesDir = (env.isDev() ? "node_modules/@highlightjs/cdn-assets/styles" : "styles");
const path = join(getResourceDir(), stylesDir);
const path = join(utils.getResourceDir(), getStylesDirectory());
const systemThemes = readThemesFromFileSystem(path);
return {
@@ -46,6 +45,14 @@ export function listSyntaxHighlightingThemes() {
}
}
function getStylesDirectory() {
if (utils.isElectron() && !env.isDev()) {
return "styles";
}
return "node_modules/@highlightjs/cdn-assets/styles";
}
/**
* Reads all the predefined themes by listing all minified CSSes from a given directory.
*

View File

@@ -420,6 +420,12 @@ function getDefaultKeyboardActions() {
separator: t("keyboard_actions.ribbon-tabs")
},
{
actionName: "toggleRibbonTabClassicEditor",
defaultShortcuts: [],
description: t("keyboard_actions.toggle-classic-editor-toolbar"),
scope: "window"
},
{
actionName: "toggleRibbonTabBasicProperties",
defaultShortcuts: [],

View File

@@ -131,7 +131,10 @@ const defaultOptions: DefaultOption[] = [
return "default:stackoverflow-dark";
}
}, isSynced: false },
{ name: "codeBlockWordWrap", value: "false", isSynced: true }
{ name: "codeBlockWordWrap", value: "false", isSynced: true },
// Text note configuration
{ name: "textNoteEditorType", value: "ckeditor-balloon", isSynced: true }
];
/**

View File

@@ -364,5 +364,6 @@ export default {
normalize,
hashedBlobId,
toMap,
isString
isString,
getResourceDir
};

View File

@@ -111,13 +111,9 @@ async function createMainWindow(app: App) {
}
function configureWebContents(webContents: WebContents, spellcheckEnabled: boolean) {
if (!mainWindow) {
return;
}
remoteMain.enable(webContents);
mainWindow.webContents.setWindowOpenHandler((details) => {
webContents.setWindowOpenHandler((details) => {
async function openExternal() {
(await import('electron')).shell.openExternal(details.url);
}

196
translations/de/server.json Normal file
View File

@@ -0,0 +1,196 @@
{
"keyboard_actions": {
"open-jump-to-note-dialog": "Öffne das Dialogfeld \"Zu Notiz springen\"",
"search-in-subtree": "Suche nach Notizen im Unterbaum der aktuellen Notiz",
"expand-subtree": "Erweitere den Unterbaum der aktuellen Notiz",
"collapse-tree": "Kollabiere den gesamten Notizbaum",
"collapse-subtree": "Kollabiere den Unterbaum der aktuellen Notiz",
"sort-child-notes": "Sortiere untergeordnete Notizen",
"creating-and-moving-notes": "Erstellen und Verschieben von Notizen",
"create-note-into-inbox": "Erstelle eine Notiz im Posteingang (falls definiert) oder in der Tagesnotiz",
"delete-note": "Notiz löschen",
"move-note-up": "Notiz nach oben verschieben",
"move-note-down": "Notiz nach unten verschieben",
"move-note-up-in-hierarchy": "Notiz in der Hierarchie nach oben verschieben",
"move-note-down-in-hierarchy": "Notiz in der Hierarchie nach unten verschieben",
"edit-note-title": "Springe vom Baum zur Notiz-Detailansicht und bearbeite den Titel",
"edit-branch-prefix": "Zeige Dialog zum Bearbeiten des Zweigpräfixes",
"note-clipboard": "Notiz-Zwischenablage",
"copy-notes-to-clipboard": "Kopiere ausgewählte Notizen in die Zwischenablage",
"paste-notes-from-clipboard": "Füge Notizen aus der Zwischenablage in die aktive Notiz ein",
"cut-notes-to-clipboard": "Schneide ausgewählte Notizen in die Zwischenablage",
"select-all-notes-in-parent": "Wähle alle Notizen der aktuellen Notizenebene",
"add-note-above-to-the-selection": "Füge eine Notiz oberhalb zur Auswahl hinzu",
"add-note-below-to-selection": "Füge eine Notiz unterhalb zur Auswahl hinzu",
"duplicate-subtree": "Dupliziere den Unterbaum",
"tabs-and-windows": "Tabs & Fenster",
"open-new-tab": "Öffne einen neuen Tab",
"close-active-tab": "Schließe den aktiven Tab",
"reopen-last-tab": "Öffne den zuletzt geschlossenen Tab",
"activate-next-tab": "Aktiviere den Tab rechts",
"activate-previous-tab": "Aktiviere den Tab links",
"open-new-window": "Öffne ein neues leeres Fenster",
"toggle-tray": "Zeige/verstecke die Anwendung im Systemtray",
"first-tab": "Aktiviere den ersten Tab in der Liste",
"second-tab": "Aktiviere den zweiten Tab in der Liste",
"third-tab": "Aktiviere den dritten Tab in der Liste",
"fourth-tab": "Aktiviere den vierten Tab in der Liste",
"fifth-tab": "Aktiviere den fünften Tab in der Liste",
"sixth-tab": "Aktiviere den sechsten Tab in der Liste",
"seventh-tab": "Aktiviere den siebten Tab in der Liste",
"eight-tab": "Aktiviere den achten Tab in der Liste",
"ninth-tab": "Aktiviere den neunten Tab in der Liste",
"last-tab": "Aktiviere den letzten Tab in der Liste",
"dialogs": "Dialoge",
"show-note-source": "Zeige das Dialogfeld der Notizquelle",
"show-options": "Zeige das Dialogfeld der Optionen",
"show-revisions": "Zeige das Dialogfeld der Notizrevisionen",
"show-recent-changes": "Zeige das Dialogfeld der letzten Änderungen",
"show-sql-console": "Zeige das Dialogfeld der SQL-Konsole",
"show-backend-log": "Zeige das Dialogfeld des Backend-Logs",
"text-note-operations": "Textnotizoperationen",
"add-link-to-text": "Öffne das Dialogfeld zum Hinzufügen eines Links zum Text",
"follow-link-under-cursor": "Folge dem Link, unter dem sich der Cursor befindet",
"insert-date-and-time-to-text": "Füge das aktuelle Datum und die Uhrzeit in den Text ein",
"paste-markdown-into-text": "Füge Markdown aus der Zwischenablage in die Textnotiz ein",
"cut-into-note": "Schneide die Auswahl aus der aktuellen Notiz und erstelle eine Unternotiz mit dem ausgewählten Text",
"add-include-note-to-text": "Öffne das Dialogfeld zum Einfügen einer Notiz",
"edit-readonly-note": "Bearbeite eine schreibgeschützte Notiz",
"attributes-labels-and-relations": "Attribute (Labels & Beziehungen)",
"add-new-label": "Erstelle ein neues Label",
"create-new-relation": "Erstelle eine neue Beziehung",
"ribbon-tabs": "Ribbon-Tabs",
"toggle-basic-properties": "Schalte die Grundattribute um",
"toggle-file-properties": "Schalte die Dateiattribute um",
"toggle-image-properties": "Schalte die Bildattribute um",
"toggle-owned-attributes": "Schalte eigene Attribute um",
"toggle-inherited-attributes": "Schalte vererbte Attribute um",
"toggle-promoted-attributes": "Schalte beworbene Attribute um",
"toggle-link-map": "Schalte die Link-Karte um",
"toggle-note-info": "Schalte Notizinformationen um",
"toggle-note-paths": "Schalte Notizpfade um",
"toggle-similar-notes": "Schalte ähnliche Notizen um",
"other": "Andere",
"toggle-right-pane": "Schalte die Anzeige des rechten Fensters um, das Inhaltsverzeichnis und Markierungen enthält",
"print-active-note": "Drucke die aktive Notiz",
"open-note-externally": "Öffne die Notiz als Datei mit der Standardanwendung",
"render-active-note": "Render (erneut rendern) der aktiven Notiz",
"run-active-note": "Führe den aktiven JavaScript (Frontend/Backend) Notizcode aus",
"toggle-note-hoisting": "Schaltet das Hoisting der aktiven Notiz um",
"unhoist": "Von überall ent-hoisten",
"reload-frontend-app": "Lade die Frontend-App neu",
"open-dev-tools": "Öffne die Entwicklertools",
"toggle-left-note-tree-panel": "Schalte das linke Notizbaum-Panel um",
"toggle-full-screen": "Schalte den Vollbildmodus um",
"zoom-out": "Zoome heraus",
"zoom-in": "Zoome hinein",
"note-navigation": "Notiznavigation",
"reset-zoom-level": "Setze den Zoomlevel zurück",
"copy-without-formatting": "Kopiere den ausgewählten Text ohne Formatierung",
"force-save-revision": "Erzwinge das Erstellen / Speichern einer neuen Notizrevision der aktiven Notiz",
"show-help": "Zeige die eingebaute Hilfe / Cheat-Sheet",
"toggle-book-properties": "Schalte die Buch-Eigenschaften um"
},
"login": {
"title": "Anmeldung",
"heading": "Trilium Anmeldung",
"incorrect-password": "Das Passwort ist falsch. Bitte versuche es erneut.",
"password": "Passwort",
"remember-me": "Erinnere dich an mich",
"button": "Anmelden"
},
"set_password": {
"heading": "Passwort festlegen",
"description": "Bevor du Trilium im Web verwenden kannst, musst du zuerst ein Passwort festlegen. Du wirst dieses Passwort dann zur Anmeldung verwenden.",
"password": "Passwort",
"password-confirmation": "Passwortbestätigung",
"button": "Passwort festlegen"
},
"javascript-required": "Trilium erfordert, dass JavaScript aktiviert ist.",
"setup": {
"heading": "TriliumNext Notizen Setup",
"new-document": "Ich bin ein neuer Benutzer und möchte ein neues Trilium-Dokument für meine Notizen erstellen",
"sync-from-desktop": "Ich habe bereits eine Desktop-Instanz und möchte die Synchronisierung damit einrichten",
"sync-from-server": "Ich habe bereits eine Server-Instanz und möchte die Synchronisierung damit einrichten",
"next": "Weiter",
"init-in-progress": "Dokumenteninitialisierung läuft",
"redirecting": "Du wirst in Kürze zur Anwendung weitergeleitet.",
"title": "Setup"
},
"setup_sync-from-desktop": {
"heading": "Synchronisation vom Desktop",
"description": "Dieses Setup muss von der Desktop-Instanz aus initiiert werden:",
"step1": "Öffne deine TriliumNext Notes Desktop-Instanz.",
"step2": "Klicke im Trilium-Menü auf Optionen.",
"step3": "Klicke auf die Kategorie Synchronisation.",
"step4": "Ändere die Server-Instanzadresse auf: {{- host}} und klicke auf Speichern.",
"step5": "Klicke auf den Button \"Test-Synchronisation\", um zu überprüfen, ob die Verbindung erfolgreich ist.",
"step6": "Sobald du diese Schritte abgeschlossen hast, klicke auf {{- link}}.",
"step6-here": "hier"
},
"setup_sync-from-server": {
"heading": "Synchronisation vom Server",
"instructions": "Bitte gib unten die Trilium-Server-Adresse und die Zugangsdaten ein. Dies wird das gesamte Trilium-Dokument vom Server herunterladen und die Synchronisation einrichten. Je nach Dokumentgröße und Verbindungsgeschwindigkeit kann dies eine Weile dauern.",
"server-host": "Trilium Server-Adresse",
"server-host-placeholder": "https://<hostname>:<port>",
"proxy-server": "Proxy-Server (optional)",
"proxy-server-placeholder": "https://<hostname>:<port>",
"note": "Hinweis:",
"proxy-instruction": "Wenn du die Proxy-Einstellung leer lässt, wird der System-Proxy verwendet (nur für die Desktop-Anwendung)",
"password": "Passwort",
"password-placeholder": "Passwort",
"back": "Zurück",
"finish-setup": "Setup abschließen"
},
"setup_sync-in-progress": {
"heading": "Synchronisation läuft",
"successful": "Die Synchronisation wurde erfolgreich eingerichtet. Es wird eine Weile dauern, bis die erste Synchronisation abgeschlossen ist. Sobald dies erledigt ist, wirst du zur Anmeldeseite weitergeleitet.",
"outstanding-items": "Ausstehende Synchronisationselemente:",
"outstanding-items-default": "N/A"
},
"share_404": {
"title": "Nicht gefunden",
"heading": "Nicht gefunden"
},
"share_page": {
"parent": "Eltern:",
"clipped-from": "Diese Notiz wurde ursprünglich von {{- url}} ausgeschnitten",
"child-notes": "Untergeordnete Notizen:",
"no-content": "Diese Notiz hat keinen Inhalt."
},
"weekdays": {
"monday": "Montag",
"tuesday": "Dienstag",
"wednesday": "Mittwoch",
"thursday": "Donnerstag",
"friday": "Freitag",
"saturday": "Samstag",
"sunday": "Sonntag"
},
"months": {
"january": "Januar",
"february": "Februar",
"march": "März",
"april": "April",
"may": "Mai",
"june": "Juni",
"july": "Juli",
"august": "August",
"september": "September",
"october": "Oktober",
"november": "November",
"december": "Dezember"
},
"special_notes": {
"search_prefix": "Suche:"
},
"code_block": {
"theme_none": "Keine Syntax-Hervorhebung",
"theme_group_light": "Helle Themen",
"theme_group_dark": "Dunkle Themen"
},
"test_sync": {
"not-configured": "Der Synchronisations-Server-Host ist nicht konfiguriert. Bitte konfiguriere zuerst die Synchronisation.",
"successful": "Die Server-Verbindung wurde erfolgreich hergestellt, die Synchronisation wurde gestartet."
}
}

View File

@@ -89,7 +89,8 @@
"copy-without-formatting": "Copy selected text without formatting",
"force-save-revision": "Force creating / saving new note revision of the active note",
"show-help": "Shows built-in Help / cheatsheet",
"toggle-book-properties": "Toggle Book Properties"
"toggle-book-properties": "Toggle Book Properties",
"toggle-classic-editor-toolbar": "Toggle the Formatting tab for the editor with fixed toolbar"
},
"login": {
"title": "Login",

View File

@@ -89,7 +89,8 @@
"copy-without-formatting": "Copiar el texto seleccionado sin formatear",
"force-save-revision": "Forzar la creación/guardado de una nueva revisión de nota de la nota activa",
"show-help": "Muestra ayuda/hoja de referencia integrada",
"toggle-book-properties": "Alternar propiedades del libro"
"toggle-book-properties": "Alternar propiedades del libro",
"toggle-classic-editor-toolbar": "Alternar la pestaña de formato por el editor con barra de herramientas fija"
},
"login": {
"title": "Iniciar sesión",

View File

@@ -66,7 +66,7 @@
"toggle-owned-attributes": "Afficher/masquer les Attributs propres",
"toggle-inherited-attributes": "Afficher/masquer les Attributs hérités",
"toggle-promoted-attributes": "Afficher/masquer les Attributs promus",
"toggle-link-map": "Afficher/masquer la Carte des liens",
"toggle-link-map": "Afficher/masquer la Carte de la note",
"toggle-note-info": "Afficher/masquer les Informations de la note",
"toggle-note-paths": "Afficher/masquer les Emplacements de la note",
"toggle-similar-notes": "Afficher/masquer les Notes similaires",
@@ -157,5 +157,31 @@
"clipped-from": "Cette note a été initialement extraite de {{- url}}",
"child-notes": "Notes enfants :",
"no-content": "Cette note n'a aucun contenu."
},
"weekdays": {
"monday": "Lundi",
"tuesday": "Mardi",
"wednesday": "Mercredi",
"thursday": "Jeudi",
"friday": "Vendredi",
"saturday": "Samedi",
"sunday": "Dimanche"
},
"months": {
"january": "Janvier",
"february": "Février",
"march": "Mars",
"april": "Avril",
"may": "Mai",
"june": "Juin",
"july": "Juillet",
"august": "Août",
"september": "Septembre",
"october": "Octobre",
"november": "Novembre",
"december": "Décembre"
},
"special_notes": {
"search_prefix": "Recherche :"
}
}

View File

@@ -89,7 +89,8 @@
"toggle-tray": "Afișează/ascunde aplicația din tray-ul de sistem",
"unhoist": "Defocalizează complet",
"zoom-in": "Mărește zoom-ul",
"zoom-out": "Micșorează zoom-ul"
"zoom-out": "Micșorează zoom-ul",
"toggle-classic-editor-toolbar": "Comută tab-ul „Formatare” pentru editorul cu bară fixă"
},
"login": {
"button": "Autentifică",