Compare commits

..

1 Commits

Author SHA1 Message Date
perf3ct
66074ddbc9 fix(docs): try to fix more docs links... 2025-09-07 22:30:10 -07:00
831 changed files with 17115 additions and 43314 deletions

View File

@@ -1,6 +1,6 @@
root = true
[*.{js,ts,tsx}]
[*.{js,ts,.tsx}]
charset = utf-8
end_of_line = lf
indent_size = 4

View File

@@ -74,7 +74,7 @@ runs:
- name: Update build info
shell: ${{ inputs.shell }}
run: pnpm run chore:update-build-info
run: npm run chore:update-build-info
# Critical debugging configuration
- name: Run electron-forge build with enhanced logging
@@ -86,7 +86,6 @@ runs:
APPLE_ID_PASSWORD: ${{ env.APPLE_ID_PASSWORD }}
WINDOWS_SIGN_EXECUTABLE: ${{ env.WINDOWS_SIGN_EXECUTABLE }}
TRILIUM_ARTIFACT_NAME_HINT: TriliumNotes-${{ github.ref_name }}-${{ inputs.os }}-${{ inputs.arch }}
TARGET_ARCH: ${{ inputs.arch }}
run: pnpm run --filter desktop electron-forge:make --arch=${{ inputs.arch }} --platform=${{ inputs.forge_platform }}
# Add DMG signing step

View File

@@ -10,7 +10,7 @@ runs:
steps:
- uses: pnpm/action-setup@v4
- name: Set up node & dependencies
uses: actions/setup-node@v6
uses: actions/setup-node@v5
with:
node-version: 22
cache: "pnpm"

View File

@@ -1,103 +0,0 @@
name: "Deploy to Cloudflare Pages"
description: "Deploys to Cloudflare Pages on either a temporary branch with preview comment, or on the production version if on the main branch."
inputs:
project_name:
description: "CloudFlare Pages project name"
comment_body:
description: "The message to display when deployment is ready"
default: "Deployment is ready."
required: false
production_url:
description: "The URL to mention as the production URL."
required: true
deploy_dir:
description: "The directory from which to deploy."
required: true
cloudflare_api_token:
description: "The Cloudflare API token to use for deployment."
required: true
cloudflare_account_id:
description: "The Cloudflare account ID to use for deployment."
required: true
github_token:
description: "The GitHub token to use for posting PR comments."
required: true
runs:
using: composite
steps:
# Install wrangler globally to avoid workspace issues
- name: Install Wrangler
shell: bash
run: npm install -g wrangler
# Deploy using Wrangler (use pre-installed wrangler)
- name: Deploy to Cloudflare Pages
id: deploy
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ inputs.cloudflare_api_token }}
accountId: ${{ inputs.cloudflare_account_id }}
command: pages deploy ${{ inputs.deploy_dir }} --project-name=${{ inputs.project_name}} --branch=${{ github.ref_name }}
wranglerVersion: '' # Use pre-installed version
# Deploy preview for PRs
- name: Deploy Preview to Cloudflare Pages
id: preview-deployment
if: github.event_name == 'pull_request'
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ inputs.cloudflare_api_token }}
accountId: ${{ inputs.cloudflare_account_id }}
command: pages deploy ${{ inputs.deploy_dir }} --project-name=${{ inputs.project_name}} --branch=pr-${{ github.event.pull_request.number }}
wranglerVersion: '' # Use pre-installed version
# Post deployment URL as PR comment
- name: Comment PR with Preview URL
if: github.event_name == 'pull_request'
uses: actions/github-script@v8
env:
COMMENT_BODY: ${{ inputs.comment_body }}
PRODUCTION_URL: ${{ inputs.production_url }}
PROJECT_NAME: ${{ inputs.project_name }}
with:
github-token: ${{ inputs.github_token }}
script: |
const prNumber = context.issue.number;
// Construct preview URL based on Cloudflare Pages pattern
const projectName = process.env.PROJECT_NAME;
const previewUrl = `https://pr-${prNumber}.${projectName}.pages.dev`;
// Check if we already commented
const comments = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber
});
const customMessage = process.env.COMMENT_BODY;
const botComment = comments.data.find(comment =>
comment.user.type === 'Bot' &&
comment.body.includes(customMessage)
);
const mainUrl = process.env.PRODUCTION_URL;
const commentBody = `${customMessage}!\n\n🔗 Preview URL: ${previewUrl}\n📖 Production URL: ${mainUrl}\n\n✅ All checks passed\n\n_This preview will be updated automatically with new commits._`;
if (botComment) {
// Update existing comment
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: commentBody
});
} else {
// Create new comment
await github.rest.issues.createComment({
issue_number: prNumber,
owner: context.repo.owner,
repo: context.repo.repo,
body: commentBody
});
}

View File

@@ -67,7 +67,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
@@ -95,6 +95,6 @@ jobs:
exit 1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"

View File

@@ -16,10 +16,11 @@ on:
- 'requirements-docs.txt'
- '.github/workflows/deploy-docs.yml'
- 'scripts/fix-mkdocs-structure.ts'
- 'validate-docs-links.ts'
# Allow manual triggering from Actions tab
workflow_dispatch:
# Run on pull requests for preview deployments
pull_request:
branches:
@@ -32,61 +33,62 @@ on:
- 'requirements-docs.txt'
- '.github/workflows/deploy-docs.yml'
- 'scripts/fix-mkdocs-structure.ts'
- 'validate-docs-links.ts'
jobs:
build-and-deploy:
name: Build and Deploy MkDocs
runs-on: ubuntu-latest
timeout-minutes: 10
# Required permissions for deployment
permissions:
contents: read
deployments: write
pull-requests: write # For PR preview comments
id-token: write # For OIDC authentication (if needed)
steps:
- name: Checkout Repository
uses: actions/checkout@v5
with:
fetch-depth: 0 # Fetch all history for git info and mkdocs-git-revision-date plugin
- name: Setup Python
uses: actions/setup-python@v6
with:
python-version: '3.14'
python-version: '3.13'
cache: 'pip'
cache-dependency-path: 'requirements-docs.txt'
- name: Install MkDocs and Dependencies
run: |
pip install --upgrade pip
pip install -r requirements-docs.txt
env:
PIP_DISABLE_PIP_VERSION_CHECK: 1
# Setup pnpm before fixing docs structure
- name: Setup pnpm
uses: pnpm/action-setup@v4
# Setup Node.js with pnpm
- name: Setup Node.js
uses: actions/setup-node@v6
uses: actions/setup-node@v5
with:
node-version: '22'
cache: 'pnpm'
# Install Node.js dependencies for the TypeScript script
- name: Install Dependencies
run: |
pnpm install --frozen-lockfile
- name: Fix Documentation Structure
run: |
# Fix duplicate navigation entries by moving overview pages to index.md
pnpm run chore:fix-mkdocs-structure
- name: Build MkDocs Site
run: |
# Build with strict mode but allow expected warnings
@@ -102,12 +104,7 @@ jobs:
exit $EXIT_CODE
fi
}
- name: Fix HTML Links
run: |
# Remove .md extensions from links in generated HTML
pnpm tsx ./scripts/fix-html-links.ts site
- name: Validate Built Site
run: |
# Basic validation that important files exist
@@ -115,15 +112,79 @@ jobs:
test -f site/sitemap.xml || (echo "ERROR: site/sitemap.xml not found" && exit 1)
test -d site/assets || (echo "ERROR: site/assets directory not found" && exit 1)
echo "✅ Site validation passed"
- name: Deploy
uses: ./.github/actions/deploy-to-cloudflare-pages
if: github.repository == ${{ vars.REPO_MAIN }}
- name: Validate Documentation Links
run: |
# Run the TypeScript link validation script
pnpm tsx validate-docs-links.ts
# Install wrangler globally to avoid workspace issues
- name: Install Wrangler
run: |
npm install -g wrangler
# Deploy using Wrangler (use pre-installed wrangler)
- name: Deploy to Cloudflare Pages
id: deploy
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
uses: cloudflare/wrangler-action@v3
with:
project_name: "trilium-docs"
comment_body: "📚 Documentation preview is ready"
production_url: "https://docs.triliumnotes.org"
deploy_dir: "site"
cloudflare_api_token: ${{ secrets.CLOUDFLARE_API_TOKEN }}
cloudflare_account_id: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
github_token: ${{ secrets.GITHUB_TOKEN }}
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy site --project-name=trilium-docs --branch=${{ github.ref_name }}
wranglerVersion: '' # Use pre-installed version
# Deploy preview for PRs
- name: Deploy Preview to Cloudflare Pages
id: preview-deployment
if: github.event_name == 'pull_request'
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy site --project-name=trilium-docs --branch=pr-${{ github.event.pull_request.number }}
wranglerVersion: '' # Use pre-installed version
# Post deployment URL as PR comment
- name: Comment PR with Preview URL
if: github.event_name == 'pull_request'
uses: actions/github-script@v8
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const prNumber = context.issue.number;
// Construct preview URL based on Cloudflare Pages pattern
const previewUrl = `https://pr-${prNumber}.trilium-docs.pages.dev`;
const mainUrl = 'https://docs.triliumnotes.org';
// Check if we already commented
const comments = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber
});
const botComment = comments.data.find(comment =>
comment.user.type === 'Bot' &&
comment.body.includes('Documentation preview is ready')
);
const commentBody = `📚 Documentation preview is ready!\n\n🔗 Preview URL: ${previewUrl}\n📖 Production URL: ${mainUrl}\n\n✅ All checks passed\n\n_This preview will be updated automatically with new commits._`;
if (botComment) {
// Update existing comment
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: commentBody
});
} else {
// Create new comment
await github.rest.issues.createComment({
issue_number: prNumber,
owner: context.repo.owner,
repo: context.repo.repo,
body: commentBody
});
}

View File

@@ -28,7 +28,7 @@ jobs:
- uses: pnpm/action-setup@v4
- name: Set up node & dependencies
uses: actions/setup-node@v6
uses: actions/setup-node@v5
with:
node-version: 22
cache: "pnpm"

View File

@@ -44,7 +44,7 @@ jobs:
- uses: pnpm/action-setup@v4
- name: Set up node & dependencies
uses: actions/setup-node@v6
uses: actions/setup-node@v5
with:
node-version: 22
cache: "pnpm"
@@ -144,7 +144,7 @@ jobs:
uses: actions/checkout@v5
- uses: pnpm/action-setup@v4
- name: Set up node & dependencies
uses: actions/setup-node@v6
uses: actions/setup-node@v5
with:
node-version: 22
cache: 'pnpm'
@@ -152,12 +152,12 @@ jobs:
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Update build info
run: pnpm run chore:update-build-info
- name: Run the TypeScript build
run: pnpm run server:build
- name: Update build info
run: pnpm run chore:update-build-info
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
@@ -211,7 +211,7 @@ jobs:
- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digests-${{ env.PLATFORM_PAIR }}-${{ matrix.dockerfile }}
name: digests-${{ env.PLATFORM_PAIR }}
path: /tmp/digests/*
if-no-files-found: error
retention-days: 1

View File

@@ -19,6 +19,7 @@ concurrency:
cancel-in-progress: true
env:
GITHUB_UPLOAD_URL: https://uploads.github.com/repos/TriliumNext/Notes/releases/179589950/assets{?name,label}
GITHUB_RELEASE_ID: 179589950
permissions:
@@ -50,7 +51,7 @@ jobs:
- uses: actions/checkout@v5
- uses: pnpm/action-setup@v4
- name: Set up node & dependencies
uses: actions/setup-node@v6
uses: actions/setup-node@v5
with:
node-version: 22
cache: 'pnpm'
@@ -77,7 +78,7 @@ jobs:
GPG_SIGNING_KEY: ${{ secrets.GPG_SIGN_KEY }}
- name: Publish release
uses: softprops/action-gh-release@v2.4.1
uses: softprops/action-gh-release@v2.3.3
if: ${{ github.event_name != 'pull_request' }}
with:
make_latest: false
@@ -118,7 +119,7 @@ jobs:
arch: ${{ matrix.arch }}
- name: Publish release
uses: softprops/action-gh-release@v2.4.1
uses: softprops/action-gh-release@v2.3.3
if: ${{ github.event_name != 'pull_request' }}
with:
make_latest: false

View File

@@ -4,8 +4,6 @@ on:
push:
branches:
- main
paths-ignore:
- "apps/website/**"
pull_request:
permissions:
@@ -22,7 +20,7 @@ jobs:
fetch-depth: 0
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v6
- uses: actions/setup-node@v5
with:
node-version: 22
cache: 'pnpm'

View File

@@ -30,25 +30,12 @@ jobs:
image: win-signing
shell: cmd
forge_platform: win32
# Exclude ARM64 Linux from default matrix to use native runner
exclude:
- arch: arm64
os:
name: linux
# Add ARM64 Linux with native ubuntu-24.04-arm runner for better-sqlite3 compatibility
include:
- arch: arm64
os:
name: linux
image: ubuntu-24.04-arm
shell: bash
forge_platform: linux
runs-on: ${{ matrix.os.image }}
steps:
- uses: actions/checkout@v5
- uses: pnpm/action-setup@v4
- name: Set up node & dependencies
uses: actions/setup-node@v6
uses: actions/setup-node@v5
with:
node-version: 22
cache: 'pnpm'
@@ -127,7 +114,7 @@ jobs:
path: upload
- name: Publish stable release
uses: softprops/action-gh-release@v2.4.1
uses: softprops/action-gh-release@v2.3.3
with:
draft: false
body_path: docs/Release Notes/Release Notes/${{ github.ref_name }}.md

View File

@@ -1,51 +0,0 @@
name: Deploy website
on:
push:
branches:
- main
paths:
- "apps/website/**"
pull_request:
paths:
- "apps/website/**"
release:
types: [ released ]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
name: Build & deploy website
permissions:
contents: read
deployments: write
pull-requests: write # For PR preview comments
steps:
- uses: actions/checkout@v5
- uses: pnpm/action-setup@v4
- name: Set up node & dependencies
uses: actions/setup-node@v6
with:
node-version: 22
cache: "pnpm"
- name: Install dependencies
run: pnpm install --filter website --frozen-lockfile
- name: Build the website
run: pnpm website:build
- name: Deploy
uses: ./.github/actions/deploy-to-cloudflare-pages
with:
project_name: "trilium-homepage"
comment_body: "📚 Website preview is ready"
production_url: "https://triliumnotes.org"
deploy_dir: "apps/website/dist"
cloudflare_api_token: ${{ secrets.CLOUDFLARE_API_TOKEN }}
cloudflare_account_id: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
github_token: ${{ secrets.GITHUB_TOKEN }}

2
.nvmrc
View File

@@ -1 +1 @@
22.20.0
22.19.0

View File

@@ -14,7 +14,6 @@ usageMatchRegex:
# the `{key}` will be placed by a proper keypath matching regex,
# you can ignore it and use your own matching rules as well
- "[^\\w\\d]t\\(['\"`]({key})['\"`]"
- <Trans\s*i18nKey="({key})"[^>]*>
# A RegEx to set a custom scope range. This scope will be used as a prefix when detecting keys
# and works like how the i18next framework identifies the namespace scope from the

View File

@@ -5,8 +5,7 @@
"i18n-ally.keystyle": "nested",
"i18n-ally.localesPaths": [
"apps/server/src/assets/translations",
"apps/client/src/translations",
"apps/website/public/translations"
"apps/client/src/translations"
],
"npm.exclude": [
"**/dist",

View File

@@ -1,14 +1,3 @@
<div align="center">
<sup>Special thanks to:</sup><br />
<a href="https://go.warp.dev/Trilium" target="_blank">
<img alt="Warp sponsorship" width="400" src="https://github.com/warpdotdev/brand-assets/blob/main/Github/Sponsor/Warp-Github-LG-03.png"><br />
Warp, built for coding with multiple AI agents<br />
</a>
<sup>Available for macOS, Linux and Windows</sup>
</div>
<hr />
# Trilium Notes
![GitHub Sponsors](https://img.shields.io/github/sponsors/eliandoran) ![LiberaPay patrons](https://img.shields.io/liberapay/patrons/ElianDoran)
@@ -16,7 +5,7 @@
![GitHub Downloads (all assets, all releases)](https://img.shields.io/github/downloads/triliumnext/trilium/total)
[![RelativeCI](https://badges.relative-ci.com/badges/Di5q7dz9daNDZ9UXi0Bp?branch=develop)](https://app.relative-ci.com/projects/Di5q7dz9daNDZ9UXi0Bp) [![Translation status](https://hosted.weblate.org/widget/trilium/svg-badge.svg)](https://hosted.weblate.org/engage/trilium/)
[English](./README.md) | [Chinese (Simplified)](./docs/README-ZH_CN.md) | [Chinese (Traditional)](./docs/README-ZH_TW.md) | [Russian](./docs/README-ru.md) | [Japanese](./docs/README-ja.md) | [Italian](./docs/README-it.md) | [Spanish](./docs/README-es.md)
[English](./README.md) | [Chinese (Simplified)](./docs/README-ZH_CN.md) | [Chinese (Traditional)](./docs/README-ZH_TW.md) | [Russian](./docs/README.ru.md) | [Japanese](./docs/README.ja.md) | [Italian](./docs/README.it.md) | [Spanish](./docs/README.es.md)
Trilium Notes is a free and open-source, cross-platform hierarchical note taking application with focus on building large personal knowledge bases.
@@ -24,27 +13,6 @@ See [screenshots](https://triliumnext.github.io/Docs/Wiki/screenshot-tour) for q
<a href="https://triliumnext.github.io/Docs/Wiki/screenshot-tour"><img src="./docs/app.png" alt="Trilium Screenshot" width="1000"></a>
## ⏬ Download
- [Latest release](https://github.com/TriliumNext/Trilium/releases/latest) stable version, recommended for most users.
- [Nightly build](https://github.com/TriliumNext/Trilium/releases/tag/nightly) unstable development version, updated daily with the latest features and fixes.
## 📚 Documentation
**Visit our comprehensive documentation at [docs.triliumnotes.org](https://docs.triliumnotes.org/)**
Our documentation is available in multiple formats:
- **Online Documentation**: Browse the full documentation at [docs.triliumnotes.org](https://docs.triliumnotes.org/)
- **In-App Help**: Press `F1` within Trilium to access the same documentation directly in the application
- **GitHub**: Navigate through the [User Guide](./docs/User%20Guide/User%20Guide/) in this repository
### Quick Links
- [Getting Started Guide](https://docs.triliumnotes.org/)
- [Installation Instructions](./docs/User%20Guide/User%20Guide/Installation%20&%20Setup/Server%20Installation.md)
- [Docker Setup](./docs/User%20Guide/User%20Guide/Installation%20&%20Setup/Server%20Installation/1.%20Installing%20the%20server/Using%20Docker.md)
- [Upgrading TriliumNext](./docs/User%20Guide/User%20Guide/Installation%20%26%20Setup/Upgrading%20TriliumNext.md)
- [Basic Concepts and Features](./docs/User%20Guide/User%20Guide/Basic%20Concepts%20and%20Features/Notes.md)
- [Patterns of Personal Knowledge Base](https://triliumnext.github.io/Docs/Wiki/patterns-of-personal-knowledge)
## 🎁 Features
* Notes can be arranged into arbitrarily deep tree. Single note can be placed into multiple places in the tree (see [cloning](https://triliumnext.github.io/Docs/Wiki/cloning-notes))
@@ -88,6 +56,19 @@ There are no special migration steps to migrate from a zadam/Trilium instance to
Versions up to and including [v0.90.4](https://github.com/TriliumNext/Trilium/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/Trilium have their sync versions incremented which prevents direct migration.
## 📖 Documentation
We're currently in the progress of moving the documentation to in-app (hit the `F1` key within Trilium). As a result, there may be some missing parts until we've completed the migration. If you'd prefer to navigate through the documentation within GitHub, you can navigate the [User Guide](./docs/User%20Guide/User%20Guide/) documentation.
Below are some quick links for your convenience to navigate the documentation:
- [Server installation](./docs/User%20Guide/User%20Guide/Installation%20&%20Setup/Server%20Installation.md)
- [Docker installation](./docs/User%20Guide/User%20Guide/Installation%20&%20Setup/Server%20Installation/1.%20Installing%20the%20server/Using%20Docker.md)
- [Upgrading TriliumNext](./docs/User%20Guide/User%20Guide/Installation%20%26%20Setup/Upgrading%20TriliumNext.md)
- [Concepts and Features - Note](./docs/User%20Guide/User%20Guide/Basic%20Concepts%20and%20Features/Notes.md)
- [Patterns of personal knowledge base](https://triliumnext.github.io/Docs/Wiki/patterns-of-personal-knowledge)
Until we finish reorganizing the documentation, you may also want to [browse the old documentation](https://triliumnext.github.io/Docs).
## 💬 Discuss with us
Feel free to join our official conversations. We would love to hear what features, suggestions, or issues you may have!
@@ -181,34 +162,16 @@ Please view the [documentation guide](https://github.com/TriliumNext/Trilium/blo
## 👏 Shoutouts
* [zadam](https://github.com/zadam) for the original concept and implementation of the application.
* [Sarah Hussein](https://github.com/Sarah-Hussein) for designing the application icon.
* [nriver](https://github.com/nriver) for his work on internationalization.
* [Thomas Frei](https://github.com/thfrei) for his original work on the Canvas.
* [antoniotejada](https://github.com/nriver) for the original syntax highlight widget.
* [Dosu](https://dosu.dev/) for providing us with the automated responses to GitHub issues and discussions.
* [Tabler Icons](https://tabler.io/icons) for the system tray icons.
Trilium would not be possible without the technologies behind it:
* [CKEditor 5](https://github.com/ckeditor/ckeditor5) - the visual editor behind text notes. We are grateful for being offered a set of the premium features.
* [CodeMirror](https://github.com/codemirror/CodeMirror) - code editor with support for huge amount of languages.
* [Excalidraw](https://github.com/excalidraw/excalidraw) - the infinite whiteboard used in Canvas notes.
* [Mind Elixir](https://github.com/SSShooter/mind-elixir-core) - providing the mind map functionality.
* [Leaflet](https://github.com/Leaflet/Leaflet) - for rendering geographical maps.
* [Tabulator](https://github.com/olifolkerd/tabulator) - for the interactive table used in collections.
* [FancyTree](https://github.com/mar10/fancytree) - feature-rich tree library without real competition.
* [jsPlumb](https://github.com/jsplumb/jsplumb) - visual connectivity library. Used in [relation maps](https://triliumnext.github.io/Docs/Wiki/relation-map.html) and [link maps](https://triliumnext.github.io/Docs/Wiki/note-map.html#link-map)
* [CKEditor 5](https://github.com/ckeditor/ckeditor5) - best WYSIWYG editor on the market, very interactive and listening team
* [FancyTree](https://github.com/mar10/fancytree) - very feature rich tree library without real competition. Trilium Notes would not be the same without it.
* [CodeMirror](https://github.com/codemirror/CodeMirror) - code editor with support for huge amount of languages
* [jsPlumb](https://github.com/jsplumb/jsplumb) - visual connectivity library without competition. Used in [relation maps](https://triliumnext.github.io/Docs/Wiki/relation-map.html) and [link maps](https://triliumnext.github.io/Docs/Wiki/note-map.html#link-map)
## 🤝 Support
Trilium is built and maintained with [hundreds of hours of work](https://github.com/TriliumNext/Trilium/graphs/commit-activity). Your support keeps it open-source, improves features, and covers costs such as hosting.
Consider supporting the main developer ([eliandoran](https://github.com/eliandoran)) of the application via:
- [GitHub Sponsors](https://github.com/sponsors/eliandoran)
- [PayPal](https://paypal.me/eliandoran)
- [Buy Me a Coffee](https://buymeacoffee.com/eliandoran)
Support for the TriliumNext organization will be possible in the near future. For now, you can:
- Support continued development on TriliumNext by supporting our developers: [eliandoran](https://github.com/sponsors/eliandoran) (See the [repository insights]([developers]([url](https://github.com/TriliumNext/trilium/graphs/contributors))) for a full list)
- Show a token of gratitude to the original Trilium developer ([zadam](https://github.com/sponsors/zadam)) via [PayPal](https://paypal.me/za4am) or Bitcoin (bitcoin:bc1qv3svjn40v89mnkre5vyvs2xw6y8phaltl385d2).
## 🔑 License

View File

@@ -35,22 +35,22 @@
"chore:generate-openapi": "tsx bin/generate-openapi.js"
},
"devDependencies": {
"@playwright/test": "1.56.1",
"@stylistic/eslint-plugin": "5.5.0",
"@playwright/test": "1.55.0",
"@stylistic/eslint-plugin": "5.3.1",
"@types/express": "5.0.3",
"@types/node": "22.18.11",
"@types/node": "22.18.1",
"@types/yargs": "17.0.33",
"@vitest/coverage-v8": "3.2.4",
"eslint": "9.38.0",
"eslint": "9.35.0",
"eslint-plugin-simple-import-sort": "12.1.1",
"esm": "3.2.25",
"jsdoc": "4.0.5",
"jsdoc": "4.0.4",
"lorem-ipsum": "2.0.8",
"rcedit": "4.0.1",
"rimraf": "6.0.1",
"tslib": "2.8.1",
"typedoc": "0.28.14",
"typedoc-plugin-missing-exports": "4.1.2"
"typedoc": "0.28.12",
"typedoc-plugin-missing-exports": "4.1.0"
},
"optionalDependencies": {
"appdmg": "0.6.6"

View File

@@ -1,3 +1,4 @@
import type child_process from "child_process";
import { describe, beforeAll, afterAll } from "vitest";
let etapiAuthToken: string | undefined;
@@ -11,6 +12,8 @@ type SpecDefinitionsFunc = () => void;
function describeEtapi(description: string, specDefinitions: SpecDefinitionsFunc): void {
describe(description, () => {
let appProcess: ReturnType<typeof child_process.spawn>;
beforeAll(async () => {});
afterAll(() => {});

View File

@@ -1,4 +1,5 @@
# The development license key for premium CKEditor features.
# Note: This key must only be used for the Trilium Notes project.
VITE_CKEDITOR_KEY=eyJhbGciOiJFUzI1NiJ9.eyJleHAiOjE3ODcyNzA0MDAsImp0aSI6IjkyMWE1MWNlLTliNDMtNGRlMC1iOTQwLTc5ZjM2MDBkYjg1NyIsImRpc3RyaWJ1dGlvbkNoYW5uZWwiOiJ0cmlsaXVtIiwiZmVhdHVyZXMiOlsiVFJJTElVTSJdLCJ2YyI6ImU4YzRhMjBkIn0.hny77p-U4-jTkoqbwPytrEar5ylGCWBN7Ez3SlB8i6_mJCBIeCSTOlVQk_JMiOEq3AGykUMHzWXzjdMFwgniOw
# Expires on: 2025-09-13
VITE_CKEDITOR_KEY=eyJhbGciOiJFUzI1NiJ9.eyJleHAiOjE3NTc3MjE1OTksImp0aSI6ImFiN2E0NjZmLWJlZGMtNDNiYy1iMzU4LTk0NGQ0YWJhY2I3ZiIsImRpc3RyaWJ1dGlvbkNoYW5uZWwiOlsic2giLCJkcnVwYWwiXSwid2hpdGVMYWJlbCI6dHJ1ZSwiZmVhdHVyZXMiOlsiRFJVUCIsIkNNVCIsIkRPIiwiRlAiLCJTQyIsIlRPQyIsIlRQTCIsIlBPRSIsIkNDIiwiTUYiLCJTRUUiLCJFQ0giLCJFSVMiXSwidmMiOiI1MzlkOWY5YyJ9.2rvKPql4hmukyXhEtWPZ8MLxKvzPIwzCdykO653g7IxRRZy2QJpeRszElZx9DakKYZKXekVRAwQKgHxwkgbE_w
VITE_CKEDITOR_ENABLE_INSPECTOR=false

View File

@@ -1,13 +1,13 @@
{
"name": "@triliumnext/client",
"version": "0.99.2",
"version": "0.98.1",
"description": "JQuery-based client for TriliumNext, used for both web and desktop (via Electron)",
"private": true,
"license": "AGPL-3.0-only",
"author": {
"name": "Trilium Notes Team",
"email": "contact@eliandoran.me",
"url": "https://github.com/TriliumNext/Trilium"
"url": "https://github.com/TriliumNext/Notes"
},
"scripts": {
"build": "cross-env NODE_OPTIONS=--max-old-space-size=4096 vite build",
@@ -15,7 +15,7 @@
"circular-deps": "dpdm -T src/**/*.ts --tree=false --warning=false --skip-dynamic-imports=circular"
},
"dependencies": {
"@eslint/js": "9.38.0",
"@eslint/js": "9.35.0",
"@excalidraw/excalidraw": "0.18.0",
"@fullcalendar/core": "6.1.19",
"@fullcalendar/daygrid": "6.1.19",
@@ -35,31 +35,29 @@
"autocomplete.js": "0.38.1",
"bootstrap": "5.3.8",
"boxicons": "2.1.4",
"color": "5.0.2",
"dayjs": "1.11.18",
"dayjs-plugin-utc": "0.1.2",
"debounce": "2.2.0",
"draggabilly": "3.0.0",
"force-graph": "1.51.0",
"globals": "16.4.0",
"i18next": "25.6.0",
"globals": "16.3.0",
"i18next": "25.5.2",
"i18next-http-backend": "3.0.2",
"jquery": "3.7.1",
"jquery.fancytree": "2.38.5",
"jsplumb": "2.15.6",
"katex": "0.16.25",
"katex": "0.16.22",
"knockout": "3.5.1",
"leaflet": "1.9.4",
"leaflet-gpx": "2.2.0",
"mark.js": "8.11.1",
"marked": "16.4.1",
"mermaid": "11.12.0",
"mind-elixir": "5.3.3",
"marked": "16.2.1",
"mermaid": "11.11.0",
"mind-elixir": "5.1.1",
"normalize.css": "8.0.1",
"panzoom": "9.4.3",
"preact": "10.27.2",
"react-i18next": "16.1.0",
"reveal.js": "5.2.1",
"preact": "10.27.1",
"react-i18next": "15.7.3",
"split.js": "1.6.5",
"svg-pan-zoom": "3.6.2",
"tabulator-tables": "6.3.1",
@@ -70,14 +68,13 @@
"@preact/preset-vite": "2.10.2",
"@types/bootstrap": "5.2.10",
"@types/jquery": "3.5.33",
"@types/leaflet": "1.9.21",
"@types/leaflet": "1.9.20",
"@types/leaflet-gpx": "1.3.8",
"@types/mark.js": "8.11.12",
"@types/reveal.js": "5.2.1",
"@types/tabulator-tables": "6.2.11",
"@types/tabulator-tables": "6.2.10",
"copy-webpack-plugin": "13.0.1",
"happy-dom": "20.0.7",
"happy-dom": "18.0.1",
"script-loader": "0.7.2",
"vite-plugin-static-copy": "3.1.4"
"vite-plugin-static-copy": "3.1.2"
}
}

View File

@@ -7,9 +7,6 @@
"display": "standalone",
"scope": "/",
"start_url": "/",
"display_override": [
"window-controls-overlay"
],
"icons": [
{
"src": "icon.png",

View File

@@ -116,7 +116,7 @@ export type CommandMappings = {
openedFileUpdated: CommandData & {
entityType: string;
entityId: string;
lastModifiedMs?: number;
lastModifiedMs: number;
filePath: string;
};
focusAndSelectTitle: CommandData & {
@@ -650,7 +650,7 @@ export class AppContext extends Component {
}
getComponentByEl(el: HTMLElement) {
return $(el).closest("[data-component-id]").prop("component");
return $(el).closest(".component").prop("component");
}
addBeforeUnloadListener(obj: BeforeUploadListener | (() => boolean)) {

View File

@@ -326,11 +326,9 @@ class NoteContext extends Component implements EventListener<"entitiesReloaded">
}
// Collections must always display a note list, even if no children.
if (note.type === "book") {
const viewType = note.getLabelValue("viewType") ?? "grid";
if (!["list", "grid"].includes(viewType)) {
return true;
}
const viewType = note.getLabelValue("viewType") ?? "grid";
if (!["list", "grid"].includes(viewType)) {
return true;
}
if (!note.hasChildren()) {
@@ -440,22 +438,4 @@ class NoteContext extends Component implements EventListener<"entitiesReloaded">
}
}
export function openInCurrentNoteContext(evt: MouseEvent | JQuery.ClickEvent | JQuery.MouseDownEvent | React.PointerEvent<HTMLCanvasElement> | null, notePath: string, viewScope?: ViewScope) {
const ntxId = $(evt?.target as Element)
.closest("[data-ntx-id]")
.attr("data-ntx-id");
const noteContext = ntxId ? appContext.tabManager.getNoteContextById(ntxId) : appContext.tabManager.getActiveContext();
if (noteContext) {
noteContext.setNote(notePath, { viewScope }).then(() => {
if (noteContext !== appContext.tabManager.getActiveContext()) {
appContext.tabManager.activateNoteContext(noteContext.ntxId);
}
});
} else {
appContext.tabManager.openContextWithNote(notePath, { viewScope, activate: true });
}
}
export default NoteContext;

View File

@@ -433,9 +433,6 @@ export default class TabManager extends Component {
$autocompleteEl.autocomplete("close");
}
// close dangling tooltips
$("body > div.tooltip").remove();
const noteContextsToRemove = noteContextToRemove.getSubContexts();
const ntxIdsToRemove = noteContextsToRemove.map((nc) => nc.ntxId);
@@ -603,18 +600,18 @@ export default class TabManager extends Component {
}
async moveTabToNewWindowCommand({ ntxId }: { ntxId: string }) {
const { notePath, hoistedNoteId, viewScope } = this.getNoteContextById(ntxId);
const { notePath, hoistedNoteId } = this.getNoteContextById(ntxId);
const removed = await this.removeNoteContext(ntxId);
if (removed) {
this.triggerCommand("openInWindow", { notePath, hoistedNoteId, viewScope });
this.triggerCommand("openInWindow", { notePath, hoistedNoteId });
}
}
async copyTabToNewWindowCommand({ ntxId }: { ntxId: string }) {
const { notePath, hoistedNoteId, viewScope } = this.getNoteContextById(ntxId);
this.triggerCommand("openInWindow", { notePath, hoistedNoteId, viewScope });
const { notePath, hoistedNoteId } = this.getNoteContextById(ntxId);
this.triggerCommand("openInWindow", { notePath, hoistedNoteId });
}
async reopenLastTabCommand() {

View File

@@ -23,11 +23,11 @@ export default class TouchBarComponent extends Component {
this.$widget = $("<div>");
$(window).on("focusin", async (e) => {
const focusedEl = e.target as unknown as HTMLElement;
const $target = $(focusedEl);
const $target = $(e.target);
this.$activeModal = $target.closest(".modal-dialog");
this.lastFocusedComponent = appContext.getComponentByEl(focusedEl);
const parentComponentEl = $target.closest(".component");
this.lastFocusedComponent = appContext.getComponentByEl(parentComponentEl[0]);
this.#refreshTouchBar();
});
}

View File

@@ -10,6 +10,7 @@ import { t } from "./services/i18n.js";
import options from "./services/options.js";
import type ElectronRemote from "@electron/remote";
import type Electron from "electron";
import "bootstrap/dist/css/bootstrap.min.css";
import "boxicons/css/boxicons.min.css";
import "autocomplete.js/index_jquery.js";
@@ -44,10 +45,6 @@ if (utils.isElectron()) {
electronContextMenu.setupContextMenu();
}
if (utils.isPWA()) {
initPWATopbarColor();
}
function initOnElectron() {
const electron: typeof Electron = utils.dynamicRequire("electron");
electron.ipcRenderer.on("globalShortcut", async (event, actionName) => appContext.triggerCommand(actionName));
@@ -116,20 +113,3 @@ function initDarkOrLightMode(style: CSSStyleDeclaration) {
const { nativeTheme } = utils.dynamicRequire("@electron/remote") as typeof ElectronRemote;
nativeTheme.themeSource = themeSource;
}
function initPWATopbarColor() {
const tracker = $("#background-color-tracker");
if (tracker.length) {
const applyThemeColor = () => {
let meta = $("meta[name='theme-color']");
if (!meta.length) {
meta = $(`<meta name="theme-color">`).appendTo($("head"));
}
meta.attr("content", tracker.css("color"));
};
tracker.on("transitionend", applyThemeColor);
applyThemeColor();
}
}

View File

@@ -1,5 +1,6 @@
import server from "../services/server.js";
import noteAttributeCache from "../services/note_attribute_cache.js";
import ws from "../services/ws.js";
import protectedSessionHolder from "../services/protected_session_holder.js";
import cssClassManager from "../services/css_class_manager.js";
import type { Froca } from "../services/froca-interface.js";
@@ -255,20 +256,18 @@ export default class FNote {
return this.children;
}
async getSubtreeNoteIds(includeArchived = false) {
async getSubtreeNoteIds() {
let noteIds: (string | string[])[] = [];
for (const child of await this.getChildNotes()) {
if (child.isArchived && !includeArchived) continue;
noteIds.push(child.noteId);
noteIds.push(await child.getSubtreeNoteIds(includeArchived));
noteIds.push(await child.getSubtreeNoteIds());
}
return noteIds.flat();
}
async getSubtreeNotes() {
const noteIds = await this.getSubtreeNoteIds();
return (await this.froca.getNotes(noteIds));
return this.froca.getNotes(noteIds);
}
async getChildNotes() {
@@ -585,7 +584,7 @@ export default class FNote {
let childBranches = this.getChildBranches();
if (!childBranches) {
console.error(`No children for '${this.noteId}'. This shouldn't happen.`);
ws.logError(`No children for '${this.noteId}'. This shouldn't happen.`);
return [];
}
@@ -906,8 +905,8 @@ export default class FNote {
return this.getBlob();
}
getBlob() {
return this.froca.getBlob("notes", this.noteId);
async getBlob() {
return await this.froca.getBlob("notes", this.noteId);
}
toString() {

View File

@@ -5,6 +5,7 @@ import NoteTreeWidget from "../widgets/note_tree.js";
import NoteTitleWidget from "../widgets/note_title.jsx";
import NoteDetailWidget from "../widgets/note_detail.js";
import PromotedAttributesWidget from "../widgets/promoted_attributes.js";
import NoteListWidget from "../widgets/note_list.js";
import NoteIconWidget from "../widgets/note_icon.jsx";
import ScrollingContainer from "../widgets/containers/scrolling_container.js";
import RootContainer from "../widgets/containers/root_container.js";
@@ -41,7 +42,6 @@ import LeftPaneToggle from "../widgets/buttons/left_pane_toggle.js";
import ApiLog from "../widgets/api_log.jsx";
import CloseZenModeButton from "../widgets/close_zen_button.jsx";
import SharedInfo from "../widgets/shared_info.jsx";
import NoteList from "../widgets/collections/NoteList.jsx";
export default class DesktopLayout {
@@ -123,10 +123,10 @@ export default class DesktopLayout {
.child(<NoteIconWidget />)
.child(<NoteTitleWidget />)
.child(new SpacerWidget(0, 1))
.child(<MovePaneButton direction="left" />)
.child(<MovePaneButton direction="right" />)
.child(<ClosePaneButton />)
.child(<CreatePaneButton />)
.child(new MovePaneButton(true))
.child(new MovePaneButton(false))
.child(new ClosePaneButton())
.child(new CreatePaneButton())
)
.child(<Ribbon />)
.child(<SharedInfo />)
@@ -138,7 +138,7 @@ export default class DesktopLayout {
.child(new PromotedAttributesWidget())
.child(<SqlTableSchemas />)
.child(new NoteDetailWidget())
.child(<NoteList media="screen" />)
.child(new NoteListWidget(false))
.child(<SearchResult />)
.child(<SqlResults />)
.child(<ScrollPadding />)

View File

@@ -27,10 +27,10 @@ import FlexContainer from "../widgets/containers/flex_container.js";
import NoteIconWidget from "../widgets/note_icon";
import PromotedAttributesWidget from "../widgets/promoted_attributes.js";
import NoteDetailWidget from "../widgets/note_detail.js";
import NoteListWidget from "../widgets/note_list.js";
import CallToActionDialog from "../widgets/dialogs/call_to_action.jsx";
import NoteTitleWidget from "../widgets/note_title.jsx";
import { PopupEditorFormattingToolbar } from "../widgets/ribbon/FormattingToolbar.js";
import NoteList from "../widgets/collections/NoteList.jsx";
export function applyModals(rootContainer: RootContainer) {
rootContainer
@@ -66,6 +66,6 @@ export function applyModals(rootContainer: RootContainer) {
.child(<PopupEditorFormattingToolbar />)
.child(new PromotedAttributesWidget())
.child(new NoteDetailWidget())
.child(<NoteList media="screen" displayOnlyCollections />))
.child(new NoteListWidget(true)))
.child(<CallToActionDialog />);
}

View File

@@ -5,6 +5,7 @@ import QuickSearchWidget from "../widgets/quick_search.js";
import NoteTreeWidget from "../widgets/note_tree.js";
import ScreenContainer from "../widgets/mobile_widgets/screen_container.js";
import ScrollingContainer from "../widgets/containers/scrolling_container.js";
import NoteListWidget from "../widgets/note_list.js";
import GlobalMenuWidget from "../widgets/buttons/global_menu.js";
import LauncherContainer from "../widgets/containers/launcher_container.js";
import RootContainer from "../widgets/containers/root_container.js";
@@ -23,7 +24,6 @@ import ToggleSidebarButton from "../widgets/mobile_widgets/toggle_sidebar_button
import CloseZenModeButton from "../widgets/close_zen_button.js";
import NoteWrapperWidget from "../widgets/note_wrapper.js";
import MobileDetailMenu from "../widgets/mobile_widgets/mobile_detail_menu.js";
import NoteList from "../widgets/collections/NoteList.jsx";
const MOBILE_CSS = `
<style>
@@ -40,8 +40,8 @@ kbd {
border: none;
cursor: pointer;
font-size: 1.25em;
padding-inline-start: 0.5em;
padding-inline-end: 0.5em;
padding-left: 0.5em;
padding-right: 0.5em;
color: var(--main-text-color);
}
.quick-search {
@@ -59,7 +59,7 @@ const FANCYTREE_CSS = `
margin-top: 0px;
overflow-y: auto;
contain: content;
padding-inline-start: 10px;
padding-left: 10px;
}
.fancytree-custom-icon {
@@ -68,7 +68,7 @@ const FANCYTREE_CSS = `
.fancytree-title {
font-size: 1.5em;
margin-inline-start: 0.6em !important;
margin-left: 0.6em !important;
}
.fancytree-node {
@@ -81,7 +81,7 @@ const FANCYTREE_CSS = `
span.fancytree-expander {
width: 24px !important;
margin-inline-end: 5px;
margin-right: 5px;
}
.fancytree-loading span.fancytree-expander {
@@ -101,7 +101,7 @@ span.fancytree-expander {
.tree-wrapper .scroll-to-active-note-button,
.tree-wrapper .tree-settings-button {
position: fixed;
margin-inline-end: 16px;
margin-right: 16px;
display: none;
}
@@ -126,8 +126,8 @@ export default class MobileLayout {
.class("d-md-flex d-lg-flex d-xl-flex col-12 col-sm-5 col-md-4 col-lg-3 col-xl-3")
.id("mobile-sidebar-wrapper")
.css("max-height", "100%")
.css("padding-inline-start", "0")
.css("padding-inline-end", "0")
.css("padding-left", "0")
.css("padding-right", "0")
.css("contain", "content")
.child(new FlexContainer("column").filling().id("mobile-sidebar-wrapper").child(new QuickSearchWidget()).child(new NoteTreeWidget().cssBlock(FANCYTREE_CSS)))
)
@@ -154,7 +154,7 @@ export default class MobileLayout {
.filling()
.contentSized()
.child(new NoteDetailWidget())
.child(<NoteList media="screen" />)
.child(new NoteListWidget(false))
.child(<FilePropertiesWrapper />)
)
.child(<MobileEditorToolbar />)
@@ -187,4 +187,4 @@ function FilePropertiesWrapper() {
{note?.type === "file" && <FilePropertiesTab note={note} />}
</div>
);
}
}

View File

@@ -1,3 +1,5 @@
import "bootstrap/dist/css/bootstrap.min.css";
// @ts-ignore - module = undefined
// Required for correct loading of scripts in Electron
if (typeof module === 'object') {window.module = module; module = undefined;}

View File

@@ -1,8 +1,6 @@
import { KeyboardActionNames } from "@triliumnext/commons";
import keyboardActionService, { getActionSync } from "../services/keyboard_actions.js";
import keyboardActionService from "../services/keyboard_actions.js";
import note_tooltip from "../services/note_tooltip.js";
import utils from "../services/utils.js";
import { should } from "vitest";
export interface ContextMenuOptions<T> {
x: number;
@@ -15,13 +13,8 @@ export interface ContextMenuOptions<T> {
onHide?: () => void;
}
export interface MenuSeparatorItem {
kind: "separator";
}
export interface MenuHeader {
title: string;
kind: "header";
interface MenuSeparatorItem {
title: "----";
}
export interface MenuItemBadge {
@@ -45,13 +38,12 @@ export interface MenuCommandItem<T> {
handler?: MenuHandler<T>;
items?: MenuItem<T>[] | null;
shortcut?: string;
keyboardShortcut?: KeyboardActionNames;
spellingSuggestion?: string;
checked?: boolean;
columns?: number;
}
export type MenuItem<T> = MenuCommandItem<T> | MenuSeparatorItem | MenuHeader;
export type MenuItem<T> = MenuCommandItem<T> | MenuSeparatorItem;
export type MenuHandler<T> = (item: MenuCommandItem<T>, e: JQuery.MouseDownEvent<HTMLElement, undefined, HTMLElement, HTMLElement>) => void;
export type ContextMenuEvent = PointerEvent | MouseEvent | JQuery.ContextMenuEvent;
@@ -150,57 +142,20 @@ class ContextMenu {
this.$widget
.css({
display: "block",
top,
left
top: top,
left: left
})
.addClass("show");
}
addItems($parent: JQuery<HTMLElement>, items: MenuItem<any>[], multicolumn = false) {
let $group = $parent; // The current group or parent element to which items are being appended
let shouldStartNewGroup = false; // If true, the next item will start a new group
let shouldResetGroup = false; // If true, the next item will be the last one from the group
for (let index = 0; index < items.length; index++) {
const item = items[index];
addItems($parent: JQuery<HTMLElement>, items: MenuItem<any>[]) {
for (const item of items) {
if (!item) {
continue;
}
// If the current item is a header, start a new group. This group will contain the
// header and the next item that follows the header.
if ("kind" in item && item.kind === "header") {
if (multicolumn && !shouldResetGroup) {
shouldStartNewGroup = true;
}
}
// If the next item is a separator, start a new group. This group will contain the
// current item, the separator, and the next item after the separator.
const nextItem = (index < items.length - 1) ? items[index + 1] : null;
if (multicolumn && nextItem && "kind" in nextItem && nextItem.kind === "separator") {
if (!shouldResetGroup) {
shouldStartNewGroup = true;
} else {
shouldResetGroup = true; // Continue the current group
}
}
// Create a new group to avoid column breaks before and after the seaparator / header.
// This is a workaround for Firefox not supporting break-before / break-after: avoid
// for columns.
if (shouldStartNewGroup) {
$group = $("<div class='dropdown-no-break'>");
$parent.append($group);
shouldStartNewGroup = false;
}
if ("kind" in item && item.kind === "separator") {
$group.append($("<div>").addClass("dropdown-divider"));
shouldResetGroup = true; // End the group after the next item
} else if ("kind" in item && item.kind === "header") {
$group.append($("<h6>").addClass("dropdown-header").text(item.title));
shouldResetGroup = true;
if (item.title === "----") {
$parent.append($("<div>").addClass("dropdown-divider"));
} else {
const $icon = $("<span>");
@@ -230,23 +185,7 @@ class ContextMenu {
}
}
if ("keyboardShortcut" in item && item.keyboardShortcut) {
const shortcuts = getActionSync(item.keyboardShortcut).effectiveShortcuts;
if (shortcuts) {
const allShortcuts: string[] = [];
for (const effectiveShortcut of shortcuts) {
allShortcuts.push(effectiveShortcut.split("+")
.map(key => `<kbd>${key}</kbd>`)
.join("+"));
}
if (allShortcuts.length) {
const container = $("<span>").addClass("keyboard-shortcut");
container.append($(allShortcuts.join(",")));
$link.append(container);
}
}
} else if ("shortcut" in item && item.shortcut) {
if ("shortcut" in item && item.shortcut) {
$link.append($("<kbd>").text(item.shortcut));
}
@@ -302,24 +241,16 @@ class ContextMenu {
$link.addClass("dropdown-toggle");
const $subMenu = $("<ul>").addClass("dropdown-menu");
const hasColumns = !!item.columns && item.columns > 1;
if (!this.isMobile && hasColumns) {
$subMenu.css("column-count", item.columns!);
if (!this.isMobile && item.columns) {
$subMenu.css("column-count", item.columns);
}
this.addItems($subMenu, item.items, hasColumns);
this.addItems($subMenu, item.items);
$item.append($subMenu);
}
$group.append($item);
// After adding a menu item, if the previous item was a separator or header,
// reset the group so that the next item will be appended directly to the parent.
if (shouldResetGroup) {
$group = $parent;
shouldResetGroup = false;
};
$parent.append($item);
}
}
}

View File

@@ -37,7 +37,7 @@ function setupContextMenu() {
handler: () => webContents.session.addWordToSpellCheckerDictionary(params.misspelledWord)
});
items.push({ kind: "separator" });
items.push({ title: `----` });
}
if (params.isEditable) {
@@ -112,7 +112,7 @@ function setupContextMenu() {
// Replace the placeholder with the real search keyword.
let searchUrl = searchEngineUrl.replace("{keyword}", encodeURIComponent(params.selectionText));
items.push({ kind: "separator" });
items.push({ title: "----" });
items.push({
title: t("electron_context_menu.search_online", { term: shortenedSelection, searchEngine: searchEngineName }),

View File

@@ -45,16 +45,16 @@ export default class LauncherContextMenu implements SelectMenuItemEventListener<
isVisibleRoot || isAvailableRoot ? { title: t("launcher_context_menu.add-script-launcher"), command: "addScriptLauncher", uiIcon: "bx bx-code-curly" } : null,
isVisibleRoot || isAvailableRoot ? { title: t("launcher_context_menu.add-custom-widget"), command: "addWidgetLauncher", uiIcon: "bx bx-customize" } : null,
isVisibleRoot || isAvailableRoot ? { title: t("launcher_context_menu.add-spacer"), command: "addSpacerLauncher", uiIcon: "bx bx-dots-horizontal" } : null,
isVisibleRoot || isAvailableRoot ? { kind: "separator" } : null,
isVisibleRoot || isAvailableRoot ? { title: "----" } : null,
isAvailableItem ? { title: t("launcher_context_menu.move-to-visible-launchers"), command: "moveLauncherToVisible", uiIcon: "bx bx-show", enabled: true } : null,
isVisibleItem ? { title: t("launcher_context_menu.move-to-available-launchers"), command: "moveLauncherToAvailable", uiIcon: "bx bx-hide", enabled: true } : null,
isVisibleItem || isAvailableItem ? { kind: "separator" } : null,
isVisibleItem || isAvailableItem ? { title: "----" } : null,
{ title: `${t("launcher_context_menu.duplicate-launcher")}`, command: "duplicateSubtree", uiIcon: "bx bx-outline", enabled: isItem },
{ title: `${t("launcher_context_menu.delete")}`, command: "deleteNotes", uiIcon: "bx bx-trash destructive-action-icon", enabled: canBeDeleted },
{ kind: "separator" },
{ title: "----" },
{ title: t("launcher_context_menu.reset"), command: "resetLauncher", uiIcon: "bx bx-reset destructive-action-icon", enabled: canBeReset }
];

View File

@@ -13,8 +13,6 @@ import type NoteTreeWidget from "../widgets/note_tree.js";
import type FAttachment from "../entities/fattachment.js";
import type { SelectMenuItemEventListener } from "../components/events.js";
import utils from "../services/utils.js";
import attributes from "../services/attributes.js";
import { executeBulkActions } from "../services/bulk_action.js";
// TODO: Deduplicate once client/server is well split.
interface ConvertToAttachmentResponse {
@@ -63,11 +61,6 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
// the only exception is when the only selected note is the one that was right-clicked, then
// it's clear what the user meant to do.
const selNodes = this.treeWidget.getSelectedNodes();
const selectedNotes = await froca.getNotes(selNodes.map(node => node.data.noteId));
if (note && !selectedNotes.includes(note)) selectedNotes.push(note);
const isArchived = selectedNotes.every(note => note.isArchived);
const canToggleArchived = !selectedNotes.some(note => note.isArchived !== isArchived);
const noSelectedNotes = selNodes.length === 0 || (selNodes.length === 1 && selNodes[0] === this.node);
const notSearch = note?.type !== "search";
@@ -76,29 +69,27 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
const insertNoteAfterEnabled = isNotRoot && !isHoisted && parentNotSearch;
const items: (MenuItem<TreeCommandNames> | null)[] = [
{ title: t("tree-context-menu.open-in-a-new-tab"), command: "openInTab", shortcut: "Ctrl+Click", uiIcon: "bx bx-link-external", enabled: noSelectedNotes },
{ title: `${t("tree-context-menu.open-in-a-new-tab")}`, command: "openInTab", uiIcon: "bx bx-link-external", enabled: noSelectedNotes },
{ title: t("tree-context-menu.open-in-a-new-split"), command: "openNoteInSplit", uiIcon: "bx bx-dock-right", enabled: noSelectedNotes },
{ title: t("tree-context-menu.open-in-popup"), command: "openNoteInPopup", uiIcon: "bx bx-edit", enabled: noSelectedNotes },
isHoisted
? null
: {
title: `${t("tree-context-menu.hoist-note")}`,
title: `${t("tree-context-menu.hoist-note")} <kbd data-command="toggleNoteHoisting"></kbd>`,
command: "toggleNoteHoisting",
keyboardShortcut: "toggleNoteHoisting",
uiIcon: "bx bxs-chevrons-up",
enabled: noSelectedNotes && notSearch
},
!isHoisted || !isNotRoot
? null
: { title: t("tree-context-menu.unhoist-note"), command: "toggleNoteHoisting", keyboardShortcut: "toggleNoteHoisting", uiIcon: "bx bx-door-open" },
: { title: `${t("tree-context-menu.unhoist-note")} <kbd data-command="toggleNoteHoisting"></kbd>`, command: "toggleNoteHoisting", uiIcon: "bx bx-door-open" },
{ kind: "separator" },
{ title: "----" },
{
title: t("tree-context-menu.insert-note-after"),
title: `${t("tree-context-menu.insert-note-after")}<kbd data-command="createNoteAfter"></kbd>`,
command: "insertNoteAfter",
keyboardShortcut: "createNoteAfter",
uiIcon: "bx bx-plus",
items: insertNoteAfterEnabled ? await noteTypesService.getNoteTypeItems("insertNoteAfter") : null,
enabled: insertNoteAfterEnabled && noSelectedNotes && notOptionsOrHelp,
@@ -106,22 +97,21 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
},
{
title: t("tree-context-menu.insert-child-note"),
title: `${t("tree-context-menu.insert-child-note")}<kbd data-command="createNoteInto"></kbd>`,
command: "insertChildNote",
keyboardShortcut: "createNoteInto",
uiIcon: "bx bx-plus",
items: notSearch ? await noteTypesService.getNoteTypeItems("insertChildNote") : null,
enabled: notSearch && noSelectedNotes && notOptionsOrHelp,
columns: 2
},
{ kind: "separator" },
{ title: "----" },
{ title: t("tree-context-menu.protect-subtree"), command: "protectSubtree", uiIcon: "bx bx-check-shield", enabled: noSelectedNotes },
{ title: t("tree-context-menu.unprotect-subtree"), command: "unprotectSubtree", uiIcon: "bx bx-shield", enabled: noSelectedNotes },
{ kind: "separator" },
{ title: "----" },
{
title: t("tree-context-menu.advanced"),
@@ -130,52 +120,48 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
items: [
{ title: t("tree-context-menu.apply-bulk-actions"), command: "openBulkActionsDialog", uiIcon: "bx bx-list-plus", enabled: true },
{ kind: "separator" },
{ title: "----" },
{
title: t("tree-context-menu.edit-branch-prefix"),
title: `${t("tree-context-menu.edit-branch-prefix")} <kbd data-command="editBranchPrefix"></kbd>`,
command: "editBranchPrefix",
keyboardShortcut: "editBranchPrefix",
uiIcon: "bx bx-rename",
enabled: isNotRoot && parentNotSearch && noSelectedNotes && notOptionsOrHelp
},
{ title: t("tree-context-menu.convert-to-attachment"), command: "convertNoteToAttachment", uiIcon: "bx bx-paperclip", enabled: isNotRoot && !isHoisted && notOptionsOrHelp },
{ kind: "separator" },
{ title: "----" },
{ title: t("tree-context-menu.expand-subtree"), command: "expandSubtree", keyboardShortcut: "expandSubtree", uiIcon: "bx bx-expand", enabled: noSelectedNotes },
{ title: t("tree-context-menu.collapse-subtree"), command: "collapseSubtree", keyboardShortcut: "collapseSubtree", uiIcon: "bx bx-collapse", enabled: noSelectedNotes },
{ title: `${t("tree-context-menu.expand-subtree")} <kbd data-command="expandSubtree"></kbd>`, command: "expandSubtree", uiIcon: "bx bx-expand", enabled: noSelectedNotes },
{ title: `${t("tree-context-menu.collapse-subtree")} <kbd data-command="collapseSubtree"></kbd>`, command: "collapseSubtree", uiIcon: "bx bx-collapse", enabled: noSelectedNotes },
{
title: t("tree-context-menu.sort-by"),
title: `${t("tree-context-menu.sort-by")} <kbd data-command="sortChildNotes"></kbd>`,
command: "sortChildNotes",
keyboardShortcut: "sortChildNotes",
uiIcon: "bx bx-sort-down",
enabled: noSelectedNotes && notSearch
},
{ kind: "separator" },
{ title: "----" },
{ title: t("tree-context-menu.copy-note-path-to-clipboard"), command: "copyNotePathToClipboard", uiIcon: "bx bx-directions", enabled: true },
{ title: t("tree-context-menu.recent-changes-in-subtree"), command: "recentChangesInSubtree", uiIcon: "bx bx-history", enabled: noSelectedNotes && notOptionsOrHelp }
]
},
{ kind: "separator" },
{ title: "----" },
{
title: t("tree-context-menu.cut"),
title: `${t("tree-context-menu.cut")} <kbd data-command="cutNotesToClipboard"></kbd>`,
command: "cutNotesToClipboard",
keyboardShortcut: "cutNotesToClipboard",
uiIcon: "bx bx-cut",
enabled: isNotRoot && !isHoisted && parentNotSearch
},
{ title: t("tree-context-menu.copy-clone"), command: "copyNotesToClipboard", keyboardShortcut: "copyNotesToClipboard", uiIcon: "bx bx-copy", enabled: isNotRoot && !isHoisted },
{ title: `${t("tree-context-menu.copy-clone")} <kbd data-command="copyNotesToClipboard"></kbd>`, command: "copyNotesToClipboard", uiIcon: "bx bx-copy", enabled: isNotRoot && !isHoisted },
{
title: t("tree-context-menu.paste-into"),
title: `${t("tree-context-menu.paste-into")} <kbd data-command="pasteNotesFromClipboard"></kbd>`,
command: "pasteNotesFromClipboard",
keyboardShortcut: "pasteNotesFromClipboard",
uiIcon: "bx bx-paste",
enabled: !clipboard.isClipboardEmpty() && notSearch && noSelectedNotes
},
@@ -188,71 +174,39 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
},
{
title: t("tree-context-menu.move-to"),
title: `${t("tree-context-menu.move-to")} <kbd data-command="moveNotesTo"></kbd>`,
command: "moveNotesTo",
keyboardShortcut: "moveNotesTo",
uiIcon: "bx bx-transfer",
enabled: isNotRoot && !isHoisted && parentNotSearch
},
{ title: t("tree-context-menu.clone-to"), command: "cloneNotesTo", keyboardShortcut: "cloneNotesTo", uiIcon: "bx bx-duplicate", enabled: isNotRoot && !isHoisted },
{ title: `${t("tree-context-menu.clone-to")} <kbd data-command="cloneNotesTo"></kbd>`, command: "cloneNotesTo", uiIcon: "bx bx-duplicate", enabled: isNotRoot && !isHoisted },
{
title: t("tree-context-menu.duplicate"),
title: `${t("tree-context-menu.duplicate")} <kbd data-command="duplicateSubtree">`,
command: "duplicateSubtree",
keyboardShortcut: "duplicateSubtree",
uiIcon: "bx bx-outline",
enabled: parentNotSearch && isNotRoot && !isHoisted && notOptionsOrHelp
},
{
title: !isArchived ? t("tree-context-menu.archive") : t("tree-context-menu.unarchive"),
uiIcon: !isArchived ? "bx bx-archive" : "bx bx-archive-out",
enabled: canToggleArchived,
handler: () => {
if (!selectedNotes.length) return;
if (selectedNotes.length == 1) {
const note = selectedNotes[0];
if (!isArchived) {
attributes.addLabel(note.noteId, "archived");
} else {
attributes.removeOwnedLabelByName(note, "archived");
}
} else {
const noteIds = selectedNotes.map(note => note.noteId);
if (!isArchived) {
executeBulkActions(noteIds, [{
name: "addLabel", labelName: "archived"
}]);
} else {
executeBulkActions(noteIds, [{
name: "deleteLabel", labelName: "archived"
}]);
}
}
}
},
{
title: t("tree-context-menu.delete"),
title: `${t("tree-context-menu.delete")} <kbd data-command="deleteNotes"></kbd>`,
command: "deleteNotes",
keyboardShortcut: "deleteNotes",
uiIcon: "bx bx-trash destructive-action-icon",
enabled: isNotRoot && !isHoisted && parentNotSearch && notOptionsOrHelp
},
{ kind: "separator" },
{ title: "----" },
{ title: t("tree-context-menu.import-into-note"), command: "importIntoNote", uiIcon: "bx bx-import", enabled: notSearch && noSelectedNotes && notOptionsOrHelp },
{ title: t("tree-context-menu.export"), command: "exportNote", uiIcon: "bx bx-export", enabled: notSearch && noSelectedNotes && notOptionsOrHelp },
{ kind: "separator" },
{ title: "----" },
{
title: t("tree-context-menu.search-in-subtree"),
title: `${t("tree-context-menu.search-in-subtree")} <kbd data-command="searchInSubtree"></kbd>`,
command: "searchInSubtree",
keyboardShortcut: "searchInSubtree",
uiIcon: "bx bx-search",
enabled: notSearch && noSelectedNotes
}

View File

@@ -1,6 +1,7 @@
import appContext from "./components/app_context.js";
import noteAutocompleteService from "./services/note_autocomplete.js";
import glob from "./services/glob.js";
import "bootstrap/dist/css/bootstrap.min.css";
import "boxicons/css/boxicons.min.css";
import "autocomplete.js/index_jquery.js";

View File

@@ -1,155 +0,0 @@
:root {
--print-font-size: 11pt;
--ck-content-color-image-caption-background: transparent !important;
}
html,
body {
width: 100%;
height: 100%;
color: black;
}
@page {
margin: 2cm;
}
.note-list-widget.full-height,
.note-list-widget.full-height .note-list-widget-content {
height: unset !important;
}
.component {
contain: none !important;
}
body[data-note-type="text"] .ck-content {
font-size: var(--print-font-size);
text-align: justify;
}
.ck-content figcaption {
font-style: italic;
}
.ck-content a {
text-decoration: none;
}
.ck-content a:not([href^="#root/"]) {
text-decoration: underline;
color: #374a75;
}
.ck-content .todo-list__label * {
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
@supports selector(.todo-list__label__description:has(*)) and (height: 1lh) {
.ck-content .todo-list__label__description {
/* The percentage of the line height that the check box occupies */
--box-ratio: 0.75;
/* The size of the gap between the check box and the caption */
--box-text-gap: 0.25em;
--box-size: calc(1lh * var(--box-ratio));
--box-vert-offset: calc((1lh - var(--box-size)) / 2);
display: inline-block;
padding-inline-start: calc(var(--box-size) + var(--box-text-gap));
/* Source: https://pictogrammers.com/library/mdi/icon/checkbox-blank-outline/ */
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'%3e%3cpath d='M19%2c3H5C3.89%2c3 3%2c3.89 3%2c5V19A2%2c2 0 0%2c0 5%2c21H19A2%2c2 0 0%2c0 21%2c19V5C21%2c3.89 20.1%2c3 19%2c3M19%2c5V19H5V5H19Z' /%3e%3c/svg%3e");
background-position: 0 var(--box-vert-offset);
background-size: var(--box-size);
background-repeat: no-repeat;
}
.ck-content .todo-list__label:has(input[type="checkbox"]:checked) .todo-list__label__description {
/* Source: https://pictogrammers.com/library/mdi/icon/checkbox-outline/ */
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'%3e%3cpath d='M19%2c3H5A2%2c2 0 0%2c0 3%2c5V19A2%2c2 0 0%2c0 5%2c21H19A2%2c2 0 0%2c0 21%2c19V5A2%2c2 0 0%2c0 19%2c3M19%2c5V19H5V5H19M10%2c17L6%2c13L7.41%2c11.58L10%2c14.17L16.59%2c7.58L18%2c9' /%3e%3c/svg%3e");
}
.ck-content .todo-list__label input[type="checkbox"] {
display: none !important;
}
}
/* #region Footnotes */
.footnote-reference a,
.footnote-back-link a {
text-decoration: none !important;
}
li.footnote-item {
position: relative;
width: fit-content;
}
.ck-content .footnote-back-link {
margin-right: 0.25em;
}
.ck-content .footnote-content {
display: inline-block;
width: unset;
}
/* #endregion */
/* #region Widows and orphans */
p,
blockquote {
widows: 4;
orphans: 4;
}
pre > code {
widows: 6;
orphans: 6;
overflow: auto;
white-space: pre-wrap !important;
}
h1,
h2,
h3,
h4,
h5,
h6 {
page-break-after: avoid;
break-after: avoid;
}
/* #endregion */
/* #region Tables */
.table thead th,
.table td,
.table th {
/* Fix center vertical alignment of table cells */
vertical-align: middle;
}
pre {
box-shadow: unset !important;
border: 0.75pt solid gray !important;
border-radius: 2pt !important;
}
th,
span[style] {
print-color-adjust: exact;
-webkit-print-color-adjust: exact;
}
/* #endregion */
/* #region Page breaks */
.page-break {
page-break-after: always;
break-after: always;
}
.page-break > *,
.page-break::after {
display: none !important;
}
/* #endregion */

View File

@@ -1,92 +0,0 @@
import FNote from "./entities/fnote";
import { render } from "preact";
import { CustomNoteList } from "./widgets/collections/NoteList";
import { useCallback, useLayoutEffect, useRef } from "preact/hooks";
import content_renderer from "./services/content_renderer";
interface RendererProps {
note: FNote;
onReady: () => void;
}
async function main() {
const notePath = window.location.hash.substring(1);
const noteId = notePath.split("/").at(-1);
if (!noteId) return;
await import("./print.css");
const froca = (await import("./services/froca")).default;
const note = await froca.getNote(noteId);
render(<App note={note} noteId={noteId} />, document.body);
}
function App({ note, noteId }: { note: FNote | null | undefined, noteId: string }) {
const sentReadyEvent = useRef(false);
const onReady = useCallback(() => {
if (sentReadyEvent.current) return;
window.dispatchEvent(new Event("note-ready"));
window._noteReady = true;
sentReadyEvent.current = true;
}, []);
const props: RendererProps | undefined | null = note && { note, onReady };
if (!note || !props) return <Error404 noteId={noteId} />
useLayoutEffect(() => {
document.body.dataset.noteType = note.type;
}, [ note ]);
return (
<>
{note.type === "book"
? <CollectionRenderer {...props} />
: <SingleNoteRenderer {...props} />
}
</>
);
}
function SingleNoteRenderer({ note, onReady }: RendererProps) {
const containerRef = useRef<HTMLDivElement>(null);
useLayoutEffect(() => {
async function load() {
if (note.type === "text") {
await import("@triliumnext/ckeditor5/src/theme/ck-content.css");
}
const { $renderedContent } = await content_renderer.getRenderedContent(note, { noChildrenList: true });
containerRef.current?.replaceChildren(...$renderedContent);
}
load().then(() => requestAnimationFrame(onReady))
}, [ note ]);
return <>
<h1>{note.title}</h1>
<main ref={containerRef} />
</>;
}
function CollectionRenderer({ note, onReady }: RendererProps) {
return <CustomNoteList
isEnabled
note={note}
notePath={note.getBestNotePath().join("/")}
ntxId="print"
highlightedTokens={null}
media="print"
onReady={onReady}
/>;
}
function Error404({ noteId }: { noteId: string }) {
return (
<main>
<p>The note you are trying to print could not be found.</p>
<small>{noteId}</small>
</main>
)
}
main();

View File

@@ -1,15 +1,5 @@
import $ from "jquery";
async function loadBootstrap() {
if (document.body.dir === "rtl") {
await import("bootstrap/dist/css/bootstrap.rtl.min.css");
} else {
await import("bootstrap/dist/css/bootstrap.min.css");
}
}
(window as any).$ = $;
(window as any).jQuery = $;
await loadBootstrap();
$("body").show();

View File

@@ -210,7 +210,7 @@ function makeToast(id: string, message: string): ToastOptions {
}
ws.subscribeToMessages(async (message) => {
if (!("taskType" in message) || message.taskType !== "deleteNotes") {
if (message.taskType !== "deleteNotes") {
return;
}
@@ -228,7 +228,7 @@ ws.subscribeToMessages(async (message) => {
});
ws.subscribeToMessages(async (message) => {
if (!("taskType" in message) || message.taskType !== "undeleteNotes") {
if (message.taskType !== "undeleteNotes") {
return;
}

View File

@@ -23,13 +23,11 @@ interface Options {
tooltip?: boolean;
trim?: boolean;
imageHasZoom?: boolean;
/** If enabled, it will prevent the default behavior in which an empty note would display a list of children. */
noChildrenList?: boolean;
}
const CODE_MIME_TYPES = new Set(["application/json"]);
export async function getRenderedContent(this: {} | { ctx: string }, entity: FNote | FAttachment, options: Options = {}) {
async function getRenderedContent(this: {} | { ctx: string }, entity: FNote | FAttachment, options: Options = {}) {
options = Object.assign(
{
@@ -44,7 +42,7 @@ export async function getRenderedContent(this: {} | { ctx: string }, entity: FNo
const $renderedContent = $('<div class="rendered-content">');
if (type === "text" || type === "book") {
await renderText(entity, $renderedContent, options);
await renderText(entity, $renderedContent);
} else if (type === "code") {
await renderCode(entity, $renderedContent);
} else if (["image", "canvas", "mindMap"].includes(type)) {
@@ -116,7 +114,7 @@ export async function getRenderedContent(this: {} | { ctx: string }, entity: FNo
};
}
async function renderText(note: FNote | FAttachment, $renderedContent: JQuery<HTMLElement>, options: Options = {}) {
async function renderText(note: FNote | FAttachment, $renderedContent: JQuery<HTMLElement>) {
// entity must be FNote
const blob = await note.getBlob();
@@ -137,7 +135,7 @@ async function renderText(note: FNote | FAttachment, $renderedContent: JQuery<HT
}
await formatCodeBlocks($renderedContent);
} else if (note instanceof FNote && !options.noChildrenList) {
} else if (note instanceof FNote) {
await renderChildrenList($renderedContent, note);
}
}
@@ -258,19 +256,8 @@ function renderFile(entity: FNote | FAttachment, type: string, $renderedContent:
</button>
`);
$downloadButton.on("click", (e) => {
e.stopPropagation();
openService.downloadFileNote(entity.noteId)
});
$openButton.on("click", async (e) => {
const iconEl = $openButton.find("> .bx");
iconEl.removeClass("bx bx-link-external");
iconEl.addClass("bx bx-loader spin");
e.stopPropagation();
await openService.openNoteExternally(entity.noteId, entity.mime)
iconEl.removeClass("bx bx-loader spin");
iconEl.addClass("bx bx-link-external");
});
$downloadButton.on("click", () => openService.downloadFileNote(entity.noteId));
$openButton.on("click", () => openService.openNoteExternally(entity.noteId, entity.mime));
// open doesn't work for protected notes since it works through a browser which isn't in protected session
$openButton.toggle(!entity.isProtected);

View File

@@ -1,39 +1,21 @@
import {readCssVar} from "../utils/css-var";
import Color, { ColorInstance } from "color";
const registeredClasses = new Set<string>();
// Read the color lightness limits defined in the theme as CSS variables
function createClassForColor(color: string | null) {
if (!color?.trim()) {
return "";
}
const lightThemeColorMaxLightness = readCssVar(
document.documentElement,
"tree-item-light-theme-max-color-lightness"
).asNumber(70);
const normalizedColorName = color.replace(/[^a-z0-9]/gi, "");
const darkThemeColorMinLightness = readCssVar(
document.documentElement,
"tree-item-dark-theme-min-color-lightness"
).asNumber(50);
if (!normalizedColorName.trim()) {
return "";
}
function createClassForColor(colorString: string | null) {
if (!colorString?.trim()) return "";
const color = parseColor(colorString);
if (!color) return "";
const className = `color-${color.hex().substring(1)}`;
const className = `color-${normalizedColorName}`;
if (!registeredClasses.has(className)) {
const adjustedColor = adjustColorLightness(color, lightThemeColorMaxLightness!,
darkThemeColorMinLightness!);
$("head").append(`<style>
.${className}, span.fancytree-active.${className} {
--light-theme-custom-color: ${adjustedColor.lightThemeColor};
--dark-theme-custom-color: ${adjustedColor.darkThemeColor};
--custom-color-hue: ${getHue(color) ?? 'unset'};
}
</style>`);
// make the active fancytree selector more specific than the normal color setting
$("head").append(`<style>.${className}, span.fancytree-active.${className} { color: ${color} !important; }</style>`);
registeredClasses.add(className);
}
@@ -41,41 +23,6 @@ function createClassForColor(colorString: string | null) {
return className;
}
function parseColor(color: string) {
try {
return Color(color);
} catch (ex) {
console.error(ex);
}
}
/**
* Returns a pair of colors — one optimized for light themes and the other for dark themes, derived
* from the specified color to maintain sufficient contrast with each theme.
* The adjustment is performed by limiting the colors lightness in the CIELAB color space,
* according to the lightThemeMaxLightness and darkThemeMinLightness parameters.
*/
function adjustColorLightness(color: ColorInstance, lightThemeMaxLightness: number, darkThemeMinLightness: number) {
const labColor = color.lab();
const lightness = labColor.l();
// For the light theme, limit the maximum lightness
const lightThemeColor = labColor.l(Math.min(lightness, lightThemeMaxLightness)).hex();
// For the dark theme, limit the minimum lightness
const darkThemeColor = labColor.l(Math.max(lightness, darkThemeMinLightness)).hex();
return {lightThemeColor, darkThemeColor};
}
/** Returns the hue of the specified color, or undefined if the color is grayscale. */
function getHue(color: ColorInstance) {
const hslColor = color.hsl();
if (hslColor.saturationl() > 0) {
return hslColor.hue();
}
}
export default {
createClassForColor
};

View File

@@ -60,7 +60,7 @@ async function confirmDeleteNoteBoxWithNote(title: string) {
return new Promise<ConfirmDialogResult | undefined>((res) => appContext.triggerCommand("showConfirmDeleteNoteBoxWithNoteDialog", { title, callback: res }));
}
export async function prompt(props: PromptDialogOptions) {
async function prompt(props: PromptDialogOptions) {
return new Promise<string | null>((res) => appContext.triggerCommand("showPromptDialog", { ...props, callback: res }));
}

View File

@@ -1,8 +1,16 @@
import ws from "./ws.js";
import appContext from "../components/app_context.js";
import { OpenedFileUpdateStatus } from "@triliumnext/commons";
const fileModificationStatus: Record<string, Record<string, OpenedFileUpdateStatus>> = {
// TODO: Deduplicate
interface Message {
type: string;
entityType: string;
entityId: string;
lastModifiedMs: number;
filePath: string;
}
const fileModificationStatus: Record<string, Record<string, Message>> = {
notes: {},
attachments: {}
};
@@ -31,7 +39,7 @@ function ignoreModification(entityType: string, entityId: string) {
delete fileModificationStatus[entityType][entityId];
}
ws.subscribeToMessages(async message => {
ws.subscribeToMessages(async (message: Message) => {
if (message.type !== "openedFileUpdated") {
return;
}

View File

@@ -40,23 +40,20 @@ class FrocaImpl implements Froca {
constructor() {
this.initializedPromise = this.loadInitialTree();
this.#clear();
}
async loadInitialTree() {
const resp = await server.get<SubtreeResponse>("tree");
// clear the cache only directly before adding new content which is important for e.g., switching to protected session
this.#clear();
this.addResp(resp);
}
#clear() {
this.notes = {};
this.branches = {};
this.attributes = {};
this.attachments = {};
this.blobPromises = {};
this.addResp(resp);
}
async loadSubTree(subTreeNoteId: string) {

View File

@@ -8,7 +8,6 @@ import FAttribute, { type FAttributeRow } from "../entities/fattribute.js";
import FAttachment, { type FAttachmentRow } from "../entities/fattachment.js";
import type { default as FNote, FNoteRow } from "../entities/fnote.js";
import type { EntityChange } from "../server_types.js";
import type { OptionNames } from "@triliumnext/commons";
async function processEntityChanges(entityChanges: EntityChange[]) {
const loadResults = new LoadResults(entityChanges);
@@ -31,8 +30,9 @@ async function processEntityChanges(entityChanges: EntityChange[]) {
continue; // only noise
}
options.set(attributeEntity.name as OptionNames, attributeEntity.value);
loadResults.addOption(attributeEntity.name as OptionNames);
options.set(attributeEntity.name, attributeEntity.value);
loadResults.addOption(attributeEntity.name);
} else if (ec.entityName === "attachments") {
processAttachment(loadResults, ec);
} else if (ec.entityName === "blobs") {

View File

@@ -21,7 +21,6 @@ import dayjs from "dayjs";
import type NoteContext from "../components/note_context.js";
import type NoteDetailWidget from "../widgets/note_detail.js";
import type Component from "../components/component.js";
import { formatLogMessage } from "@triliumnext/commons";
/**
* A whole number
@@ -456,7 +455,7 @@ export interface Api {
/**
* Log given message to the log pane in UI
*/
log(message: string | object): void;
log(message: string): void;
}
/**
@@ -697,7 +696,7 @@ function FrontendScriptApi(this: Api, startNote: FNote, currentNote: FNote, orig
this.log = (message) => {
const { noteId } = this.startNote;
message = `${utils.now()}: ${formatLogMessage(message)}`;
message = `${utils.now()}: ${message}`;
console.log(`Script ${noteId}: ${message}`);

View File

@@ -6,7 +6,7 @@ import { describe, expect, it } from "vitest";
describe("i18n", () => {
it("translations are valid JSON", () => {
for (const locale of LOCALES) {
if (locale.contentOnly || locale.id === "en_rtl") {
if (locale.contentOnly) {
continue;
}

View File

@@ -4,7 +4,6 @@ import ws from "./ws.js";
import utils from "./utils.js";
import appContext from "../components/app_context.js";
import { t } from "./i18n.js";
import { WebSocketMessage } from "@triliumnext/commons";
type BooleanLike = boolean | "true" | "false";
@@ -67,7 +66,7 @@ function makeToast(id: string, message: string): ToastOptions {
}
ws.subscribeToMessages(async (message) => {
if (!("taskType" in message) || message.taskType !== "importNotes") {
if (message.taskType !== "importNotes") {
return;
}
@@ -88,8 +87,8 @@ ws.subscribeToMessages(async (message) => {
}
});
ws.subscribeToMessages(async (message: WebSocketMessage) => {
if (!("taskType" in message) || message.taskType !== "importAttachments") {
ws.subscribeToMessages(async (message) => {
if (message.taskType !== "importAttachments") {
return;
}

View File

@@ -1,6 +1,6 @@
import { NoteType } from "@triliumnext/commons";
import { ViewTypeOptions } from "./note_list_renderer";
import FNote from "../entities/fnote";
import { ViewTypeOptions } from "../widgets/collections/interface";
export const byNoteType: Record<Exclude<NoteType, "book">, string | null> = {
canvas: null,
@@ -27,8 +27,7 @@ export const byBookType: Record<ViewTypeOptions, string | null> = {
calendar: "xWbu3jpNWapp",
table: "2FvYrpmOXm29",
geoMap: "81SGnPGMk7Xc",
board: "CtBQqbwXDx1w",
presentation: null
board: "CtBQqbwXDx1w"
};
export function getHelpUrlForNote(note: FNote | null | undefined) {

View File

@@ -3,8 +3,16 @@ import linkContextMenuService from "../menus/link_context_menu.js";
import appContext, { type NoteCommandData } from "../components/app_context.js";
import froca from "./froca.js";
import utils from "./utils.js";
import { ALLOWED_PROTOCOLS } from "@triliumnext/commons";
import { openInCurrentNoteContext } from "../components/note_context.js";
// Be consistent with `allowedSchemes` in `src\services\html_sanitizer.ts`
// TODO: Deduplicate with server once we can.
export const ALLOWED_PROTOCOLS = [
'http', 'https', 'ftp', 'ftps', 'mailto', 'data', 'evernote', 'file', 'facetime', 'gemini', 'git',
'gopher', 'imap', 'irc', 'irc6', 'jabber', 'jar', 'lastfm', 'ldap', 'ldaps', 'magnet', 'message',
'mumble', 'nfs', 'onenote', 'pop', 'rmi', 's3', 'sftp', 'skype', 'sms', 'spotify', 'steam', 'svn', 'udp',
'view-source', 'vlc', 'vnc', 'ws', 'wss', 'xmpp', 'jdbc', 'slack', 'tel', 'smb', 'zotero', 'geo',
'mid'
];
function getNotePathFromUrl(url: string) {
const notePathMatch = /#(root[A-Za-z0-9_/]*)$/.exec(url);
@@ -27,7 +35,8 @@ async function getLinkIcon(noteId: string, viewMode: ViewMode | undefined) {
return icon;
}
export type ViewMode = "default" | "source" | "attachments" | "contextual-help";
// TODO: Remove `string` once all the view modes have been mapped.
type ViewMode = "default" | "source" | "attachments" | "contextual-help" | string;
export interface ViewScope {
/**
@@ -317,7 +326,21 @@ function goToLinkExt(evt: MouseEvent | JQuery.ClickEvent | JQuery.MouseDownEvent
viewScope
});
} else if (isLeftClick) {
openInCurrentNoteContext(evt, notePath, viewScope);
const ntxId = $(evt?.target as any)
.closest("[data-ntx-id]")
.attr("data-ntx-id");
const noteContext = ntxId ? appContext.tabManager.getNoteContextById(ntxId) : appContext.tabManager.getActiveContext();
if (noteContext) {
noteContext.setNote(notePath, { viewScope }).then(() => {
if (noteContext !== appContext.tabManager.getActiveContext()) {
appContext.tabManager.activateNoteContext(noteContext.ntxId);
}
});
} else {
appContext.tabManager.openContextWithNote(notePath, { viewScope, activate: true });
}
}
} else if (hrefLink) {
const withinEditLink = $link?.hasClass("ck-link-actions__preview");

View File

@@ -1,4 +1,4 @@
import type { AttachmentRow, EtapiTokenRow, OptionNames } from "@triliumnext/commons";
import type { AttachmentRow, EtapiTokenRow } from "@triliumnext/commons";
import type { AttributeType } from "../entities/fattribute.js";
import type { EntityChange } from "../server_types.js";
@@ -67,7 +67,7 @@ export default class LoadResults {
private revisionRows: RevisionRow[];
private noteReorderings: string[];
private contentNoteIdToComponentId: ContentNoteIdToComponentIdRow[];
private optionNames: OptionNames[];
private optionNames: string[];
private attachmentRows: AttachmentRow[];
public hasEtapiTokenChanges: boolean = false;
@@ -180,11 +180,11 @@ export default class LoadResults {
return this.contentNoteIdToComponentId.find((l) => l.noteId === noteId && l.componentId !== componentId);
}
addOption(name: OptionNames) {
addOption(name: string) {
this.optionNames.push(name);
}
isOptionReloaded(name: OptionNames) {
isOptionReloaded(name: string) {
return this.optionNames.includes(name);
}

View File

@@ -0,0 +1,71 @@
import type FNote from "../entities/fnote.js";
import BoardView from "../widgets/view_widgets/board_view/index.js";
import CalendarView from "../widgets/view_widgets/calendar_view.js";
import GeoView from "../widgets/view_widgets/geo_view/index.js";
import ListOrGridView from "../widgets/view_widgets/list_or_grid_view.js";
import TableView from "../widgets/view_widgets/table_view/index.js";
import type { ViewModeArgs } from "../widgets/view_widgets/view_mode.js";
import type ViewMode from "../widgets/view_widgets/view_mode.js";
const allViewTypes = ["list", "grid", "calendar", "table", "geoMap", "board"] as const;
export type ArgsWithoutNoteId = Omit<ViewModeArgs, "noteIds">;
export type ViewTypeOptions = typeof allViewTypes[number];
export default class NoteListRenderer {
private viewType: ViewTypeOptions;
private args: ArgsWithoutNoteId;
public viewMode?: ViewMode<any>;
constructor(args: ArgsWithoutNoteId) {
this.args = args;
this.viewType = this.#getViewType(args.parentNote);
}
#getViewType(parentNote: FNote): ViewTypeOptions {
const viewType = parentNote.getLabelValue("viewType");
if (!(allViewTypes as readonly string[]).includes(viewType || "")) {
// when not explicitly set, decide based on the note type
return parentNote.type === "search" ? "list" : "grid";
} else {
return viewType as ViewTypeOptions;
}
}
get isFullHeight() {
switch (this.viewType) {
case "list":
case "grid":
return false;
default:
return true;
}
}
async renderList() {
const args = this.args;
const viewMode = this.#buildViewMode(args);
this.viewMode = viewMode;
await viewMode.beforeRender();
return await viewMode.renderList();
}
#buildViewMode(args: ViewModeArgs) {
switch (this.viewType) {
case "calendar":
return new CalendarView(args);
case "table":
return new TableView(args);
case "geoMap":
return new GeoView(args);
case "board":
return new BoardView(args);
case "list":
case "grid":
default:
return new ListOrGridView(this.viewType, args);
}
}
}

View File

@@ -1,7 +1,7 @@
import { t } from "./i18n.js";
import froca from "./froca.js";
import server from "./server.js";
import type { MenuCommandItem, MenuItem, MenuItemBadge, MenuSeparatorItem } from "../menus/context_menu.js";
import type { MenuCommandItem, MenuItem, MenuItemBadge } from "../menus/context_menu.js";
import type { NoteType } from "../entities/fnote.js";
import type { TreeCommandNames } from "../menus/tree_context_menu.js";
@@ -73,7 +73,7 @@ const BETA_BADGE = {
title: t("note_types.beta-feature")
};
const SEPARATOR: MenuSeparatorItem = { kind: "separator" };
const SEPARATOR = { title: "----" };
const creationDateCache = new Map<string, Date>();
let rootCreationDate: Date | undefined;
@@ -81,8 +81,8 @@ let rootCreationDate: Date | undefined;
async function getNoteTypeItems(command?: TreeCommandNames) {
const items: MenuItem<TreeCommandNames>[] = [
...getBlankNoteTypes(command),
...await getBuiltInTemplates(null, command, false),
...await getBuiltInTemplates(t("note_types.collections"), command, true),
...await getBuiltInTemplates(null, command, false),
...await getUserTemplates(command)
];
@@ -121,10 +121,7 @@ async function getUserTemplates(command?: TreeCommandNames) {
}
const items: MenuItem<TreeCommandNames>[] = [
{
title: t("note_type_chooser.templates"),
kind: "header"
}
SEPARATOR
];
for (const templateNote of templateNotes) {
@@ -161,15 +158,15 @@ async function getBuiltInTemplates(title: string | null, command: TreeCommandNam
if (title) {
items.push({
title: title,
kind: "header"
enabled: false,
uiIcon: "bx bx-empty"
});
} else {
items.push(SEPARATOR);
}
for (const templateNote of childNotes) {
if (templateNote.hasLabel("collection") !== filterCollections ||
!templateNote.hasLabel("template")) {
if (templateNote.hasLabel("collection") !== filterCollections) {
continue;
}

View File

@@ -20,7 +20,7 @@ class Options {
this.arr = arr;
}
get(key: OptionNames) {
get(key: string) {
return this.arr?.[key] as string;
}
@@ -40,7 +40,7 @@ class Options {
}
}
getInt(key: OptionNames) {
getInt(key: string) {
const value = this.arr?.[key];
if (typeof value === "number") {
return value;
@@ -52,7 +52,7 @@ class Options {
return null;
}
getFloat(key: OptionNames) {
getFloat(key: string) {
const value = this.arr?.[key];
if (typeof value !== "string") {
return null;
@@ -60,15 +60,15 @@ class Options {
return parseFloat(value);
}
is(key: OptionNames) {
is(key: string) {
return this.arr[key] === "true";
}
set(key: OptionNames, value: OptionValue) {
set(key: string, value: OptionValue) {
this.arr[key] = value;
}
async save(key: OptionNames, value: OptionValue) {
async save(key: string, value: OptionValue) {
this.set(key, value);
const payload: Record<string, OptionValue> = {};
@@ -85,7 +85,7 @@ class Options {
await server.put<void>("options", newValues);
}
async toggle(key: OptionNames) {
async toggle(key: string) {
await this.save(key, (!this.is(key)).toString());
}
}

View File

@@ -107,11 +107,11 @@ function makeToast(message: Message, title: string, text: string): ToastOptions
}
ws.subscribeToMessages(async (message) => {
if (!("taskType" in message) || message.taskType !== "protectNotes") {
if (message.taskType !== "protectNotes") {
return;
}
const isProtecting = message.data?.protect;
const isProtecting = message.data.protect;
const title = isProtecting ? t("protected_session.protecting-title") : t("protected_session.unprotecting-title");
if (message.type === "taskError") {

View File

@@ -119,6 +119,11 @@ describe("shortcuts", () => {
metaKey: options.metaKey || false
} as KeyboardEvent);
it("should match simple key shortcuts", () => {
const event = createKeyboardEvent({ key: "a", code: "KeyA" });
expect(matchesShortcut(event, "a")).toBe(true);
});
it("should match shortcuts with modifiers", () => {
const event = createKeyboardEvent({ key: "a", code: "KeyA", ctrlKey: true });
expect(matchesShortcut(event, "ctrl+a")).toBe(true);
@@ -143,28 +148,6 @@ describe("shortcuts", () => {
expect(matchesShortcut(event, "a")).toBe(false);
});
it("should not match when no modifiers are used", () => {
const event = createKeyboardEvent({ key: "a", code: "KeyA" });
expect(matchesShortcut(event, "a")).toBe(false);
});
it("should match some keys even with no modifiers", () => {
// Bare function keys
let event = createKeyboardEvent({ key: "F1", code: "F1" });
expect(matchesShortcut(event, "F1")).toBeTruthy();
expect(matchesShortcut(event, "f1")).toBeTruthy();
// Function keys with shift
event = createKeyboardEvent({ key: "F1", code: "F1", shiftKey: true });
expect(matchesShortcut(event, "Shift+F1")).toBeTruthy();
// Special keys
for (const keyCode of [ "Delete", "Enter" ]) {
event = createKeyboardEvent({ key: keyCode, code: keyCode });
expect(matchesShortcut(event, keyCode), `Key ${keyCode}`).toBeTruthy();
}
});
it("should handle alternative modifier names", () => {
const ctrlEvent = createKeyboardEvent({ key: "a", code: "KeyA", ctrlKey: true });
expect(matchesShortcut(ctrlEvent, "control+a")).toBe(true);

View File

@@ -36,19 +36,10 @@ const keyMap: { [key: string]: string[] } = {
};
// Function keys
const functionKeyCodes: string[] = [];
for (let i = 1; i <= 19; i++) {
const keyCode = `F${i}`;
functionKeyCodes.push(keyCode);
keyMap[`f${i}`] = [ keyCode ];
keyMap[`f${i}`] = [`F${i}`];
}
const KEYCODES_WITH_NO_MODIFIER = new Set([
"Delete",
"Enter",
...functionKeyCodes
]);
/**
* Check if IME (Input Method Editor) is composing
* This is used to prevent keyboard shortcuts from firing during IME composition
@@ -60,7 +51,7 @@ export function isIMEComposing(e: KeyboardEvent): boolean {
if (!e) {
return false;
}
// Standard check for composition state
// e.isComposing is true when IME is actively composing
// e.keyCode === 229 is a fallback for older browsers where 229 indicates IME processing
@@ -95,13 +86,13 @@ function bindElShortcut($el: JQuery<ElementType | Element>, keyboardShortcut: st
}
const e = evt as KeyboardEvent;
// Skip processing if IME is composing to prevent shortcuts from
// interfering with text input in CJK languages
if (isIMEComposing(e)) {
return;
}
if (matchesShortcut(e, keyboardShortcut)) {
e.preventDefault();
e.stopPropagation();
@@ -171,12 +162,6 @@ export function matchesShortcut(e: KeyboardEvent, shortcut: string): boolean {
const expectedShift = modifiers.includes('shift');
const expectedMeta = modifiers.includes('meta') || modifiers.includes('cmd') || modifiers.includes('command');
// Refuse key combinations that don't include modifiers because they interfere with the normal usage of the application.
// Some keys such as function keys are an exception.
if (!(expectedCtrl || expectedAlt || expectedShift || expectedMeta) && !KEYCODES_WITH_NO_MODIFIER.has(e.code)) {
return false;
}
return e.ctrlKey === expectedCtrl &&
e.altKey === expectedAlt &&
e.shiftKey === expectedShift &&

View File

@@ -61,11 +61,7 @@ export async function applySingleBlockSyntaxHighlight($codeBlock: JQuery<HTMLEle
highlightedText = highlightAuto(text);
} else if (normalizedMimeType) {
await ensureMimeTypesForHighlighting(normalizedMimeType);
try {
highlightedText = highlight(text, { language: normalizedMimeType });
} catch (e) {
console.warn("Unable to apply syntax highlight.", e);
}
highlightedText = highlight(text, { language: normalizedMimeType });
}
if (highlightedText) {
@@ -80,7 +76,7 @@ export async function ensureMimeTypesForHighlighting(mimeTypeHint?: string) {
// Load theme.
const currentThemeName = String(options.get("codeBlockTheme"));
await loadHighlightingTheme(currentThemeName);
loadHighlightingTheme(currentThemeName);
// Load mime types.
let mimeTypes: MimeType[];
@@ -102,16 +98,17 @@ export async function ensureMimeTypesForHighlighting(mimeTypeHint?: string) {
highlightingLoaded = true;
}
export async function loadHighlightingTheme(themeName: string) {
export function loadHighlightingTheme(themeName: string) {
const themePrefix = "default:";
let theme: Theme | null = null;
if (glob.device === "print") {
theme = Themes.vs;
} else if (themeName.includes(themePrefix)) {
if (themeName.includes(themePrefix)) {
theme = Themes[themeName.substring(themePrefix.length)];
}
if (!theme) {
theme = Themes.default;
}
await loadTheme(theme ?? Themes.default);
loadTheme(theme);
}
/**

View File

@@ -1,9 +1,10 @@
import ws from "./ws.js";
import utils from "./utils.js";
export interface ToastOptions {
id?: string;
icon: string;
title?: string;
title: string;
message: string;
delay?: number;
autohide?: boolean;
@@ -11,32 +12,20 @@ export interface ToastOptions {
}
function toast(options: ToastOptions) {
const $toast = $(options.title
? `\
<div class="toast" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header">
<strong class="me-auto">
<span class="bx bx-${options.icon}"></span>
<span class="toast-title"></span>
</strong>
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
</div>
<div class="toast-body"></div>
</div>`
: `
<div class="toast" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-icon">
const $toast = $(
`<div class="toast" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header">
<strong class="me-auto">
<span class="bx bx-${options.icon}"></span>
</div>
<div class="toast-body"></div>
<div class="toast-header">
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
</div>
</div>`
<span class="toast-title"></span>
</strong>
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
</div>
<div class="toast-body"></div>
</div>`
);
$toast.toggleClass("no-title", !options.title);
$toast.find(".toast-title").text(options.title ?? "");
$toast.find(".toast-title").text(options.title);
$toast.find(".toast-body").html(options.message);
if (options.id) {
@@ -81,6 +70,7 @@ function showMessage(message: string, delay = 2000) {
console.debug(utils.now(), "message:", message);
toast({
title: "Info",
icon: "check",
message: message,
autohide: true,
@@ -92,6 +82,7 @@ export function showError(message: string, delay = 10000) {
console.log(utils.now(), "error: ", message);
toast({
title: "Error",
icon: "alert",
message: message,
autohide: true,

View File

@@ -47,6 +47,27 @@ function parseDate(str: string) {
}
}
// Source: https://stackoverflow.com/a/30465299/4898894
function getMonthsInDateRange(startDate: string, endDate: string) {
const start = startDate.split("-");
const end = endDate.split("-");
const startYear = parseInt(start[0]);
const endYear = parseInt(end[0]);
const dates: string[] = [];
for (let i = startYear; i <= endYear; i++) {
const endMonth = i != endYear ? 11 : parseInt(end[1]) - 1;
const startMon = i === startYear ? parseInt(start[1]) - 1 : 0;
for (let j = startMon; j <= endMonth; j = j > 12 ? j % 12 || 11 : j + 1) {
const month = j + 1;
const displayMonth = month < 10 ? "0" + month : month;
dates.push([i, displayMonth].join("-"));
}
}
return dates;
}
function padNum(num: number) {
return `${num <= 9 ? "0" : ""}${num}`;
}
@@ -128,18 +149,6 @@ export function isElectron() {
return !!(window && window.process && window.process.type);
}
/**
* Returns `true` if the client is running as a PWA, otherwise `false`.
*/
export function isPWA() {
return (
window.matchMedia('(display-mode: standalone)').matches
|| window.matchMedia('(display-mode: window-controls-overlay)').matches
|| window.navigator.standalone
|| window.navigator.windowControlsOverlay
);
}
export function isMac() {
return navigator.platform.indexOf("Mac") > -1;
}
@@ -487,7 +496,7 @@ function sleep(time_ms: number) {
});
}
export function escapeRegExp(str: string) {
function escapeRegExp(str: string) {
return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
}
@@ -869,23 +878,12 @@ export function getErrorMessage(e: unknown) {
}
}
/**
* Handles left or right placement of e.g. tooltips in case of right-to-left languages. If the current language is a RTL one, then left and right are swapped. Other directions are unaffected.
* @param placement a string optionally containing a "left" or "right" value.
* @returns a left/right value swapped if needed, or the same as input otherwise.
*/
export function handleRightToLeftPlacement<T extends string>(placement: T) {
if (!glob.isRtl) return placement;
if (placement === "left") return "right";
if (placement === "right") return "left";
return placement;
}
export default {
reloadFrontendApp,
restartDesktopApp,
reloadTray,
parseDate,
getMonthsInDateRange,
formatDateISO,
formatDateTime,
formatTimeInterval,
@@ -893,7 +891,6 @@ export default {
localNowDateTime,
now,
isElectron,
isPWA,
isMac,
isCtrlKey,
assertArguments,

View File

@@ -6,11 +6,9 @@ import frocaUpdater from "./froca_updater.js";
import appContext from "../components/app_context.js";
import { t } from "./i18n.js";
import type { EntityChange } from "../server_types.js";
import { WebSocketMessage } from "@triliumnext/commons";
import toast from "./toast.js";
type MessageHandler = (message: WebSocketMessage) => void;
let messageHandlers: MessageHandler[] = [];
type MessageHandler = (message: any) => void;
const messageHandlers: MessageHandler[] = [];
let ws: WebSocket;
let lastAcceptedEntityChangeId = window.glob.maxEntityChangeIdAtLoad;
@@ -49,14 +47,10 @@ function logInfo(message: string) {
window.logError = logError;
window.logInfo = logInfo;
export function subscribeToMessages(messageHandler: MessageHandler) {
function subscribeToMessages(messageHandler: MessageHandler) {
messageHandlers.push(messageHandler);
}
export function unsubscribeToMessage(messageHandler: MessageHandler) {
messageHandlers = messageHandlers.filter(handler => handler !== messageHandler);
}
// used to serialize frontend update operations
let consumeQueuePromise: Promise<void> | null = null;
@@ -279,17 +273,13 @@ function connectWebSocket() {
async function sendPing() {
if (Date.now() - lastPingTs > 30000) {
console.warn(utils.now(), "Lost websocket connection to the backend");
toast.showPersistent({
id: "lost-websocket-connection",
title: t("ws.lost-websocket-connection-title"),
message: t("ws.lost-websocket-connection-message"),
icon: "no-signal"
});
console.log(
utils.now(),
"Lost websocket connection to the backend. If you keep having this issue repeatedly, you might want to check your reverse proxy (nginx, apache) configuration and allow/unblock WebSocket."
);
}
if (ws.readyState === ws.OPEN) {
toast.closePersistent("lost-websocket-connection");
ws.send(
JSON.stringify({
type: "ping",
@@ -304,8 +294,6 @@ async function sendPing() {
}
setTimeout(() => {
if (glob.device === "print") return;
ws = connectWebSocket();
lastPingTs = Date.now();

View File

@@ -1,3 +1,4 @@
import "bootstrap/dist/css/bootstrap.min.css";
import "./stylesheets/auth.css";
// @TriliumNextTODO: is this even needed anymore?

View File

@@ -1,6 +1,7 @@
import "jquery";
import utils from "./services/utils.js";
import ko from "knockout";
import "bootstrap/dist/css/bootstrap.min.css";
// TriliumNextTODO: properly make use of below types
// type SetupModelSetupType = "new-document" | "sync-from-desktop" | "sync-from-server" | "";

View File

@@ -60,7 +60,7 @@
appearance: none;
text-align: center;
border: 0;
border-inline-start: unset;
border-left: unset;
background-color: var(--menu-background-color);
font-weight: bold;
outline: 0;
@@ -102,7 +102,7 @@
content: '';
position: absolute;
top: 0;
inset-inline-end: 0;
right: 0;
bottom: 0;
width: 1px;
background-color: var(--main-border-color);

View File

@@ -299,7 +299,7 @@
content: '';
position: absolute;
top: 0;
inset-inline-start: -100%;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, var(--hover-item-background-color, rgba(0, 0, 0, 0.03)), transparent);
@@ -406,10 +406,10 @@
@keyframes shimmer {
0% {
inset-inline-start: -100%;
left: -100%;
}
100% {
inset-inline-start: 100%;
left: 100%;
}
}

View File

@@ -0,0 +1,322 @@
:root {
--main-background-color: white;
--root-background: var(--main-background-color);
--launcher-pane-background-color: var(--main-background-color);
--main-text-color: black;
--input-text-color: var(--main-text-color);
--print-font-size: 11pt;
}
@page {
margin: 2cm;
}
.ck-content {
font-size: var(--print-font-size);
text-align: justify;
}
.note-detail-readonly-text {
padding: 0 !important;
}
.no-print,
.no-print *,
.tab-row-container,
.tab-row-widget,
.title-bar-buttons,
#launcher-pane,
#left-pane,
#center-pane > *:not(.split-note-container-widget),
#right-pane,
.title-row .note-icon-widget,
.title-row .button-widget,
.ribbon-container,
.promoted-attributes-widget,
.scroll-padding-widget,
.note-list-widget,
.spacer {
display: none !important;
}
body.mobile #mobile-sidebar-wrapper,
body.mobile .classic-toolbar-widget,
body.mobile .action-button {
display: none !important;
}
body.mobile #detail-container {
max-height: unset;
}
body.mobile .note-title-widget {
padding: 0 !important;
}
body,
#root-widget,
#rest-pane > div.component:first-child,
.note-detail-printable,
.note-detail-editable-text-editor {
height: unset !important;
overflow: auto;
}
.ck.ck-editor__editable_inline {
overflow: hidden !important;
}
.note-title-widget input,
.note-detail-editable-text,
.note-detail-editable-text-editor {
padding: 0 !important;
}
html,
body {
width: unset !important;
height: unset !important;
overflow: visible;
position: unset;
/* https://github.com/zadam/trilium/issues/3202 */
color: black;
}
#root-widget,
#horizontal-main-container,
#rest-pane,
#vertical-main-container,
#center-pane,
.split-note-container-widget,
.note-split:not(.hidden-ext),
body.mobile #mobile-rest-container {
display: block !important;
overflow: auto;
border-radius: 0 !important;
}
#center-pane,
#rest-pane,
.note-split,
body.mobile #detail-container {
width: unset !important;
max-width: unset !important;
}
.component {
contain: none !important;
}
/* Respect page breaks */
.page-break {
page-break-after: always;
break-after: always;
}
.page-break > * {
display: none !important;
}
.relation-map-wrapper {
height: 100vh !important;
}
.table thead th,
.table td,
.table th {
/* Fix center vertical alignment of table cells */
vertical-align: middle;
}
pre {
box-shadow: unset !important;
border: 0.75pt solid gray !important;
border-radius: 2pt !important;
}
th,
span[style] {
print-color-adjust: exact;
-webkit-print-color-adjust: exact;
}
/*
* Text note specific fixes
*/
.ck-widget {
outline: none !important;
}
.ck-placeholder,
.ck-widget__type-around,
.ck-widget__selection-handle {
display: none !important;
}
.ck-widget.table td.ck-editor__nested-editable.ck-editor__nested-editable_focused,
.ck-widget.table td.ck-editor__nested-editable:focus,
.ck-widget.table th.ck-editor__nested-editable.ck-editor__nested-editable_focused,
.ck-widget.table th.ck-editor__nested-editable:focus {
background: unset !important;
outline: unset !important;
}
.include-note .include-note-content {
max-height: unset !important;
overflow: unset !important;
}
/* TODO: This will break once we translate the language */
.ck-content pre[data-language="Auto-detected"]:after {
display: none !important;
}
/*
* Code note specific fixes.
*/
.note-detail-code pre {
border: unset !important;
border-radius: unset !important;
}
/*
* Links
*/
.note-detail-printable a {
text-decoration: none;
}
.note-detail-printable a:not([href^="#root/"]) {
text-decoration: underline;
color: #374a75;
}
.note-detail-printable a::after {
/* Hide the external link trailing arrow */
display: none !important;
}
/*
* TODO list check boxes
*/
.note-detail-printable .todo-list__label * {
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
@supports selector(.todo-list__label__description:has(*)) and (height: 1lh) {
.note-detail-printable .todo-list__label__description {
/* The percentage of the line height that the check box occupies */
--box-ratio: 0.75;
/* The size of the gap between the check box and the caption */
--box-text-gap: 0.25em;
--box-size: calc(1lh * var(--box-ratio));
--box-vert-offset: calc((1lh - var(--box-size)) / 2);
display: inline-block;
padding-left: calc(var(--box-size) + var(--box-text-gap));
/* Source: https://pictogrammers.com/library/mdi/icon/checkbox-blank-outline/ */
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'%3e%3cpath d='M19%2c3H5C3.89%2c3 3%2c3.89 3%2c5V19A2%2c2 0 0%2c0 5%2c21H19A2%2c2 0 0%2c0 21%2c19V5C21%2c3.89 20.1%2c3 19%2c3M19%2c5V19H5V5H19Z' /%3e%3c/svg%3e");
background-position: 0 var(--box-vert-offset);
background-size: var(--box-size);
background-repeat: no-repeat;
}
.note-detail-printable .todo-list__label:has(input[type="checkbox"]:checked) .todo-list__label__description {
/* Source: https://pictogrammers.com/library/mdi/icon/checkbox-outline/ */
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='currentColor'%3e%3cpath d='M19%2c3H5A2%2c2 0 0%2c0 3%2c5V19A2%2c2 0 0%2c0 5%2c21H19A2%2c2 0 0%2c0 21%2c19V5A2%2c2 0 0%2c0 19%2c3M19%2c5V19H5V5H19M10%2c17L6%2c13L7.41%2c11.58L10%2c14.17L16.59%2c7.58L18%2c9' /%3e%3c/svg%3e");
}
.note-detail-printable .todo-list__label input[type="checkbox"] {
display: none !important;
}
}
/*
* Blockquotes
*/
.note-detail-printable blockquote {
box-shadow: unset;
}
/*
* Figures
*/
.note-detail-printable figcaption {
--accented-background-color: transparent;
font-style: italic;
}
/*
* Footnotes
*/
.note-detail-printable .footnote-reference a,
.footnote-back-link a {
text-decoration: none;
}
/* Make the "^" link cover the whole area of the footnote item */
.footnote-section {
clear: both;
}
.note-detail-printable li.footnote-item {
position: relative;
width: fit-content;
}
.note-detail-printable .footnote-back-link,
.note-detail-printable .footnote-back-link *,
.note-detail-printable .footnote-back-link a {
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.note-detail-printable .footnote-back-link a {
color: transparent;
}
.note-detail-printable .footnote-content {
display: inline-block;
width: unset;
}
/*
* Widows and orphans
*/
p,
blockquote {
widows: 4;
orphans: 4;
}
pre > code {
widows: 6;
orphans: 6;
overflow: auto;
white-space: pre-wrap !important;
}
h1,
h2,
h3,
h4,
h5,
h6 {
page-break-after: avoid;
break-after: avoid;
}

View File

@@ -62,7 +62,7 @@
.note-detail-relation-map .endpoint {
position: absolute;
bottom: 37%;
inset-inline-end: 5px;
right: 5px;
width: 1em;
height: 1em;
background-color: #333;

View File

@@ -161,8 +161,7 @@ textarea,
color: var(--muted-text-color);
}
.form-group.disabled,
.form-checkbox.disabled {
.form-group.disabled {
opacity: 0.5;
pointer-events: none;
}
@@ -174,12 +173,12 @@ textarea,
/* Add a gap between consecutive radios / check boxes */
label.tn-radio + label.tn-radio,
label.tn-checkbox + label.tn-checkbox {
margin-inline-start: 12px;
margin-left: 12px;
}
label.tn-radio input[type="radio"],
label.tn-checkbox input[type="checkbox"] {
margin-inline-end: .5em;
margin-right: .5em;
}
#left-pane input,
@@ -226,7 +225,7 @@ samp {
.badge {
--bs-badge-color: var(--muted-text-color);
margin-inline-start: 8px;
margin-left: 8px;
background: var(--accented-background-color);
}
@@ -252,6 +251,10 @@ button.close:hover {
color: var(--main-text-color) !important;
}
.note-title[readonly] {
background: inherit;
}
.tdialog {
display: none;
}
@@ -290,11 +293,6 @@ button.close:hover {
pointer-events: none;
}
.icon-action.btn {
padding: 0 8px;
min-width: unset !important;
}
.ui-widget-content a:not(.ui-tabs-anchor) {
color: #337ab7 !important;
}
@@ -338,8 +336,8 @@ button kbd {
}
.ui-menu kbd {
margin-inline-start: 30px;
float: inline-end;
margin-left: 30px;
float: right;
}
.suppressed {
@@ -360,23 +358,24 @@ button kbd {
}
.dropdown-menu,
.tabulator-popup-container,
:root .excalidraw .popover {
.tabulator-popup-container {
color: var(--menu-text-color) !important;
font-size: inherit;
background: var(--menu-background-color) !important;
background-color: var(--menu-background-color) !important;
user-select: none;
-webkit-user-select: none;
--bs-dropdown-zindex: 999;
--bs-dropdown-link-active-bg: var(--active-item-background-color) !important;
}
.dropdown-menu .dropdown-divider {
break-before: avoid;
break-after: avoid;
}
body.desktop .dropdown-menu,
body.desktop .tabulator-popup-container,
:root .excalidraw .dropdown-menu .dropdown-menu-container,
:root .excalidraw .popover {
body.desktop .tabulator-popup-container {
border: 1px solid var(--dropdown-border-color);
column-rule: 1px solid var(--dropdown-border-color);
box-shadow: 0px 10px 20px rgba(0, 0, 0, var(--dropdown-shadow-opacity));
animation: dropdown-menu-opening 100ms ease-in;
}
@@ -395,7 +394,7 @@ body.desktop .tabulator-popup-container,
}
.dropend .dropdown-toggle::after {
margin-inline-start: 0.5em;
margin-left: 0.5em;
color: var(--muted-text-color);
}
@@ -406,7 +405,7 @@ body.desktop .tabulator-popup-container,
.dropdown-menu .disabled .disabled-tooltip {
pointer-events: all;
margin-inline-start: 8px;
margin-left: 8px;
font-size: 0.5em;
color: var(--disabled-tooltip-icon-color);
cursor: help;
@@ -418,18 +417,17 @@ body.desktop .tabulator-popup-container,
}
.dropdown-menu a:hover:not(.disabled),
.dropdown-item:hover:not(.disabled, .dropdown-container-item),
.tabulator-menu-item:hover,
:root .excalidraw .context-menu .context-menu-item:hover {
.dropdown-item:hover:not(.disabled, .dropdown-item-container),
.tabulator-menu-item:hover {
color: var(--hover-item-text-color) !important;
background-color: var(--hover-item-background-color) !important;
border-color: var(--hover-item-border-color) !important;
cursor: pointer;
}
.dropdown-container-item,
.dropdown-item.dropdown-container-item:hover,
.dropdown-container-item:active {
.dropdown-item-container,
.dropdown-item-container:hover,
.dropdown-item-container:active {
background: transparent;
cursor: default;
}
@@ -444,11 +442,9 @@ body #context-menu-container .dropdown-item > span {
align-items: center;
}
.dropdown-item span.keyboard-shortcut,
.dropdown-item *:not(.keyboard-shortcut) > kbd {
.dropdown-item span.keyboard-shortcut {
flex-grow: 1;
text-align: end;
padding-inline-start: 12px;
text-align: right;
}
.dropdown-menu kbd {
@@ -458,21 +454,16 @@ body #context-menu-container .dropdown-item > span {
box-shadow: none;
padding-bottom: 0;
padding: 0;
flex-grow: 1;
text-align: right;
}
.dropdown-item,
.dropdown-header,
:root .excalidraw .context-menu .context-menu-item:hover {
.dropdown-header {
color: var(--menu-text-color) !important;
border: 1px solid transparent !important;
}
/* This is a workaround for Firefox not supporting break-before / break-after: avoid on columns.
* It usually wraps a menu item followed by a separator / header and another menu item. */
.dropdown-no-break {
break-inside: avoid;
}
.dropdown-item.disabled,
.dropdown-item.disabled kbd {
color: #aaa !important;
@@ -480,9 +471,9 @@ body #context-menu-container .dropdown-item > span {
.dropdown-item.active,
.dropdown-item:focus {
color: var(--active-item-text-color);
background-color: var(--active-item-background-color);
border-color: var(--active-item-border-color);
color: var(--active-item-text-color) !important;
background-color: var(--active-item-background-color) !important;
border-color: var(--active-item-border-color) !important;
outline: none;
}
@@ -509,7 +500,7 @@ body #context-menu-container .dropdown-item > span {
body .cm-editor .cm-gutters {
background-color: inherit !important;
border-inline-end: none;
border-right: none;
}
body .cm-editor .cm-placeholder {
@@ -591,10 +582,6 @@ button.btn-sm {
z-index: 1000;
}
body[dir=rtl] .ck.ck-block-toolbar-button {
transform: translateX(-7px);
}
pre:not(.hljs) {
color: var(--main-text-color) !important;
white-space: pre-wrap;
@@ -613,11 +600,11 @@ pre:not(.hljs) {
pre > button.copy-button {
position: absolute;
top: var(--copy-button-margin-size);
inset-inline-end: var(--copy-button-margin-size);
right: var(--copy-button-margin-size);
}
:root pre:has(> button.copy-button) {
padding-inline-end: calc(var(--copy-button-width) + (var(--copy-button-margin-size) * 2));
padding-right: calc(var(--copy-button-width) + (var(--copy-button-margin-size) * 2));
}
pre > button.copy-button:hover {
@@ -643,31 +630,31 @@ pre > button.copy-button:active {
.full-text-search-button {
cursor: pointer;
font-size: 1.3em;
padding-inline-start: 5px;
padding-inline-end: 5px;
padding-left: 5px;
padding-right: 5px;
}
.input-clearer-button {
cursor: pointer;
font-size: 1.3em;
background: inherit !important;
padding-inline-start: 5px;
padding-inline-end: 5px;
padding-left: 5px;
padding-right: 5px;
}
.open-external-link-button {
cursor: pointer;
font-size: 1.3em;
padding-inline-start: 5px;
padding-inline-end: 5px;
padding-left: 5px;
padding-right: 5px;
padding-top: 8px;
}
.go-to-selected-note-button {
cursor: pointer;
font-size: 1.3em;
padding-inline-start: 4px;
padding-inline-end: 3px;
padding-left: 4px;
padding-right: 3px;
}
.go-to-selected-note-button.disabled,
@@ -680,7 +667,7 @@ pre > button.copy-button:active {
.note-autocomplete-input {
/* this is for seamless integration of "input clearer" button */
border-inline-end: 0;
border-right: 0;
}
table.promoted-attributes-in-tooltip {
@@ -713,10 +700,10 @@ table.promoted-attributes-in-tooltip th {
border-top-color: var(--main-border-color) !important;
}
.bs-tooltip-left .tooltip-arrow::before {
border-inline-start-color: var(--main-border-color) !important;
border-left-color: var(--main-border-color) !important;
}
.bs-tooltip-right .tooltip-arrow::before {
border-inline-end-color: var(--main-border-color) !important;
border-right-color: var(--main-border-color) !important;
}
.bs-tooltip-bottom .tooltip-arrow::after {
@@ -726,17 +713,17 @@ table.promoted-attributes-in-tooltip th {
border-top-color: var(--tooltip-background-color) !important;
}
.bs-tooltip-left .tooltip-arrow::after {
border-inline-start-color: var(--tooltip-background-color) !important;
border-left-color: var(--tooltip-background-color) !important;
}
.bs-tooltip-right .tooltip-arrow::after {
border-inline-end-color: var(--tooltip-background-color) !important;
border-right-color: var(--tooltip-background-color) !important;
}
.bs-tooltip-auto[data-popper-placement^="left"] .tooltip-arrow::before,
.bs-tooltip-left .tooltip-arrow::before {
inset-inline-start: -1px;
left: -1px;
border-width: 0.4rem 0 0.4rem 0.4rem;
border-inline-start-color: var(--main-border-color) !important;
border-left-color: var(--main-border-color) !important;
}
.bs-tooltip-auto[data-popper-placement^="bottom"] .tooltip-arrow::before,
@@ -748,9 +735,9 @@ table.promoted-attributes-in-tooltip th {
.bs-tooltip-auto[data-popper-placement^="right"] .tooltip-arrow::before,
.bs-tooltip-right .tooltip-arrow::before {
inset-inline-end: -1px;
right: -1px;
border-width: 0.4rem 0.4rem 0.4rem 0;
border-inline-end-color: var(--main-border-color) !important;
border-right-color: var(--main-border-color) !important;
}
.bs-tooltip-auto[data-popper-placement^="top"] .tooltip-arrow::before,
@@ -762,9 +749,9 @@ table.promoted-attributes-in-tooltip th {
.bs-tooltip-auto[data-popper-placement^="left"] .tooltip-arrow::after,
.bs-tooltip-left .tooltip-arrow::after {
inset-inline-start: -1px;
left: -1px;
border-width: 0.4rem 0 0.4rem 0.4rem;
border-inline-start-color: var(--tooltip-background-color) !important;
border-left-color: var(--tooltip-background-color) !important;
}
.bs-tooltip-auto[data-popper-placement^="bottom"] .tooltip-arrow::after,
@@ -776,9 +763,9 @@ table.promoted-attributes-in-tooltip th {
.bs-tooltip-auto[data-popper-placement^="right"] .tooltip-arrow::after,
.bs-tooltip-right .tooltip-arrow::after {
inset-inline-end: -1px;
right: -1px;
border-width: 0.4rem 0.4rem 0.4rem 0;
border-inline-end-color: var(--tooltip-background-color) !important;
border-right-color: var(--tooltip-background-color) !important;
}
.bs-tooltip-auto[data-popper-placement^="top"] .tooltip-arrow::after,
@@ -797,7 +784,7 @@ table.promoted-attributes-in-tooltip th {
background-color: var(--tooltip-background-color) !important;
border: 1px solid var(--main-border-color);
border-radius: 5px;
text-align: start;
text-align: left;
color: var(--main-text-color) !important;
max-width: 500px;
box-shadow: 10px 10px 93px -25px #aaaaaa;
@@ -830,7 +817,7 @@ table.promoted-attributes-in-tooltip th {
.note-tooltip-content .open-popup-button {
position: absolute;
inset-inline-end: 15px;
right: 15px;
bottom: 8px;
font-size: 1.2em;
color: inherit;
@@ -850,7 +837,7 @@ table.promoted-attributes-in-tooltip th {
}
.tooltip-inner figure.image-style-side {
float: inline-end;
float: right;
}
.tooltip.show {
@@ -899,7 +886,7 @@ table.promoted-attributes-in-tooltip th {
.aa-dropdown-menu .aa-suggestion .text {
display: inline-block;
width: calc(100% - 20px);
padding-inline-start: 4px;
padding-left: 4px;
}
.aa-dropdown-menu .aa-suggestion .search-result-title {
@@ -925,7 +912,7 @@ table.promoted-attributes-in-tooltip th {
}
.help-button {
float: inline-end;
float: right;
background: none;
font-weight: 900;
color: orange;
@@ -1013,7 +1000,7 @@ svg.ck-icon .note-icon {
--ck-content-line-height: var(--bs-body-line-height);
}
:root .ck-content .table table:not(.layout-table) th {
.ck-content .table table th {
background-color: var(--accented-background-color);
}
@@ -1042,7 +1029,7 @@ svg.ck-icon .note-icon {
counter-increment: footnote-counter;
display: flex;
list-style: none;
margin-inline-start: 0.5em;
margin-left: 0.5em;
}
.ck-content .footnote-item > * {
@@ -1050,13 +1037,13 @@ svg.ck-icon .note-icon {
}
.ck-content .footnote-back-link {
margin-inline-end: 0.1em;
margin-right: 0.1em;
position: relative;
top: -0.2em;
}
.ck-content .footnotes .footnote-back-link > sup {
margin-inline-end: 0;
margin-right: 0;
}
.ck-content .footnote-item:before {
@@ -1064,8 +1051,8 @@ svg.ck-icon .note-icon {
display: inline-block;
min-width: fit-content;
position: relative;
inset-inline-end: 0.2em;
text-align: end;
right: 0.2em;
text-align: right;
}
.ck-content .footnote-content {
@@ -1081,11 +1068,11 @@ svg.ck-icon .note-icon {
}
#options-dialog input[type="number"] {
text-align: end;
text-align: right;
}
.help-cards ul {
padding-inline-start: 20px;
padding-left: 20px;
}
.help-cards kbd {
@@ -1150,26 +1137,6 @@ a.external:not(.no-arrow):after, a[href^="http://"]:not(.no-arrow):after, a[href
overflow: hidden;
}
.toast.no-title {
display: flex;
flex-direction: row;
}
.toast.no-title .toast-icon {
display: flex;
align-items: center;
padding: var(--bs-toast-padding-y) var(--bs-toast-padding-x);
}
.toast.no-title .toast-body {
padding-inline-start: 0;
padding-inline-end: 0;
}
.toast.no-title .toast-header {
background-color: unset !important;
}
.ck-mentions .ck-button {
font-size: var(--detail-font-size) !important;
padding: 5px;
@@ -1283,8 +1250,8 @@ a.external:not(.no-arrow):after, a[href^="http://"]:not(.no-arrow):after, a[href
#context-menu-cover.show {
position: fixed;
top: 0;
inset-inline-start: 0;
inset-inline-end: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1000;
background: rgba(0, 0, 0, 0.1);
@@ -1297,8 +1264,8 @@ a.external:not(.no-arrow):after, a[href^="http://"]:not(.no-arrow):after, a[href
body.mobile #context-menu-container.mobile-bottom-menu {
position: fixed !important;
inset-inline-start: 0 !important;
inset-inline-end: 0 !important;
left: 0 !important;
right: 0 !important;
bottom: 0 !important;
top: unset !important;
max-height: 70vh;
@@ -1348,7 +1315,7 @@ body.desktop li.dropdown-submenu:hover > ul.dropdown-menu {
.dropdown-submenu > .dropdown-menu {
top: 0;
inset-inline-start: calc(100% - 2px); /* -2px, otherwise there's a small gap between menu and submenu where the hover can disappear */
left: calc(100% - 2px); /* -2px, otherwise there's a small gap between menu and submenu where the hover can disappear */
margin-top: -10px;
min-width: 15rem;
/* to make submenu scrollable https://github.com/zadam/trilium/issues/3136 */
@@ -1357,7 +1324,7 @@ body.desktop li.dropdown-submenu:hover > ul.dropdown-menu {
}
body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
inset-inline-start: calc(-100% + 10px);
left: calc(-100% + 10px);
}
.right-dropdown-widget {
@@ -1423,7 +1390,7 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
.ck.ck-slash-command-button__text-part,
.ck.ck-template-form__text-part {
margin-inline-start: 0.5em;
margin-left: 0.5em;
line-height: 1.2em !important;
}
@@ -1454,8 +1421,8 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
}
.area-expander-text {
padding-inline-start: 20px;
padding-inline-end: 20px;
padding-left: 20px;
padding-right: 20px;
white-space: nowrap;
}
@@ -1501,7 +1468,7 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
cursor: pointer;
border: none;
color: var(--launcher-pane-text-color);
background-color: transparent;
background: transparent;
flex-shrink: 0;
}
@@ -1542,16 +1509,16 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
position: fixed !important;
bottom: calc(var(--mobile-bottom-offset) + var(--launcher-pane-size)) !important;
top: unset !important;
inset-inline-start: 0 !important;
inset-inline-end: 0 !important;
left: 0 !important;
right: 0 !important;
transform: unset !important;
}
#mobile-sidebar-container {
position: fixed;
top: 0;
inset-inline-start: 0;
inset-inline-end: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1000;
transition: background-color 250ms ease-in-out;
@@ -1566,7 +1533,7 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
#mobile-sidebar-wrapper {
position: absolute;
top: 0;
inset-inline-start: 0;
left: 0;
bottom: 0;
width: 85vw;
padding-top: env(safe-area-inset-top);
@@ -1598,8 +1565,8 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
body.mobile .modal-dialog {
position: fixed;
bottom: 0;
inset-inline-start: 0;
inset-inline-end: 0;
left: 0;
right: 0;
margin: 0 !important;
max-height: 85vh;
display: flex;
@@ -1757,8 +1724,8 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
display: flex;
flex-shrink: 0;
flex-direction: column;
margin-inline-start: 10px;
margin-inline-end: 5px;
margin-left: 10px;
margin-right: 5px;
}
#right-pane .card-header {
@@ -1798,7 +1765,7 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
}
#right-pane .card-body ul {
padding-inline-start: 25px;
padding-left: 25px;
margin-bottom: 5px;
}
@@ -1809,8 +1776,8 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
}
.note-split {
margin-inline-start: auto;
margin-inline-end: auto;
margin-left: auto;
margin-right: auto;
}
.note-split.full-content-width {
@@ -1829,7 +1796,7 @@ button.close:hover {
.reference-link .bx {
position: relative;
top: 1px;
margin-inline-end: 3px;
margin-right: 3px;
}
.options-section:first-of-type h4 {
@@ -1867,7 +1834,7 @@ textarea {
.attachment-help-button {
display: inline-block;
margin-inline-start: 10px;
margin-left: 10px;
vertical-align: middle;
font-size: 1em;
}
@@ -1905,6 +1872,11 @@ textarea {
width: 100%;
}
.jump-to-note-results .aa-dropdown-menu .aa-suggestion:hover,
.jump-to-note-results .aa-dropdown-menu .aa-cursor {
background-color: var(--hover-item-background-color, #f8f9fa);
}
/* Command palette styling */
.jump-to-note-dialog .command-suggestion {
display: flex;
@@ -1975,7 +1947,7 @@ textarea {
}
body.electron.platform-darwin:not(.native-titlebar) .tab-row-container {
padding-inline-start: 1em;
padding-left: 1em;
}
#tab-row-left-spacer {
@@ -1983,12 +1955,8 @@ body.electron.platform-darwin:not(.native-titlebar) .tab-row-container {
-webkit-app-region: drag;
}
body.electron.platform-darwin:not(.native-titlebar) #tab-row-left-spacer {
width: 80px;
}
.tab-row-widget {
padding-inline-end: calc(100vw - env(titlebar-area-width, 100vw));
padding-right: calc(100vw - env(titlebar-area-width, 100vw));
}
.tab-row-container .toggle-button {
@@ -2038,20 +2006,16 @@ body.zen .ribbon-container:not(:has(.classic-toolbar-widget.visible)),
body.zen .ribbon-container:has(.classic-toolbar-widget.visible) .ribbon-top-row,
body.zen .ribbon-container .ribbon-body:not(:has(.classic-toolbar-widget.visible)),
body.zen .note-icon-widget,
body.zen .title-row .icon-action,
body.zen .title-row .button-widget,
body.zen .floating-buttons-children > *:not(.bx-edit-alt),
body.zen .action-button {
display: none !important;
}
body.zen .split-note-container-widget > .gutter {
display: unset !important;
}
body.zen #launcher-pane {
position: absolute !important;
top: 0 !important;
inset-inline-end: 0 !important;
right: 0 !important;
width: 64px !important;
height: 64px !important;
background: transparent !important;
@@ -2062,8 +2026,8 @@ body.zen .title-row {
display: block !important;
height: unset !important;
-webkit-app-region: drag;
padding-inline-start: env(titlebar-area-x);
padding-inline-end: calc(100vw - env(titlebar-area-width, 100vw) + 2.5em);
padding-left: env(titlebar-area-x);
padding-right: calc(100vw - env(titlebar-area-width, 100vw) + 2.5em);
}
body.zen .floating-buttons {
@@ -2071,7 +2035,7 @@ body.zen .floating-buttons {
}
body.zen .floating-buttons-children {
inset-inline-end: 0;
right: 0;
}
body.zen .floating-buttons-children .button-widget {
@@ -2230,7 +2194,7 @@ footer.webview-footer button {
.chat-input {
width: 100%;
resize: none;
padding-inline-end: 40px;
padding-right: 40px;
}
.chat-buttons {
@@ -2286,13 +2250,14 @@ footer.webview-footer button {
.admonition {
--accent-color: var(--card-border-color);
background: color-mix(in srgb, var(--accent-color) 15%, transparent);
border: 1px solid var(--accent-color);
box-shadow: var(--card-box-shadow);
background: var(--card-background-color);
border-radius: 0.5em;
padding: 1em;
margin: 1.25em 0;
position: relative;
padding-inline-start: 2.5em;
padding-left: 2.5em;
overflow: hidden;
}
@@ -2305,7 +2270,7 @@ footer.webview-footer button {
font-family: boxicons !important;
position: absolute;
top: 1em;
inset-inline-start: 1em;
left: 1em;
}
.admonition.note { --accent-color: var(--admonition-note-accent-color); }
@@ -2331,18 +2296,18 @@ footer.webview-footer button {
display: flex;
align-items: center;
font-size: 0.9em;
margin-inline-end: 15px;
margin-right: 15px;
cursor: pointer;
}
.chat-option input[type="checkbox"] {
margin-inline-end: 5px;
margin-right: 5px;
}
/* Style for thinking process in chat responses */
.thinking-process {
background-color: rgba(0, 0, 0, 0.05);
border-inline-start: 3px solid var(--main-text-color);
border-left: 3px solid var(--main-text-color);
padding: 10px;
margin: 10px 0;
border-radius: 4px;
@@ -2350,23 +2315,23 @@ footer.webview-footer button {
.thinking-step {
margin-bottom: 8px;
padding-inline-start: 10px;
padding-left: 10px;
}
.thinking-step.observation {
border-inline-start: 2px solid #69c7ff;
border-left: 2px solid #69c7ff;
}
.thinking-step.hypothesis {
border-inline-start: 2px solid #9839f7;
border-left: 2px solid #9839f7;
}
.thinking-step.evidence {
border-inline-start: 2px solid #40c025;
border-left: 2px solid #40c025;
}
.thinking-step.conclusion {
border-inline-start: 2px solid #e2aa03;
border-left: 2px solid #e2aa03;
font-weight: bold;
}
@@ -2381,17 +2346,17 @@ footer.webview-footer button {
.content-floating-buttons.top-left {
top: 10px;
inset-inline-start: 10px;
left: 10px;
}
.content-floating-buttons.bottom-left {
bottom: 10px;
inset-inline-start: 10px;
left: 10px;
}
.content-floating-buttons.bottom-right {
bottom: 10px;
inset-inline-end: 10px;
right: 10px;
}
.content-floating-buttons button.bx {
@@ -2422,14 +2387,4 @@ footer.webview-footer button {
.revision-diff-removed {
background: rgba(255, 100, 100, 0.5);
text-decoration: line-through;
}
iframe.print-iframe {
position: absolute;
top: 0;
left: -600px;
right: -600px;
bottom: 0;
width: 0;
height: 0;
}

View File

@@ -67,13 +67,13 @@
}
.tabulator div.tabulator-header .tabulator-frozen.tabulator-frozen-left {
margin-inline-start: var(--cell-editing-border-width);
margin-left: var(--cell-editing-border-width);
}
.tabulator div.tabulator-header .tabulator-col,
.tabulator div.tabulator-header .tabulator-frozen.tabulator-frozen-left {
background: var(--col-header-background-color);
border-inline-end: var(--col-header-separator-border);
border-right: var(--col-header-separator-border);
}
/* Table body */
@@ -90,8 +90,8 @@
}
.tabulator-row .tabulator-cell input {
padding-inline-start: var(--cell-horiz-padding-size) !important;
padding-inline-end: var(--cell-horiz-padding-size) !important;
padding-left: var(--cell-horiz-padding-size) !important;
padding-right: var(--cell-horiz-padding-size) !important;
}
.tabulator-row {
@@ -117,12 +117,12 @@
/* Cell */
.tabulator-row .tabulator-cell.tabulator-frozen.tabulator-frozen-left {
margin-inline-end: var(--cell-editing-border-width);
margin-right: var(--cell-editing-border-width);
}
.tabulator-row .tabulator-cell.tabulator-frozen.tabulator-frozen-left,
.tabulator-row .tabulator-cell {
border-inline-end-color: transparent;
border-right-color: transparent;
}
.tabulator-row .tabulator-cell:not(.tabulator-editable) {
@@ -156,14 +156,14 @@
/* Align items without children/expander to the ones with. */
.tabulator-cell[tabulator-field="title"] > span:first-child, /* 1st level */
.tabulator-cell[tabulator-field="title"] > div:first-child + span { /* sub-level */
padding-inline-start: 21px;
padding-left: 21px;
}
/* Checkbox cells */
.tabulator .tabulator-cell:has(svg),
.tabulator .tabulator-cell:has(input[type="checkbox"]) {
padding-inline-start: 8px;
padding-left: 8px;
display: inline-flex;
flex-direction: column;
justify-content: center;

View File

@@ -1,16 +1,16 @@
:root {
--theme-style: dark;
--main-font-family: Montserrat, sans-serif;
--main-font-family: Montserrat;
--main-font-size: normal;
--tree-font-family: Montserrat, sans-serif;
--tree-font-family: Montserrat;
--tree-font-size: normal;
--detail-font-family: Montserrat, sans-serif;
--detail-font-family: Montserrat;
--detail-font-size: normal;
--monospace-font-family: JetBrainsLight, monospace;
--monospace-font-family: JetBrainsLight;
--monospace-font-size: normal;
--main-background-color: #333;
@@ -82,10 +82,6 @@ body ::-webkit-calendar-picker-indicator {
filter: invert(1);
}
#left-pane .fancytree-node.tinted {
--custom-color: var(--dark-theme-custom-color);
}
.excalidraw.theme--dark {
--theme-filter: invert(80%) hue-rotate(180deg) !important;
}

View File

@@ -5,16 +5,16 @@ html {
/* either light or dark, colored theme with darker tones are also dark, used e.g. for note map node colors */
--theme-style: light;
--main-font-family: Montserrat, sans-serif;
--main-font-family: Montserrat;
--main-font-size: normal;
--tree-font-family: Montserrat, sans-serif;
--tree-font-family: Montserrat;
--tree-font-size: normal;
--detail-font-family: Montserrat, sans-serif;
--detail-font-family: Montserrat;
--detail-font-size: normal;
--monospace-font-family: JetBrainsLight, monospace;
--monospace-font-family: JetBrainsLight;
--monospace-font-size: normal;
--main-background-color: white;
@@ -81,7 +81,3 @@ html {
--mermaid-theme: default;
--native-titlebar-background: #ffffff00;
}
#left-pane .fancytree-node.tinted {
--custom-color: var(--light-theme-custom-color);
}

View File

@@ -152,7 +152,7 @@
--launcher-pane-horiz-border-color: rgb(22, 22, 22);
--launcher-pane-horiz-background-color: #282828;
--launcher-pane-horiz-text-color: #b8b8b8;
--launcher-pane-horiz-text-color: #909090;
--launcher-pane-horiz-button-hover-color: #ffffff;
--launcher-pane-horiz-button-hover-background: #ffffff1c;
--launcher-pane-horiz-button-hover-shadow: unset;
@@ -160,9 +160,6 @@
--launcher-pane-horiz-background-color-bgfx: #ffffff17; /* When background effects enabled */
--launcher-pane-horiz-border-color-bgfx: #00000080; /* When background effects enabled */
--global-menu-update-available-badge-background-color: #7dbe61;
--global-menu-update-available-badge-color: black;
--protected-session-active-icon-color: #8edd8e;
--sync-status-error-pulse-color: #f47871;
@@ -175,10 +172,9 @@
--tab-close-button-hover-background: #a45353;
--tab-close-button-hover-color: white;
--active-tab-background-color: #ffffff1c;
--active-tab-hover-background-color: var(--active-tab-background-color);
--active-tab-icon-color: #a9a9a9;
--active-tab-text-color: #ffffffcd;
--active-tab-shadow: 3px 3px 6px rgba(0, 0, 0, 0.2), -1px -1px 3px rgba(0, 0, 0, 0.4);
--active-tab-dragging-shadow: var(--active-tab-shadow), 0 0 20px rgba(0, 0, 0, 0.4);
@@ -268,15 +264,6 @@
* Dark color scheme tweaks
*/
#left-pane .fancytree-node.tinted {
--custom-color: var(--dark-theme-custom-color);
/* The background color of the active item in the note tree.
* The --custom-color-hue variable contains the hue of the user-selected note color.
* This value is unset for gray tones. */
--custom-bg-color: hsl(var(--custom-color-hue), 20%, 33%, 0.4);
}
body ::-webkit-calendar-picker-indicator {
filter: invert(1);
}
@@ -287,4 +274,4 @@ body ::-webkit-calendar-picker-indicator {
body .todo-list input[type="checkbox"]:not(:checked):before {
border-color: var(--muted-text-color) !important;
}
}

View File

@@ -127,7 +127,7 @@
--left-pane-item-selected-color: black;
--left-pane-item-selected-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2);
--left-pane-item-action-button-background: rgba(0, 0, 0, 0.11);
--left-pane-item-action-button-color: var(--left-pane-text-color);
--left-pane-item-action-button-color: inherit;
--left-pane-item-action-button-hover-background: white;
--left-pane-item-action-button-hover-shadow: 2px 2px 3px rgba(0, 0, 0, 0.15);
--left-pane-item-selected-action-button-hover-shadow: 2px 2px 10px rgba(0, 0, 0, 0.25);
@@ -153,9 +153,6 @@
--launcher-pane-horiz-background-color-bgfx: #ffffffb3; /* When background effects enabled */
--launcher-pane-horiz-border-color-bgfx: #00000026; /* When background effects enabled */
--global-menu-update-available-badge-background-color: #4fa450;
--global-menu-update-available-badge-color: white;
--protected-session-active-icon-color: #16b516;
--sync-status-error-pulse-color: #ff5528;
@@ -168,10 +165,9 @@
--tab-close-button-hover-background: #c95a5a;
--tab-close-button-hover-color: white;
--active-tab-background-color: white;
--active-tab-hover-background-color: var(--active-tab-background-color);
--active-tab-icon-color: gray;
--active-tab-text-color: black;
--active-tab-shadow: 3px 3px 6px rgba(0, 0, 0, 0.1), -1px -1px 3px rgba(0, 0, 0, 0.05);
--active-tab-dragging-shadow: var(--active-tab-shadow), 0 0 20px rgba(0, 0, 0, 0.1);
@@ -261,13 +257,5 @@
--ck-editor-toolbar-button-on-color: black;
--ck-editor-toolbar-button-on-shadow: none;
--ck-editor-toolbar-dropdown-button-open-background: #0000000f;
}
#left-pane .fancytree-node.tinted {
--custom-color: var(--light-theme-custom-color);
/* The background color of the active item in the note tree.
* The --custom-color-hue variable contains the hue of the user-selected note color.
* This value is unset for gray tones. */
--custom-bg-color: hsl(var(--custom-color-hue), 37%, 89%, 1);
}

View File

@@ -4,7 +4,6 @@
@import url(./pages.css);
@import url(./ribbon.css);
@import url(./notes/text.css);
@import url(./notes/canvas.css);
@import url(./notes/collections/table.css);
@font-face {
@@ -27,7 +26,7 @@
--detail-font-family: var(--main-font-family);
--detail-font-size: normal;
--monospace-font-family: JetBrainsLight, monospace;
--monospace-font-family: JetBrainsLight;
--monospace-font-size: normal;
--left-pane-item-selected-shadow-size: 2px;
@@ -82,20 +81,6 @@
/* Theme capabilities */
--tab-note-icons: true;
/* To ensure that a tree item's custom color remains sufficiently contrasted and readable,
* the color is adjusted based on the current color scheme (light or dark). The lightness
* component of the color represented in the CIELAB color space, will be
* constrained to a certain percentage defined below.
*
* Note: the tree background may vary when background effects are enabled, so it is recommended
* to maintain a higher contrast margin than on the usual note tree solid background. */
/* The maximum perceptual lightness for the custom color in the light theme (%): */
--tree-item-light-theme-max-color-lightness: 60;
/* The minimum perceptual lightness for the custom color in the dark theme (%): */
--tree-item-dark-theme-min-color-lightness: 65;
}
body.backdrop-effects-disabled {
@@ -111,13 +96,16 @@ body.backdrop-effects-disabled {
* supported when this class is used.
*/
.dropdown-menu:not(.static),
:root .excalidraw .popover {
.dropdown-menu:not(.static) {
border-radius: var(--dropdown-border-radius);
padding: var(--padding, var(--menu-padding-size)) !important;
padding: var(--menu-padding-size) !important;
font-size: 0.9rem !important;
}
.dropdown-menu {
--scrollbar-background-color: var(--menu-background-color);
}
body.mobile .dropdown-menu {
backdrop-filter: var(--dropdown-backdrop-filter);
border-radius: var(--dropdown-border-radius);
@@ -130,15 +118,14 @@ body.mobile .dropdown-menu .dropdown-menu {
}
body.desktop .dropdown-menu::before,
:root .ck.ck-dropdown__panel::before,
:root .excalidraw .popover::before {
:root .ck.ck-dropdown__panel::before {
content: "";
backdrop-filter: var(--dropdown-backdrop-filter);
border-radius: var(--dropdown-border-radius);
position: absolute;
top: 0;
inset-inline-start: 0;
inset-inline-end: 0;
left: 0;
right: 0;
bottom: 0;
z-index: -1;
}
@@ -165,32 +152,14 @@ body.desktop .dropdown-submenu .dropdown-menu {
}
.dropdown-item,
body.mobile .dropdown-submenu .dropdown-toggle,
.excalidraw .context-menu .context-menu-item {
--menu-item-start-padding: 8px;
--menu-item-end-padding: 22px;
--menu-item-vertical-padding: 2px;
padding-top: var(--menu-item-vertical-padding) !important;
padding-bottom: var(--menu-item-vertical-padding) !important;
padding-inline-start: var(--menu-item-start-padding) !important;
padding-inline-end: var(--menu-item-end-padding) !important;
body.mobile .dropdown-submenu .dropdown-toggle {
padding: 2px 2px 2px 8px !important;
padding-inline-end: 16px !important;
/* Note: the right padding should also accommodate the submenu arrow. */
border-radius: 6px;
cursor: default !important;
}
:root .dropdown-item:focus-visible {
outline: 2px solid var(--input-focus-outline-color) !important;
background-color: transparent;
color: unset;
}
:root .dropdown-item:active {
background: unset;
}
body.mobile .dropdown-submenu {
padding: 0 !important;
}
@@ -227,8 +196,7 @@ html body .dropdown-item[disabled] {
}
/* Menu item keyboard shortcut */
.dropdown-item kbd,
.excalidraw .context-menu-item__shortcut {
.dropdown-item kbd {
font-family: unset !important;
font-size: unset !important;
color: var(--menu-item-keyboard-shortcut-color) !important;
@@ -237,23 +205,21 @@ html body .dropdown-item[disabled] {
.dropdown-item span.keyboard-shortcut {
color: var(--menu-item-keyboard-shortcut-color) !important;
margin-inline-start: 16px;
margin-left: 16px;
}
.dropdown-divider,
.excalidraw .context-menu hr {
.dropdown-divider {
position: relative;
border-color: transparent !important;
overflow: visible;
}
.dropdown-divider::after,
.excalidraw .context-menu hr::before {
.dropdown-divider::after {
position: absolute;
content: "";
top: -1px;
inset-inline-start: calc(0px - var(--menu-padding-size));
inset-inline-end: calc(0px - var(--menu-padding-size));
left: calc(0px - var(--menu-padding-size));
right: calc(0px - var(--menu-padding-size));
border-top: 1px solid var(--menu-item-delimiter-color);
}
@@ -265,7 +231,7 @@ html body .dropdown-item[disabled] {
align-items: center;
justify-content: center;
top: 0;
inset-inline-end: 0;
right: 0;
margin: unset !important;
border: unset !important;
padding: 0 4px;
@@ -274,16 +240,10 @@ html body .dropdown-item[disabled] {
color: var(--menu-item-arrow-color) !important;
}
body[dir=rtl] .dropdown-menu:not([data-popper-placement="bottom-start"]) .dropdown-toggle::after {
content: "\ea4d" !important;
}
/* Menu item group heading */
/* The heading body */
.dropdown-menu h6,
.excalidraw .dropdown-menu-container .dropdown-menu-group-title,
.excalidraw .dropdown-menu-container div[data-testid="canvas-background-label"] {
.dropdown-menu h6 {
position: relative;
background: transparent;
padding: 1em 8px 14px 8px;
@@ -294,14 +254,12 @@ body[dir=rtl] .dropdown-menu:not([data-popper-placement="bottom-start"]) .dropdo
}
/* The delimiter line */
.dropdown-menu h6::before,
.excalidraw .dropdown-menu-container .dropdown-menu-group-title::before,
.excalidraw .dropdown-menu-container div[data-testid="canvas-background-label"]::before {
.dropdown-menu h6::before {
content: "";
position: absolute;
bottom: 8px;
inset-inline-start: calc(0px - var(--menu-padding-size));
inset-inline-end: calc(0px - var(--menu-padding-size));
left: calc(0px - var(--menu-padding-size));
right: calc(0px - var(--menu-padding-size));
border-top: 1px solid var(--menu-item-delimiter-color);
}
@@ -331,20 +289,6 @@ body.mobile .dropdown-menu .dropdown-item.submenu-open .dropdown-toggle::after {
transform: rotate(270deg);
}
/* Dropdown item button (used in zoom buttons in global menu) */
li.dropdown-item a.dropdown-item-button {
border: unset;
}
li.dropdown-item a.dropdown-item-button.bx {
color: var(--menu-text-color) !important;
}
li.dropdown-item a.dropdown-item-button:focus-visible {
outline: 2px solid var(--input-focus-outline-color) !important;
}
/*
* TOASTS
*/
@@ -363,49 +307,30 @@ li.dropdown-item a.dropdown-item-button:focus-visible {
--modal-control-button-color: var(--bs-toast-color);
display: flex;
flex-direction: column;
flex-direction: row-reverse;
backdrop-filter: blur(6px);
}
#toast-container .toast .toast-header {
padding: 0 !important;
background: transparent !important;
border-bottom: none;
color: var(--toast-text-color) !important;
}
#toast-container .toast .toast-header strong > * {
vertical-align: middle;
#toast-container .toast .toast-header strong {
/* The title of the toast is no longer displayed */
display: none;
}
#toast-container .toast .toast-header .btn-close {
margin: 0 0 0 12px;
}
margin: 0 var(--bs-toast-padding-x) 0 12px;
#toast-container .toast.no-title {
flex-direction: row;
}
#toast-container .toast .toast-body {
flex-grow: 1;
overflow: hidden;
text-overflow: ellipsis;
padding-top: 0;
}
#toast-container .toast:not(.no-title) .bx {
margin-inline-end: 0.5em;
font-size: 1.1em;
opacity: 0.85;
}
#toast-container .toast.no-title .bx {
margin-inline-end: 0;
font-size: 1.3em;
}
#toast-container .toast.no-title .toast-body {
padding-top: var(--bs-toast-padding-x);
color: var(--toast-text-color);
}
/*

View File

@@ -29,7 +29,7 @@
display: flex;
justify-content: center;
align-items: center;
margin-inline-start: 8px;
margin-left: 8px;
border: 0;
border-radius: 50%;
padding: 0;
@@ -56,7 +56,7 @@
}
.modal .modal-header .help-button {
margin-inline-end: 0;
margin-right: 0;
font-size: calc(var(--modal-control-button-size) * .75);
font-family: unset;
font-weight: bold;
@@ -141,7 +141,7 @@ div.tn-tool-dialog {
/* Search box wrapper */
.jump-to-note-dialog .input-group {
margin-inline-end: 16px;
margin-right: 16px;
}
.jump-to-note-dialog .input-group:hover {
@@ -197,8 +197,8 @@ div.tn-tool-dialog {
border: unset;
padding-top: var(--timeline-item-top-padding);
padding-bottom: var(--timeline-item-bottom-padding);
padding-inline-start: calc(var(--timeline-left-gap) + var(--timeline-right-gap));
padding-inline-end: var(--timeline-left-gap);
padding-left: calc(var(--timeline-left-gap) + var(--timeline-right-gap));
padding-right: var(--timeline-left-gap);
color: var(--active-item-text-color);
}
@@ -259,7 +259,7 @@ div.tn-tool-dialog {
position: absolute;
content: "";
top: var(--connector-top, 0);
inset-inline-start: calc(var(--timeline-left-gap) + ((var(--timeline-bullet-size) - var(--timeline-connector-size)) / 2));
left: calc(var(--timeline-left-gap) + ((var(--timeline-bullet-size) - var(--timeline-connector-size)) / 2));
bottom: var(--connector-bottom, 0);
width: var(--timeline-connector-size);
border-radius: var(--connector-radius, 0) var(--connector-radius, 0) 0 0;
@@ -291,7 +291,7 @@ div.tn-tool-dialog {
position: absolute;
content: "";
top: calc(var(--timeline-item-top-padding) + var(--timeline-bullet-vertical-pos));
inset-inline-start: var(--timeline-left-gap);
left: var(--timeline-left-gap);
width: var(--timeline-bullet-size);
height: var(--timeline-bullet-size);
border-radius: 50%;
@@ -374,7 +374,7 @@ div.tn-tool-dialog {
}
.help-dialog .help-cards kbd:first-child {
margin-inline-start: 0;
margin-left: 0;
}
/* Inline code - used for Markdown samples */
@@ -392,7 +392,7 @@ div.tn-tool-dialog {
}
.delete-notes-list .note-path {
padding-inline-end: 8px;
padding-left: 8px;
}
/*
@@ -401,7 +401,7 @@ div.tn-tool-dialog {
/* Labels */
.attr-edit-table th {
padding-inline-end: 12px;
padding-right: 12px;
font-weight: normal;
white-space: nowrap;
}
@@ -419,5 +419,5 @@ div.tn-tool-dialog {
}
.note-type-chooser-dialog div.note-type-dropdown .dropdown-item span.bx {
margin-inline-end: .25em;
margin-right: .25em;
}

View File

@@ -62,7 +62,7 @@ button.btn.btn-secondary span.bx,
button.btn.btn-sm span.bx,
button.btn.btn-success span.bx {
color: var(--cmd-button-icon-color);
padding-inline-end: 0.35em;
padding-right: 0.35em;
font-size: 1.2em;
}
@@ -71,7 +71,7 @@ button.btn.btn-primary kbd,
button.btn.btn-secondary kbd,
button.btn.btn-sm kbd,
button.btn.btn-success kbd {
margin-inline-start: 0.5em;
margin-left: 0.5em;
background: var(--cmd-button-keyboard-shortcut-background);
color: var(--cmd-button-keyboard-shortcut-color);
font-size: 0.6em;
@@ -84,7 +84,7 @@ button.btn.btn-success kbd {
*/
:root .icon-action:not(.global-menu-button),
:root .tn-tool-button,
:root .btn.tn-tool-button,
:root .btn-group .tn-tool-button:not(:last-child),
:root .btn-group .tn-tool-button:last-child {
width: var(--icon-button-size);
@@ -96,13 +96,8 @@ button.btn.btn-success kbd {
color: var(--icon-button-color);
}
:root .btn-group .icon-action:last-child {
border-top-left-radius: unset !important;
border-bottom-left-radius: unset !important;
}
.btn-group .tn-tool-button + .tn-tool-button {
margin-inline-start: 4px !important;
margin-left: 4px !important;
}
/* The "x" icon button */
@@ -197,8 +192,8 @@ input[type="password"]:focus,
input[type="date"]:focus,
input[type="time"]:focus,
input[type="datetime-local"]:focus,
:root input.ck.ck-input-text:not([readonly="true"]):focus,
:root input.ck.ck-input-number:not([readonly="true"]):focus,
:root input.ck.ck-input-text:focus,
:root input.ck.ck-input-number:focus,
textarea.form-control:focus,
textarea:focus,
:root textarea.ck.ck-textarea:focus,
@@ -237,7 +232,7 @@ input::selection,
outline-offset: 6px;
background: var(--input-background-color);
border-radius: 6px;
padding-inline-end: 8px;
padding-right: 8px;
color: var(--quick-search-color);
flex-wrap: nowrap;
}
@@ -357,20 +352,13 @@ select.form-control,
outline: 3px solid transparent;
outline-offset: 6px;
padding-inline-end: calc(15px + 1.5rem);
background: var(--input-background-color) var(--dropdown-arrow);;
padding-right: calc(15px + 1.5rem);
background: var(--input-background-color) var(--dropdown-arrow);
color: var(--input-text-color);
border: unset;
border-radius: 0.375rem;
}
body[dir=rtl] select,
body[dir=rtl] select.form-select,
body[dir=rtl] select.form-control,
body[dir=rtl] .select-button.dropdown-toggle.btn {
background-position: left 0.75rem center;
}
select:hover,
select.form-select:hover,
select.form-control:hover,
@@ -451,7 +439,7 @@ optgroup {
content: "\eae1";
width: 2em;
height: 100%;
inset-inline-end: 0;
right: 0;
top: 0;
font-size: 1.2em;
font-family: boxicons;
@@ -469,7 +457,7 @@ optgroup {
--box-label-gap: 0.5em;
position: relative;
padding-inline-start: calc(var(--box-size) + var(--box-label-gap)) !important;
padding-left: calc(var(--box-size) + var(--box-label-gap)) !important;
user-select: none;
}
@@ -478,7 +466,7 @@ optgroup {
label.tn-checkbox > input[type="checkbox"] {
position: absolute;
top: 0;
inset-inline-start: 0;
left: 0;
width: var(--box-size);
height: 100%;
margin: unset;
@@ -492,7 +480,7 @@ optgroup {
content: "";
position: absolute;
top: 50%;
inset-inline-start: 0;
left: 0;
translate: 0 -50%;
width: var(--box-size);
height: var(--box-size);

View File

@@ -19,11 +19,11 @@
}
.chat-message.user-message {
margin-inline-start: auto;
margin-left: auto;
}
.chat-message.assistant-message {
margin-inline-end: auto;
margin-right: auto;
}
.message-avatar {
@@ -33,7 +33,7 @@
display: flex;
align-items: center;
justify-content: center;
margin-inline-end: 8px;
margin-right: 8px;
}
.user-message .message-avatar {

View File

@@ -1,261 +0,0 @@
:root .excalidraw {
--ui-font: var(--main-font-family);
/* Button hover background color */
--button-hover-bg: var(--hover-item-background-color);
--color-surface-high: var(--hover-item-background-color);
--button-active-border: transparent;
--color-brand-active: transparent;
--color-surface-mid: transparent;
--color-surface-low: transparent;
/* Slider colors */
--color-slider-track: var(--menu-item-delimiter-color);
--color-slider-thumb: var(--muted-text-color);
/* Selected button icon fill color */
--color-on-primary-container: var(--ck-editor-toolbar-button-on-color);
--color-primary: var(--ck-editor-toolbar-button-on-color);
/* Selected button icon background color */
--color-surface-primary-container: var(--ck-editor-toolbar-button-on-background);
--color-primary-light: var(--ck-editor-toolbar-button-on-background);
--island-bg-color: var(--floating-button-background-color);
}
/* Dark theme tweaks */
:root body .excalidraw.theme--dark {
--color-surface-high: transparent;
--color-brand-hover: transparent;
}
:root .excalidraw.theme--dark.excalidraw .App-mobile-menu,
:root .excalidraw.theme--dark.excalidraw .App-menu__left {
--button-hover-bg: var(--hover-item-background-color);
}
:root .excalidraw.theme--dark.excalidraw .dropdown-menu-button:hover {
--background: var(--hover-item-background-color);
}
/* Backdrop blur pseudo-element */
.Island:not(.App-menu__left)::before,
.excalidraw .picker::before,
:root .App-menu__left > .panelColumn > fieldset::before,
:root .App-menu__left > .panelColumn > label::before,
:root .App-menu__left > .panelColumn > div:has(> *)::before {
display: block;
position: absolute;
content: "";
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: inherit;
backdrop-filter: blur(10px) saturate(6);
z-index: -1;
}
/* Note's root */
:root .type-canvas {
--floating-buttons-vert-offset: 20px;
}
/* Context menus */
/* Context menu - outer wrapper */
:root .excalidraw .popover {
--padding: 0;
max-width: unset;
overflow: hidden;
font-family: var(--main-font-family);
}
/* Context menu - inner wrapper */
:root .excalidraw .popover > .context-menu {
margin: 0;
padding: 8px !important;
overflow-y: auto;
overflow-x: hidden;
height: 100%;
border: none;
padding: 0;
box-shadow: none;
background: transparent;
}
/* Context menu item */
:root .excalidraw .context-menu .context-menu-item {
--menu-item-start-padding: 22px;
border: 1px solid transparent;
}
/* Context menu item icon */
:root .excalidraw .dropdown-menu-item__icon {
color: var(--menu-item-icon-color);
}
/* Context menu item label */
:root .excalidraw .context-menu-item__label,
:root .excalidraw .context-menu-item.dangerous .context-menu-item__label {
color: var(--menu-text-color);
}
:root .excalidraw .context-menu-item:hover .context-menu-item__label {
color: var(--hover-item-text-color);
}
/* Context menu item keyboard shortcut */
:root .excalidraw .context-menu-item__shortcut {
padding: 0;
opacity: 1;
}
/* Context menu separator */
.excalidraw .context-menu .context-menu-item-separator {
margin: 8px 0;
opacity: 1;
}
/* Main menu */
/* Hide separators - no longer needed as the menu group headers feature a delimiter line */
.excalidraw .Island.dropdown-menu-container>div:not(:has(>*)) {
display: none;
}
/* Menu group header */
.excalidraw .dropdown-menu-container .dropdown-menu-group-title,
.excalidraw .Island.dropdown-menu-container div[data-testid="canvas-background-label"] {
margin: 0 !important;
}
/* Header */
.excalidraw .App-menu.App-menu_top {
align-items: center;
}
.excalidraw .App-menu.App-menu_top .App-menu_top__left {
/* Fixes a layout glitch with the header when the options panel is visbile */
--gap: 0 !important;
}
/* The parent element of the "Library" button */
.excalidraw .App-menu.App-menu_top > div:nth-child(3) {
flex-direction: row-reverse;
}
/* Panels */
.excalidraw .zoom-actions,
.undo-redo-buttons {
box-shadow: 1px 1px 1px var(--floating-button-shadow-color);
backdrop-filter: blur(10px) saturate(6);
}
:root .excalidraw .main-menu-trigger,
:root .excalidraw .sidebar-trigger,
:root .excalidraw .help-icon {
box-shadow: none;
}
/* Selected color outline */
:root .excalidraw .color-picker__button.active .color-picker__button-outline {
box-shadow: 0 0 0 2px var(--input-focus-outline-color);
}
:root .excalidraw .buttonList label.active {
border-color: transparent;
}
/* Options panel */
.excalidraw .Island.App-menu__left {
box-shadow: none;
background: transparent;
backdrop-filter: none;
width: 13.2em;
}
body[dir=ltr] .excalidraw .Island.App-menu__left {
right: 0;
}
body[dir=rtl] .excalidraw .Island.App-menu__left {
left: 0;
}
:root .App-menu__left > .panelColumn {
row-gap: 5px;
}
/* Options panel card */
:root .App-menu__left > .panelColumn > fieldset,
:root .App-menu__left > .panelColumn > label,
:root .App-menu__left > .panelColumn > div:has(> *) {
position: relative;
margin: 0;
border-radius: 4px;
box-shadow: 1px 1px 1px var(--floating-button-shadow-color);
background: var(--floating-button-background-color);
padding: 8px 12px;
/* backdrop: blur() creates a new stacking context that prevents some popovers like the
* arrowheads picker from being positioned correctly. To workaround this, the backdrop blur
* effect is applyed using a pseudo-element instead. */
}
/* Options panel card title */
:root .App-menu__left fieldset > legend,
:root .App-menu__left div > h3,
:root .App-menu__left > .panelColumn > label {
text-transform: uppercase;
font-size: .65rem;
letter-spacing: 1pt;
color: var(--muted-text-color);
}
/* Options panel button bar */
:root .excalidraw .App-menu__left .buttonList {
padding: 0;
}
/* Picker */
body[dir=ltr] .excalidraw .App-menu__left .buttonList .picker {
translate: -80% 0;
}
/* Properties panel */
body[dir=ltr] .excalidraw .exc-stats {
left: 0;
}
body[dir=rtl] .excalidraw .exc-stats {
right: 0;
}
/* Sidebar */
.split-note-container-widget > .component.type-canvas:has(.excalidraw-container > .Island.default-sidebar) > .floating-buttons {
/* Hide the floating buttons when the sidebar is open */
display: none;
}
/* Pickers */
.excalidraw .picker {
position: relative;
}

View File

@@ -117,9 +117,9 @@
content: "";
position: absolute;
top: var(--negative-padding);
inset-inline-end: var(--negative-padding);
right: var(--negative-padding);
bottom: var(--negative-padding);
inset-inline-start: var(--negative-padding);
left: var(--negative-padding);
border-radius: var(--dropdown-border-radius);
backdrop-filter: var(--dropdown-backdrop-filter);
z-index: -1;
@@ -210,7 +210,7 @@
/* Separator */
:root .ck .ck-list__separator {
margin: .5em 0;
margin-inline-start: calc(0px - var(--ck-editor-popup-padding));
margin-left: calc(0px - var(--ck-editor-popup-padding));
width: calc(100% + (var(--ck-editor-popup-padding) * 2));
background: var(--menu-item-delimiter-color);
}
@@ -233,8 +233,8 @@
position: absolute;
top: 0;
bottom: var(--negative-padding);
inset-inline-start: var(--negative-padding);
inset-inline-end: var(--negative-padding);
left: var(--negative-padding);
right: var(--negative-padding);
border-top: 1px solid var(--ck-editor-popup-border-color);
background: var(--menu-section-background-color);
}
@@ -255,7 +255,7 @@
:root .ck.ck-toolbar .ck.ck-toolbar__separator {
background: transparent;
border-inline-start: 1px solid var(--ck-color-toolbar-border);
border-left: 1px solid var(--ck-color-toolbar-border);
}
/* The last separator of the toolbar */
@@ -354,8 +354,7 @@
align-items: center;
width: 100%;
margin: 4px;
background: color-mix(in srgb, var(--accent) 15%, var(--main-background-color));
padding-inline-end: 2em;
padding-right: 2em;
border: 1px solid var(--accent);
border-radius: 6px;
}
@@ -493,7 +492,7 @@ button.ck.ck-button:is(.ck-button-action, .ck-button-save, .ck-button-cancel).ck
/* Move the label above the text box regardless of the text box state */
transform: translate(0, calc(-.2em - var(--ck-input-label-height))) !important;
padding-inline-start: 0 !important;
padding-left: 0 !important;
background: transparent;
font-size: .85em;
font-weight: 600;
@@ -557,7 +556,7 @@ pre button.copy-button.icon-action {
}
:root pre:has(> button.copy-button) {
padding-inline-end: calc(var(--icon-button-size) + (var(--copy-button-margin-size) * 2));
padding-right: calc(var(--icon-button-size) + (var(--copy-button-margin-size) * 2));
}
html .note-detail-editable-text :not(figure, .include-note, hr):first-child {
@@ -616,12 +615,12 @@ html .note-detail-editable-text :not(figure, .include-note, hr):first-child {
.ck-content blockquote:before {
content: "“";
inset-inline-start: 0.2em;
left: 0.2em;
}
.ck-content blockquote:after {
content: "”";
inset-inline-end: 0.35em;
right: 0.35em;
}
.ck-content h2,

View File

@@ -52,7 +52,7 @@
background-color: #f5f5f5;
}
.google-login-btn img {
margin-inline-end: 10px;
margin-right: 10px;
width: 18px;
height: 18px;
}
@@ -109,11 +109,6 @@
* NOTE MAP
*/
.note-detail-note-map .fixnodes-type-switcher .tn-tool-button,
.note-map-widget .fixnodes-type-switcher .tn-tool-button {
padding: unset;
}
.note-detail-note-map .fixnodes-type-switcher .tn-tool-button.toggled {
color: var(--tab-close-button-hover-background);
}
@@ -199,7 +194,7 @@ body.desktop .option-section:not(.tn-no-card) {
color: var(--launcher-pane-text-color);
margin-top: calc(-1 * var(--options-card-padding) - var(--options-title-font-size) - var(--options-title-offset)) !important;
margin-bottom: calc(var(--options-title-offset) + var(--options-card-padding)) !important;
margin-inline-start: calc(-1 * var(--options-card-padding));
margin-left: calc(-1 * var(--options-card-padding));
}
.options-section:not(.tn-no-card) h5 {
@@ -216,8 +211,8 @@ body.desktop .option-section:not(.tn-no-card) {
.options-section hr {
--bs-border-width: 2px;
margin-inline-start: calc(var(--options-card-padding) * -1);
margin-inline-end: calc(var(--options-card-padding) * -1);
margin-left: calc(var(--options-card-padding) * -1);
margin-right: calc(var(--options-card-padding) * -1);
opacity: 1;
color: var(--root-background);
}

View File

@@ -94,18 +94,19 @@ div.promoted-attributes-container {
/* Note type dropdown */
ul.note-type-dropdown .check {
margin-inline-end: 6px;
}
ul.note-type-dropdown li.dropdown-item {
--menu-item-icon-vert-offset: 0;
div.note-type-dropdown .check {
margin-right: 6px;
}
/* Editability dropdown */
ul.editability-dropdown li.dropdown-item > div {
margin-inline-start: 4px;
div.editability-dropdown a.dropdown-item {
padding: 4px 16px 4px 0;
align-items: start !important;
}
.editability-dropdown .dropdown-item .check {
margin-left: 4px;
}
.editability-dropdown .dropdown-item .description {
@@ -142,12 +143,12 @@ ul.editability-dropdown li.dropdown-item > div {
}
.attribute-list .save-attributes-button {
inset-inline-end: 30px;
right: 30px;
}
/* Note path in attribute detail dialog */
.attr-detail .note-path {
margin-inline-start: 8px;
margin-left: 8px;
}
/*

View File

@@ -18,7 +18,7 @@
body {
--native-titlebar-darwin-x-offset: 10;
--native-titlebar-darwin-y-offset: 12 !important;
--native-titlebar-darwin-y-offset: 17 !important;
}
body.layout-horizontal {
@@ -69,7 +69,7 @@ body.background-effects.platform-win32.layout-vertical #vertical-main-container
/* Add a border to the vertical launch bar if collapsed. */
body.layout-vertical #horizontal-main-container.left-pane-hidden #launcher-pane.vertical {
border-inline-end: 2px solid var(--left-pane-collapsed-border-color);
border-right: 2px solid var(--left-pane-collapsed-border-color);
}
body.background-effects.zen #root-widget {
@@ -100,7 +100,7 @@ body.layout-horizontal > .horizontal {
align-items: center;
}
body[dir=ltr] #launcher-container {
#launcher-container {
scrollbar-gutter: stable both-edges;
}
@@ -223,7 +223,7 @@ body[dir=ltr] #launcher-container {
}
#launcher-pane .launcher-button:focus,
#launcher-pane .global-menu :focus {
#launcher-pane .global-menu button:focus {
outline: none;
}
@@ -279,13 +279,16 @@ body[dir=ltr] #launcher-container {
animation: sync-status-pulse 1s ease-in-out alternate-reverse infinite;
}
#launcher-pane button.global-menu-button {
--update-badge-x-offset: 3%;
--update-badge-y-offset: -12%;
#launcher-pane .global-menu-button {
--hover-item-background-color: transparent;
}
#launcher-pane.horizontal .global-menu-button .global-menu-button-update-available {
right: -23px;
bottom: -22px;
transform: scale(0.85);
}
.tooltip .tooltip-arrow {
display: none;
}
@@ -301,6 +304,18 @@ body[dir=ltr] #launcher-container {
color: var(--tooltip-foreground-color) !important;
}
/*
* Global menu
*/
.global-menu div.zoom-buttons a {
border: unset;
}
.global-menu div.zoom-buttons a.bx {
color: var(--menu-text-color) !important;
}
/*
* Calendar
*/
@@ -333,21 +348,6 @@ body[dir=ltr] #launcher-container {
--select-arrow-svg: initial; /* Disable the dropdown arrow */
}
/* Week number column */
.calendar-dropdown-widget .calendar-week-number {
transform: rotate(270deg);
justify-content: center;
padding: 0;
opacity: 0.5;
font-size: 1em;
font-weight: 700;
letter-spacing: .5pt;
}
.calendar-dropdown-widget .calendar-week-number::after {
display: none;
}
@media (max-width: 992px) {
.calendar-dropdown-widget .calendar-header button {
margin: 0 !important;
@@ -397,9 +397,9 @@ body[dir=ltr] #launcher-container {
content: "";
position: absolute;
top: var(--vertical-margin);
inset-inline-end: var(--horiz-margin);
right: var(--horiz-margin);
bottom: var(--vertical-margin);
inset-inline-start: var(--horiz-margin);
left: var(--horiz-margin);
border-radius: 6px;
background: var(--calendar-day-highlight-background);
z-index: -1;
@@ -447,7 +447,7 @@ div.bookmark-folder-widget .note-link:hover {
}
div.bookmark-folder-widget .note-link a {
padding-inline-start: 8px;
padding-left: 8px;
color: var(--menu-text-color);
cursor: default;
}
@@ -468,8 +468,8 @@ div.bookmark-folder-widget .note-link .bx {
div.quick-search {
--padding-top: 8px;
--padding-inline-start: 8px;
--padding-inline-end: 8px;
--padding-left: 8px;
--padding-right: 8px;
--padding-bottom: 8px;
position: relative;
@@ -477,7 +477,7 @@ div.quick-search {
align-items: center;
height: unset;
contain: unset;
padding: var(--padding-top) var(--padding-inline-end) var(--padding-bottom) var(--padding-inline-start);
padding: var(--padding-top) var(--padding-right) var(--padding-bottom) var(--padding-left);
}
div.quick-search,
@@ -493,9 +493,9 @@ div.quick-search::before {
position: absolute;
content: "";
top: var(--padding-top);
inset-inline-start: var(--padding-inline-start);
left: var(--padding-left);
bottom: var(--padding-bottom);
inset-inline-end: var(--padding-inline-end);
right: var(--padding-right);
z-index: 0;
border: 2px solid transparent;
border-radius: 6px;
@@ -517,7 +517,7 @@ div.quick-search:focus-within:before {
}
div.quick-search input {
padding-inline-start: 15px !important;
padding-left: 15px !important;
box-shadow: unset !important;
background: transparent !important;
}
@@ -536,7 +536,7 @@ div.quick-search .search-button {
justify-content: center;
width: 25px;
height: 25px;
margin-inline-end: 8px;
margin-right: 8px;
border-radius: 50%;
padding: 0;
color: var(--quick-search-color) !important;
@@ -562,21 +562,15 @@ div.quick-search .search-button.show {
transition: background-color 100ms ease-out !important;
}
/*
* Quick search results
*/
div.quick-search .dropdown-menu {
--quick-search-item-delimiter-color: transparent;
--menu-item-icon-vert-offset: -.065em;
}
/*
* TO FIX: The quick search results dropdown has a backdrop issue with the tree panel
* when background effects are enabled in Electron.
* As a temporary workaround, the backdrop and transparency are disabled for the
* vertical layout.
*/
body.layout-vertical.background-effects div.quick-search .dropdown-menu {
--menu-background-color: var(--menu-background-color-no-backdrop) !important;
}
/* Item */
.quick-search .dropdown-menu *.dropdown-item {
padding: 8px 12px !important;
@@ -628,18 +622,18 @@ body.layout-vertical.background-effects div.quick-search .dropdown-menu {
}
#left-pane .ui-fancytree ul {
padding-inline-start: 10px;
padding-left: 10px;
}
/* The root element of the tree */
#left-pane .fancytree-container > li:first-child > span {
padding-inline-start: 12px;
padding-left: 12px;
}
#left-pane span.fancytree-node.fancytree-active {
position: relative;
background: transparent !important;
color: var(--custom-color, var(--left-pane-item-selected-color));
color: var(--left-pane-item-selected-color) !important;
}
@keyframes left-pane-item-select {
@@ -655,10 +649,10 @@ body.layout-vertical.background-effects div.quick-search .dropdown-menu {
position: absolute;
content: "";
top: var(--left-pane-item-selected-shadow-size);
inset-inline-start: var(--left-pane-item-selected-shadow-size);
left: var(--left-pane-item-selected-shadow-size);
bottom: var(--left-pane-item-selected-shadow-size);
inset-inline-end: var(--left-pane-item-selected-shadow-size);
background: var(--custom-bg-color, var(--left-pane-item-selected-background)) !important;
right: var(--left-pane-item-selected-shadow-size);
background: var(--left-pane-item-selected-background) !important;
box-shadow: var(--left-pane-item-selected-shadow);
border-radius: 6px;
animation: left-pane-item-select 200ms ease-out;
@@ -673,7 +667,7 @@ body.layout-vertical.background-effects div.quick-search .dropdown-menu {
#left-pane span.fancytree-node.protected > span.fancytree-custom-icon:after {
position: absolute;
bottom: 0;
inset-inline-end: 0;
right: 0;
font-size: 14px;
content: "\eb4a";
font-family: "boxicons";
@@ -682,10 +676,6 @@ body.layout-vertical.background-effects div.quick-search .dropdown-menu {
border-radius: 50%;
}
body[dir=rtl] #left-pane span.fancytree-node.protected > span.fancytree-custom-icon:after {
transform: translateX(-25%);
}
body.mobile .fancytree-expander::before,
body.mobile .fancytree-title,
body.mobile .fancytree-node > span {
@@ -700,7 +690,7 @@ body.mobile .fancytree-node > span {
body.mobile:not(.force-fixed-tree) #mobile-sidebar-wrapper {
border-top-right-radius: 12px;
border-bottom-right-radius: 12px;
border-inline-end: 1px solid var(--subtle-border-color);
border-right: 1px solid var(--subtle-border-color);
}
}
@@ -718,6 +708,9 @@ body.mobile .fancytree-node > span {
margin-top: 0; /* Use this to align the icon with the tree view item's caption */
}
#left-pane span .fancytree-title {
margin-top: -5px;
}
#left-pane span.fancytree-active .fancytree-title {
font-weight: normal;
@@ -732,7 +725,7 @@ body.mobile .fancytree-node > span {
}
#left-pane .tree-item-button {
margin-inline-end: 6px;
margin-right: 6px;
border: unset;
border-radius: 50%;
background: var(--left-pane-item-action-button-background);
@@ -766,12 +759,12 @@ body.mobile .fancytree-node > span {
/* Toolbar container (collapsed state) */
#left-pane .tree-actions {
max-width: var(--tree-actions-toolbar-collapsed-width);
inset-inline-end: var(--tree-actions-toolbar-horizontal-margin);
right: var(--tree-actions-toolbar-horizontal-margin);
bottom: var(--tree-actions-toolbar-vertical-margin);
overflow: hidden;
border: 1px solid transparent;
padding: var(--tree-actions-toolbar-padding-size);
padding-inline-end: var(--tree-actions-toolbar-collapsed-width);
padding-right: var(--tree-actions-toolbar-collapsed-width);
background: transparent;
transition:
max-width 400ms ease-out,
@@ -815,7 +808,7 @@ body.mobile .fancytree-node > span {
justify-content: center;
align-items: center;
top: 50%;
inset-inline-end: calc((var(--tree-actions-toolbar-collapsed-width) - var(--tree-actions-toolbar-expand-button-size)) / 2);
right: calc((var(--tree-actions-toolbar-collapsed-width) - var(--tree-actions-toolbar-expand-button-size)) / 2);
width: var(--tree-actions-toolbar-expand-button-size);
height: var(--tree-actions-toolbar-expand-button-size);
box-shadow: 2px 2px 6px var(--left-pane-background-color);
@@ -873,10 +866,7 @@ body.mobile .fancytree-node > span {
}
.tab-row-container .toggle-button {
--icon-button-size: 30px;
--icon-button-icon-ratio: .6;
margin: 3px 6px auto 8px !important;
margin: 6px 10px !important;
}
.tab-row-container {
@@ -904,9 +894,9 @@ body.electron.background-effects.layout-horizontal .tab-row-container .toggle-bu
content: "";
position: absolute;
bottom: 0;
inset-inline-start: -10px;
inset-inline-end: -10px;
top: 32px;
left: -10px;
right: -10px;
top: 29px;
height: 1px;
border-bottom: 1px solid var(--launcher-pane-horiz-border-color);
}
@@ -916,13 +906,13 @@ body.electron.background-effects.layout-horizontal .tab-row-container .tab-scrol
position: relative;
}
body.electron.background-effects.layout-horizontal .tab-row-container .tab-scroll-button-inset-inline-start:after,
body.electron.background-effects.layout-horizontal .tab-row-container .tab-scroll-button-inset-inline-end:after {
body.electron.background-effects.layout-horizontal .tab-row-container .tab-scroll-button-left:after,
body.electron.background-effects.layout-horizontal .tab-row-container .tab-scroll-button-right:after {
content: "";
position: absolute;
bottom: 0;
inset-inline-start: 0px;
inset-inline-end: 0px;
left: 0px;
right: 0px;
height: 1px;
border-bottom: 1px solid var(--launcher-pane-horiz-border-color);
}
@@ -931,9 +921,9 @@ body.electron.background-effects.layout-horizontal .tab-row-container .note-tab[
content: "";
position: absolute;
bottom: 0;
inset-inline-start: -32768px;
left: -32768px;
top: var(--tab-height);
inset-inline-end: calc(100% - 1px);
right: calc(100% - 1px);
height: 1px;
border-bottom: 1px solid var(--launcher-pane-horiz-border-color);
}
@@ -942,9 +932,9 @@ body.electron.background-effects.layout-horizontal .tab-row-container .note-tab[
content: "";
position: absolute;
bottom: 0;
inset-inline-start: 100%;
left: 100%;
top: var(--tab-height);
inset-inline-end: 0;
right: 0;
width: 100vw;
height: 1px;
border-bottom: 1px solid var(--launcher-pane-horiz-border-color);
@@ -954,9 +944,9 @@ body.electron.background-effects.layout-horizontal .tab-row-container .note-new-
content: "";
position: absolute;
bottom: 0;
inset-inline-start: -4px;
left: -4px;
top: calc(var(--tab-height), -1);
inset-inline-end: 0;
right: 0;
width: 100vw;
height: 1px;
border-bottom: 1px solid var(--launcher-pane-horiz-border-color);
@@ -1043,24 +1033,16 @@ body.layout-horizontal .tab-row-widget .note-tab .note-tab-wrapper {
content: "";
position: absolute;
top: 0;
inset-inline-start: 0;
inset-inline-end: 0;
left: 0;
right: 0;
height: 3px;
background-color: var(--workspace-tab-background-color);
}
body:not([dir=rtl]) .tab-row-widget .note-tab:nth-child(1) {
.tab-row-widget .note-tab:nth-child(1) {
transform: translate3d(var(--tab-first-item-horiz-offset), 0, 0);
}
:root .tab-row-widget .note-tab .note-tab-icon {
padding-inline-end: 5px; /* The gap between the icon and the title */
}
.tab-row-widget .note-tab[active] .note-tab-icon {
color: var(--active-tab-icon-color);
}
.tab-row-widget .note-tab .note-tab-title {
text-overflow: ellipsis;
}
@@ -1099,7 +1081,7 @@ body.layout-vertical .tab-row-widget-is-sorting .note-tab.note-tab-is-dragging .
.tab-row-widget .note-new-tab {
position: relative;
margin-inline-start: 3px;
margin-left: 3px;
color: transparent; /* Prevent the original "+" from being displayed */
}
@@ -1112,7 +1094,7 @@ body.layout-vertical .tab-row-widget-is-sorting .note-tab.note-tab-is-dragging .
position: absolute;
content: "";
top: calc((var(--tab-height) - var(--new-tab-button-size)) / 2);
inset-inline-start: calc((var(--tab-height) - var(--new-tab-button-size)) / 2);
left: calc((var(--tab-height) - var(--new-tab-button-size)) / 2);
width: var(--new-tab-button-size);
height: var(--new-tab-button-size);
background: var(--new-tab-button-background);
@@ -1137,7 +1119,7 @@ body.layout-vertical .tab-row-widget-is-sorting .note-tab.note-tab-is-dragging .
display: flex;
position: absolute;
content: "\ebc0";
inset-inline-start: 0;
left: 0;
top: 0;
width: 100%;
height: 100%;
@@ -1219,23 +1201,23 @@ body.mobile .note-title {
}
.title-row > *:first-child {
margin-inline-end: 0;
margin-right: 0;
}
.title-row > *:nth-child(2) {
margin-inline-start: 0;
margin-left: 0;
}
.title-row {
/* Aligns the "Create new split" button with the note menu button (the three dots button) */
padding-inline-end: 3px;
padding-right: 3px;
}
.note-title-widget input {
--input-background-color: transparent;
border-radius: 8px;
padding-inline-start: 12px;
padding-left: 12px;
}
/* The "Change note icon" button */
@@ -1310,7 +1292,7 @@ body.mobile .note-title {
/* The promoted attributes section */
div.promoted-attributes-container {
display: flex;
margin-inline-end: 10%;
margin-right: 10%;
padding: 6px 0;
gap: 8px;
align-items: stretch;
@@ -1324,8 +1306,8 @@ div.promoted-attributes-container input {
/* A promoted attribute card */
div.promoted-attribute-cell {
--pa-card-padding-inline-start: 16px;
--pa-card-padding-inline-end: 2px;
--pa-card-padding-left: 16px;
--pa-card-padding-right: 2px;
--input-background-color: transparent;
box-shadow: 1px 1px 2px var(--promoted-attribute-card-shadow-color);
@@ -1333,7 +1315,7 @@ div.promoted-attribute-cell {
display: inline-flex;
margin: 0;
border-radius: 8px;
padding: 2px var(--pa-card-padding-inline-end) 2px var(--pa-card-padding-inline-start);
padding: 2px var(--pa-card-padding-right) 2px var(--pa-card-padding-left);
background: var(--promoted-attribute-card-background-color);
overflow-y: visible;
}
@@ -1348,7 +1330,7 @@ div.promoted-attribute-cell {
/* A promoted attribute card (boolean attribute) */
div.promoted-attribute-cell:has(input[type="checkbox"]):not(:has(.multiplicity > span)) {
/* Checbox attribute, without multiplicity */
padding-inline-end: var(--pa-card-padding-inline-start);
padding-right: var(--pa-card-padding-left);
}
div.promoted-attribute-cell > * {
@@ -1398,23 +1380,16 @@ div.promoted-attribute-cell .tn-checkbox {
/* Relocate the checkbox before the label */
div.promoted-attribute-cell.promoted-attribute-label-boolean > div:first-of-type {
order: -1;
margin-inline-end: 1.5em;
margin-right: 1.5em;
}
/* The element containing the "new attribute" and "remove this attribute button" */
div.promoted-attribute-cell .multiplicity:has(span) {
--icon-button-size: 24px;
margin-inline-start: 8px;
margin-inline-end: calc(var(--pa-card-padding-inline-start) - var(--pa-card-padding-inline-end));
margin-left: 8px;
margin-right: calc(var(--pa-card-padding-left) - var(--pa-card-padding-right));
font-size: 0; /* Prevent whitespaces creating a gap between buttons */
display: flex;
}
div.promoted-attribute-cell .multiplicity:has(span) span {
display: flex;
align-items: center;
justify-content: center;
}
/*
@@ -1434,10 +1409,6 @@ div#center-pane .floating-buttons-children {
opacity 250ms ease-out;
}
body[dir=rtl] div#center-pane .floating-buttons-children {
transform-origin: left;
}
/* Floating buttons container (collapsed) */
div#center-pane .floating-buttons-children.temporarily-hidden {
display: flex !important;
@@ -1549,7 +1520,7 @@ div.floating-buttons-children .close-floating-buttons {
}
div.floating-buttons-children .close-floating-buttons {
margin-inline-start: 0 !important;
margin-left: 0 !important;
background: var(--floating-button-hide-button-background);
color: var(--floating-button-hide-button-color);
}
@@ -1639,12 +1610,12 @@ div.find-replace-widget div.find-widget-found-wrapper > span {
}
.find-replace-widget .form-check {
padding-inline-start: 0;
padding-left: 0;
white-space: nowrap;
}
.find-replace-widget .form-check .form-check-input {
margin-inline-start: 0;
margin-left: 0;
}
/* Narrow version */
@@ -1664,13 +1635,13 @@ div.find-replace-widget div.find-widget-found-wrapper > span {
.find-widget-box,
.replace-widget-box {
padding-inline-end: 3em !important;
padding-right: 3em !important;
}
.find-widget-close-button {
position: absolute;
top: .85em;
inset-inline-end: .5em;
right: .5em;
}
.find-widget-box > * {
@@ -1702,7 +1673,7 @@ div.find-replace-widget div.find-widget-found-wrapper > span {
}
.replace-widget-box > * {
margin-inline-end: unset !important;
margin-right: unset !important;
}
div.replace-widget-box button.btn.btn-sm {
@@ -1745,7 +1716,7 @@ div.find-replace-widget div.find-widget-found-wrapper > span {
#right-pane .toc li,
#right-pane .highlights-list li {
padding-top: 2px;
padding-inline-end: 8px;
padding-right: 8px;
padding-bottom: 2px;
border-radius: 4px;
text-align: unset;
@@ -1784,6 +1755,10 @@ div.find-replace-widget div.find-widget-found-wrapper > span {
--border-radius-lg: 6px;
}
.excalidraw .Island {
backdrop-filter: var(--dropdown-backdrop-filter);
}
.excalidraw .Island.App-toolbar {
--island-bg-color: var(--floating-button-background-color);
--shadow-island: 1px 1px 1px var(--floating-button-shadow-color);
@@ -1804,8 +1779,8 @@ div.find-replace-widget div.find-widget-found-wrapper > span {
}
.excalidraw .dropdown-menu .dropdown-menu-container > div:not([class]):not(:last-child) {
margin-inline-start: calc(var(--padding) * var(--space-factor) * -1) !important;
margin-inline-end: calc(var(--padding) * var(--space-factor) * -1) !important;
margin-left: calc(var(--padding) * var(--space-factor) * -1) !important;
margin-right: calc(var(--padding) * var(--space-factor) * -1) !important;
}
.excalidraw .dropdown-menu:before {

View File

@@ -1,5 +1,5 @@
ul.fancytree-container {
padding-inline-start: 0;
padding-left: 0;
}
ul.fancytree-container li {
@@ -15,8 +15,10 @@ span.fancytree-node.fancytree-hide {
flex-shrink: 1;
flex-grow: 1;
overflow: hidden;
margin-inline-start: 7px;
margin-left: 7px;
outline: none;
position: relative;
top: 2px;
}
.fancytree-expander {
@@ -40,7 +42,6 @@ span.fancytree-node.fancytree-hide {
text-overflow: ellipsis;
user-select: none !important;
-webkit-user-select: none !important;
color: var(--custom-color, inherit);
}
.fancytree-node:not(.fancytree-loading) .fancytree-expander {
@@ -58,11 +59,7 @@ span.fancytree-node.fancytree-hide {
line-height: 1;
position: relative;
top: 2px;
margin-inline-end: 5px;
}
body[dir=rtl] .fancytree-node:not(.fancytree-loading):not(.fancytree-expanded) .fancytree-expander:before {
content: "\ea4d"; /* bx bx-chevron-left */
margin-right: 5px;
}
.fancytree-loading span.fancytree-expander {
@@ -83,7 +80,7 @@ body[dir=rtl] .fancytree-node:not(.fancytree-loading):not(.fancytree-expanded) .
width: 12px;
height: 12px;
margin-top: 2px;
margin-inline-start: 1px;
margin-left: 1px;
border-width: 1px;
border-style: solid;
}
@@ -172,15 +169,15 @@ span.fancytree-node.fancytree-active-clone:not(.fancytree-active) .fancytree-tit
/* first nesting level has lower left padding to avoid extra left padding. Other levels are not affected */
.ui-fancytree > li > ul {
padding-inline-start: 5px;
padding-left: 5px;
}
.ui-fancytree ul {
padding-inline-start: 20px;
padding-left: 20px;
}
span.fancytree-active {
color: var(--active-item-text-color);
color: var(--active-item-text-color) !important;
background-color: var(--active-item-background-color) !important;
border-color: transparent; /* invisible border */
border-radius: 5px;
@@ -232,14 +229,14 @@ span.fancytree-node.archived {
display: none;
font-size: 120%;
cursor: pointer;
margin-inline-start: 8px;
margin-left: 8px;
padding: 1px;
border: 1px solid transparent;
border-radius: 5px;
}
.unhoist-button.bx.tree-item-button {
margin-inline-start: 0; /* unhoist button is on the left and doesn't need more margin */
margin-left: 0; /* unhoist button is on the left and doesn't need more margin */
display: block; /* keep always visible */
}

View File

@@ -3,8 +3,6 @@ import FNote from "../entities/fnote.js";
import froca from "../services/froca.js";
import FAttribute from "../entities/fattribute.js";
import noteAttributeCache from "../services/note_attribute_cache.js";
import FBranch from "../entities/fbranch.js";
import FBlob from "../entities/fblob.js";
type AttributeDefinitions = { [key in `#${string}`]: string; };
type RelationDefinitions = { [key in `~${string}`]: string; };
@@ -12,8 +10,6 @@ type RelationDefinitions = { [key in `~${string}`]: string; };
interface NoteDefinition extends AttributeDefinitions, RelationDefinitions {
id?: string | undefined;
title: string;
children?: NoteDefinition[];
content?: string;
}
/**
@@ -51,38 +47,6 @@ export function buildNote(noteDef: NoteDefinition) {
blobId: ""
});
froca.notes[note.noteId] = note;
let childNotePosition = 0;
// Manage content.
const content = noteDef.content ?? "";
note.getContent = async () => content;
const blob = new FBlob({
blobId: utils.randomString(10),
content,
contentLength: content.length,
dateModified: new Date().toISOString(),
utcDateModified: new Date().toISOString()
});
note.getBlob = async () => blob;
// Manage children.
if (noteDef.children) {
for (const childDef of noteDef.children) {
const childNote = buildNote(childDef);
const branchId = `${note.noteId}_${childNote.noteId}`;
const branch = new FBranch(froca, {
branchId,
noteId: childNote.noteId,
parentNoteId: note.noteId,
notePosition: childNotePosition,
fromSearchNote: false
});
froca.branches[branchId] = branch;
note.addChild(childNote.noteId, branchId, false);
childNotePosition += 10;
}
}
let position = 0;
for (const [ key, value ] of Object.entries(noteDef)) {

File diff suppressed because it is too large Load Diff

View File

@@ -121,7 +121,7 @@
"sat": "Ds",
"sun": "Dg",
"january": "Gener",
"february": "Febrer",
"febuary": "Febrer",
"march": "Març",
"april": "Abril",
"may": "Maig",

View File

@@ -276,12 +276,7 @@
"mime": "MIME 类型: ",
"file_size": "文件大小:",
"preview": "预览:",
"preview_not_available": "无法预览此类型的笔记。",
"diff_on": "显示差异",
"diff_off": "显示内容",
"diff_on_hint": "点击以显示笔记源代码差异",
"diff_off_hint": "点击以显示笔记内容",
"diff_not_available": "差异不可用。"
"preview_not_available": "无法预览此类型的笔记。"
},
"sort_child_notes": {
"sort_children_by": "按...排序子笔记",
@@ -582,7 +577,7 @@
"cannot_find_day_note": "无法找到日记",
"cannot_find_week_note": "无法找到周记",
"january": "一月",
"february": "二月",
"febuary": "二月",
"march": "三月",
"april": "四月",
"may": "五月",
@@ -592,18 +587,7 @@
"september": "九月",
"october": "十月",
"november": "十一月",
"december": "十二月",
"week_previous": "上周",
"week_next": "下周",
"month_previous": "上个月",
"month_next": "下个月",
"year": "年",
"year_previous": "上一年",
"year_next": "明年",
"today": "今天",
"week": "周",
"month": "月",
"list": "列表"
"december": "十二月"
},
"close_pane_button": {
"close_this_pane": "关闭此面板"
@@ -646,9 +630,7 @@
"about": "关于 TriliumNext 笔记",
"logout": "登出",
"show-cheatsheet": "显示快捷帮助",
"toggle-zen-mode": "禅模式",
"new-version-available": "新更新可用",
"download-update": "取得版本 {{latestVersion}}"
"toggle-zen-mode": "禅模式"
},
"zen_mode": {
"button_exit": "退出禅模式"
@@ -738,8 +720,7 @@
"insert_child_note": "插入子笔记",
"delete_this_note": "删除此笔记",
"error_cannot_get_branch_id": "无法获取 notePath '{{notePath}}' 的 branchId",
"error_unrecognized_command": "无法识别的命令 {{command}}",
"note_revisions": "笔记历史版本"
"error_unrecognized_command": "无法识别的命令 {{command}}"
},
"note_icon": {
"change_note_icon": "更改笔记图标",
@@ -752,7 +733,7 @@
"editable": "可编辑",
"basic_properties": "基本属性",
"language": "语言",
"configure_code_notes": "配置代码笔记…"
"configure_code_notes": "配置代码注释..."
},
"book_properties": {
"view_type": "视图类型",
@@ -767,9 +748,7 @@
"book_properties": "集合属性",
"table": "表格",
"geo-map": "地理地图",
"board": "看板",
"include_archived_notes": "展示归档笔记",
"presentation": "演示"
"board": "看板"
},
"edited_notes": {
"no_edited_notes_found": "今天还没有编辑过的笔记...",
@@ -970,9 +949,7 @@
"no_attachments": "此笔记没有附件。"
},
"book": {
"no_children_help": "此类型为书籍的笔记没有任何子笔记,因此没有内容显示。请参阅 <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">wiki</a> 了解详情。",
"drag_locked_title": "锁定编辑",
"drag_locked_message": "无法拖拽,因为集合已被锁定编辑。"
"no_children_help": "此类型为书籍的笔记没有任何子笔记,因此没有内容显示。请参阅 <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">wiki</a> 了解详情。"
},
"editable_code": {
"placeholder": "在这里输入您的代码笔记内容..."
@@ -1262,13 +1239,7 @@
"min-days-in-first-week": "第一周的最小天数",
"first-week-info": "第一周包含一年的第一个周四,基于 <a href=\"https://en.wikipedia.org/wiki/ISO_week_date#First_week\">ISO 8601</a> 标准。",
"first-week-warning": "更改第一周选项可能会导致与现有周笔记重复,已创建的周笔记将不会相应更新。",
"formatting-locale": "日期和数字格式",
"tuesday": "周二",
"wednesday": "周三",
"thursday": "周四",
"friday": "周五",
"saturday": "周六",
"formatting-locale-auto": "依应用的语言设置"
"formatting-locale": "日期和数字格式"
},
"backup": {
"automatic_backup": "自动备份",
@@ -1363,7 +1334,7 @@
"oauth_title": "OAuth/OpenID 认证",
"oauth_description": "OpenID 是一种标准化方式,允许您使用其他服务(如 Google的账号登录网站来验证您的身份。默认的身份提供者是 Google但您可以更改为任何其他 OpenID 提供者。点击<a href=\"#root/_hidden/_help/_help_Otzi9La2YAUX/_help_WOcw2SLH6tbX/_help_7DAiwaf8Z7Rz\">这里</a>了解更多信息。请参阅这些 <a href=\"https://developers.google.com/identity/openid-connect/openid-connect\">指南</a> 通过 Google 设置 OpenID 服务。",
"oauth_description_warning": "要启用 OAuth/OpenID您需要设置 config.ini 文件中的 OAuth/OpenID 基础 URL、客户端 ID 和客户端密钥,并重新启动应用程序。如果要从环境变量设置,请设置 TRILIUM_OAUTH_BASE_URL、TRILIUM_OAUTH_CLIENT_ID 和 TRILIUM_OAUTH_CLIENT_SECRET 环境变量。",
"oauth_missing_vars": "缺少以下设置项:{{-variables}}",
"oauth_missing_vars": "缺少以下设置项:{{variables}}",
"oauth_user_account": "用户账号: ",
"oauth_user_email": "用户邮箱: ",
"oauth_user_not_logged_in": "未登录!"
@@ -1436,7 +1407,7 @@
"button-tree-map": "树形地图"
},
"tree-context-menu": {
"open-in-a-new-tab": "在新标签页中打开",
"open-in-a-new-tab": "在新标签页中打开 <kbd>Ctrl+Click</kbd>",
"open-in-a-new-split": "在新分栏中打开",
"insert-note-after": "在后面插入笔记",
"insert-child-note": "插入子笔记",
@@ -1466,9 +1437,7 @@
"converted-to-attachments": "{{count}} 个笔记已被转换为附件。",
"convert-to-attachment-confirm": "确定要将选中的笔记转换为其父笔记的附件吗?",
"duplicate": "复制",
"open-in-popup": "快速编辑",
"archive": "归档",
"unarchive": "解压"
"open-in-popup": "快速编辑"
},
"shared_info": {
"help_link": "访问 <a href=\"https://triliumnext.github.io/Docs/Wiki/sharing.html\">wiki</a> 获取帮助。",
@@ -1633,9 +1602,7 @@
"ws": {
"sync-check-failed": "同步检查失败!",
"consistency-checks-failed": "一致性检查失败!请查看日志了解详细信息。",
"encountered-error": "遇到错误 \"{{message}}\",请查看控制台。",
"lost-websocket-connection-title": "与服务器的连线中断",
"lost-websocket-connection-message": "检查您的反向代理(如 nginx 或 Apache设置以确保 Websocket 连线没有被阻挡。"
"encountered-error": "遇到错误 \"{{message}}\",请查看控制台。"
},
"hoisted_note": {
"confirm_unhoisting": "请求的笔记 '{{requestedNote}}' 位于聚焦的笔记 '{{hoistedNote}}' 的子树之外,您必须取消聚焦才能访问该笔记。是否继续取消聚焦?"
@@ -1711,7 +1678,7 @@
"native-title-bar": "原生标题栏",
"native-title-bar-description": "对于 Windows 和 macOS关闭原生标题栏可使应用程序看起来更紧凑。在 Linux 上,保留原生标题栏可以更好地与系统集成。",
"background-effects": "启用背景效果(仅适用于 Windows 11",
"background-effects-description": "Mica 效果为应用窗口添加模糊且时尚的背景,营造出深度感和现代外观。「原生标题栏」必須被禁用。",
"background-effects-description": "Mica 效果为应用窗口添加模糊且时尚的背景,营造出深度感和现代外观。",
"restart-app-button": "重启应用程序以查看更改",
"zoom-factor": "缩放系数"
},
@@ -1964,11 +1931,7 @@
"editorfeatures": {
"title": "功能",
"emoji_completion_enabled": "启用表情自动补全",
"note_completion_enabled": "启用笔记自动补全",
"emoji_completion_description": "如果启用,表情可以轻易地经由输入 `:` 加上表情名称来插入。",
"note_completion_description": "如果启用,导向笔记的链接可以经由输入 `@` 加上笔记标题来创建。",
"slash_commands_enabled": "启用斜杠命令",
"slash_commands_description": "如果启用,可以经由输入 `/` 来触发命令,如插入换行符或标题。"
"note_completion_enabled": "启用笔记自动补全"
},
"table_view": {
"new-row": "新增行",
@@ -2004,21 +1967,14 @@
"delete_row": "删除行"
},
"board_view": {
"delete-note": "删除笔记...",
"delete-note": "删除笔记",
"move-to": "移动到",
"insert-above": "在上方插入",
"insert-below": "在下方插入",
"delete-column": "删除列",
"delete-column-confirmation": "确定要删除此列吗?此列下所有笔记中对应的属性也将被删除。",
"new-item": "新增项目",
"add-column": "添加列",
"archive-note": "存档笔记",
"unarchive-note": "解压笔记",
"new-item-placeholder": "输入笔记标题...",
"add-column-placeholder": "请输入列名...",
"edit-note-title": "点击编辑笔记标题",
"edit-column-title": "点击编辑列标题",
"remove-from-board": "从看板上移除"
"add-column": "添加列"
},
"command_palette": {
"tree-action-name": "树形:{{name}}",
@@ -2065,20 +2021,6 @@
"title": "性能",
"enable-motion": "启用过渡和动画",
"enable-shadows": "启用阴影",
"enable-backdrop-effects": "启用菜单、弹窗和面板的背景效果",
"enable-smooth-scroll": "启用平滑滚动",
"app-restart-required": "(需重启程序以应用更改)"
},
"pagination": {
"page_title": "第 {{startIndex}} 页 - 第 {{endIndex}} 页",
"total_notes": "{{count}} 笔记"
},
"collections": {
"rendering_error": "出现错误无法显示内容。"
},
"presentation_view": {
"edit-slide": "编辑此幻灯片",
"start-presentation": "开始演示",
"slide-overview": "切换幻灯片概览"
"enable-backdrop-effects": "启用菜单、弹窗和面板的背景效果"
}
}

View File

@@ -1,64 +0,0 @@
{
"about": {
"title": "O Trilium Notes",
"homepage": "Domovská stránka:",
"app_version": "Verze aplikace:",
"db_version": "Verze DB:",
"sync_version": "Verze synchronizace:",
"build_date": "Datum sestavení:",
"build_revision": "Revize sestavení:",
"data_directory": "Datový adresář:"
},
"toast": {
"critical-error": {
"title": "Kritická chyba",
"message": "Nastala kritická chyba která aplikaci brání ve spuštění:\n\n{{message}}\n\nPravděpodobně neočekávaným způsobem selhal skript. Pokuste se restartovat aplikaci v safe módu a problém napravit."
},
"widget-error": {
"title": "Nepodařilo se inicializovat widget",
"message-custom": "Uživatelský widget z poznámky s ID \"{{id}}\" a názvem \"{{title}}\" nemohl být inicializován z důvodu: \n\n{{message}}",
"message-unknown": "Neznámý widget nemohl být inicializován z důvodu:\n\n{{message}}"
},
"bundle-error": {
"title": "Načtení uživatelského skriptu selhalo",
"message": "Uživatelský skript z poznámky s ID \"{{id}}\" a názvem \"{{title}}\" nemohl být spuštěn z důvodu: \n\n{{message}}"
}
},
"ai_llm": {
"n_notes_queued_0": "{{ count }} poznámka ve frontě k indexaci",
"n_notes_queued_1": "{{ count }} poznámky ve frontě k indexaci",
"n_notes_queued_2": "{{ count }} poznámek ve frontě k indexaci",
"notes_indexed_0": "{{ count }} poznámka indexována",
"notes_indexed_1": "{{ count }} poznámky indexovány",
"notes_indexed_2": "{{ count }} poznámek indexováno"
},
"add_link": {
"add_link": "Přidat odkaz",
"help_on_links": "Nápověda k odkazům",
"note": "Poznámka",
"search_note": "hledat poznámku podle názvu",
"link_title": "Název odkazu",
"button_add_link": "Přidat odkaz"
},
"branch_prefix": {
"prefix": "Prefix: ",
"save": "Uložit"
},
"bulk_actions": {
"bulk_actions": "Hromadné akce",
"affected_notes": "Ovlivněné poznámky",
"notes": "Poznámky"
},
"confirm": {
"cancel": "Zrušit",
"ok": "OK"
},
"delete_notes": {
"cancel": "Zrušit",
"ok": "OK",
"close": "Zavřít"
},
"export": {
"close": "Zavřít"
}
}

View File

@@ -276,12 +276,7 @@
"preview": "Vorschau:",
"preview_not_available": "Für diesen Notiztyp ist keine Vorschau verfügbar.",
"restore_button": "Wiederherstellen",
"delete_button": "Löschen",
"diff_on": "Zeige Differenz",
"diff_off": "Zeige Inhalt",
"diff_on_hint": "Klicke, um die Differenz des Notiz-Quellcodes zu zeigen",
"diff_off_hint": "Klicke, um den Notizinhalt zu zeigen",
"diff_not_available": "Differenz-Abgleich ist nicht verfügbar."
"delete_button": "Löschen"
},
"sort_child_notes": {
"sort_children_by": "Unternotizen sortieren nach...",
@@ -581,7 +576,7 @@
"sun": "So",
"cannot_find_day_note": "Tagesnotiz kann nicht gefunden werden",
"january": "Januar",
"february": "Februar",
"febuary": "Februar",
"march": "März",
"april": "April",
"may": "Mai",
@@ -592,18 +587,7 @@
"october": "Oktober",
"november": "November",
"december": "Dezember",
"cannot_find_week_note": "Wochennotiz kann nicht gefunden werden",
"week": "Woche",
"week_previous": "vorherige Woche",
"week_next": "nächste Woche",
"month": "Monat",
"month_previous": "vorheriger Monat",
"month_next": "nächster Monat",
"year": "Jahr",
"year_previous": "vorheriges Jahr",
"year_next": "nächstes Jahr",
"list": "Liste",
"today": "Heute"
"cannot_find_week_note": "Wochennotiz kann nicht gefunden werden"
},
"close_pane_button": {
"close_this_pane": "Schließe diesen Bereich"
@@ -646,8 +630,7 @@
"about": "Über Trilium Notes",
"logout": "Abmelden",
"show-cheatsheet": "Cheatsheet anzeigen",
"toggle-zen-mode": "Zen Modus",
"new-version-available": "Neues Update verfügbar"
"toggle-zen-mode": "Zen Modus"
},
"sync_status": {
"unknown": "<p>Der Synchronisations-Status wird bekannt, sobald der nächste Synchronisierungsversuch gestartet wird.</p><p>Klicke, um eine Synchronisierung jetzt auszulösen.</p>",
@@ -734,8 +717,7 @@
"insert_child_note": "Untergeordnete Notiz einfügen",
"delete_this_note": "Diese Notiz löschen",
"error_cannot_get_branch_id": "BranchId für notePath „{{notePath}}“ kann nicht abgerufen werden",
"error_unrecognized_command": "Unbekannter Befehl {{command}}",
"note_revisions": "Notiz Revisionen"
"error_unrecognized_command": "Unbekannter Befehl {{command}}"
},
"note_icon": {
"change_note_icon": "Notiz-Icon ändern",
@@ -763,9 +745,7 @@
"book_properties": "Sammlungseigenschaften",
"table": "Tabelle",
"geo-map": "Weltkarte",
"board": "Tafel",
"include_archived_notes": "Zeige archivierte Notizen",
"presentation": "Präsentation"
"board": "Tafel"
},
"edited_notes": {
"no_edited_notes_found": "An diesem Tag wurden noch keine Notizen bearbeitet...",
@@ -966,9 +946,7 @@
"no_attachments": "Diese Notiz enthält keine Anhänge."
},
"book": {
"no_children_help": "Diese Notiz mit dem Notiztyp Buch besitzt keine Unternotizen, deshalb ist nichts zum Anzeigen vorhanden. Siehe <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">Wiki</a> für mehr Details.",
"drag_locked_title": "Für Bearbeitung gesperrt",
"drag_locked_message": "Das Ziehen ist nicht möglich, da die Sammlung für die Bearbeitung gesperrt ist."
"no_children_help": "Diese Notiz mit dem Notiztyp Buch besitzt keine Unternotizen, deshalb ist nichts zum Anzeigen vorhanden. Siehe <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">Wiki</a> für mehr Details."
},
"editable_code": {
"placeholder": "Gebe hier den Inhalt deiner Codenotiz ein..."
@@ -1258,13 +1236,7 @@
"min-days-in-first-week": "Mindestanzahl an Tagen in erster Woche",
"first-week-info": "Die erste Woche, die den ersten Donnerstag des Jahres enthält, basiert auf dem Standard <a href=\"https://en.wikipedia.org/wiki/ISO_week_date#First_week\">ISO 8601</a>.",
"first-week-warning": "Das Ändern der Optionen für die erste Woche kann zu Duplikaten mit bestehenden Wochen-Notizen führen. Bestehende Wochen-Notizen werden nicht entsprechend aktualisiert.",
"formatting-locale": "Datums- und Zahlenformat",
"tuesday": "Dienstag",
"wednesday": "Mittwoch",
"thursday": "Donnerstag",
"friday": "Freitag",
"saturday": "Samstag",
"formatting-locale-auto": "Basierend auf die Anwendungssprache"
"formatting-locale": "Datums- und Zahlenformat"
},
"backup": {
"automatic_backup": "Automatische Sicherung",
@@ -1399,7 +1371,7 @@
"button-tree-map": "Baumkarte"
},
"tree-context-menu": {
"open-in-a-new-tab": "In neuem Tab öffnen",
"open-in-a-new-tab": "In neuem Tab öffnen <kbd>Strg+Klick</kbd>",
"open-in-a-new-split": "In neuem Split öffnen",
"insert-note-after": "Notiz dahinter einfügen",
"insert-child-note": "Unternotiz einfügen",
@@ -1429,9 +1401,7 @@
"apply-bulk-actions": "Massenaktionen anwenden",
"converted-to-attachments": "{{count}} Notizen wurden als Anhang konvertiert.",
"convert-to-attachment-confirm": "Bist du sicher, dass du die ausgewählten Notizen in Anhänge ihrer übergeordneten Notizen umwandeln möchtest?",
"open-in-popup": "Schnellbearbeitung",
"archive": "Archiviere",
"unarchive": "Entarchivieren"
"open-in-popup": "Schnellbearbeitung"
},
"shared_info": {
"shared_publicly": "Diese Notiz ist öffentlich geteilt auf {{- link}}.",
@@ -1596,9 +1566,7 @@
"ws": {
"sync-check-failed": "Synchronisationsprüfung fehlgeschlagen!",
"consistency-checks-failed": "Konsistenzprüfung fehlgeschlagen! Siehe Logs für Details.",
"encountered-error": "Fehler „{{message}}“ aufgetreten, siehe Konsole für Details.",
"lost-websocket-connection-title": "Verbindung zum Server verloren",
"lost-websocket-connection-message": "Überprüfe die Konfiguration des Reverse-Proxys (z. B. nginx oder Apache), um sicherzustellen, dass WebSocket-Verbindungen zugelassen und nicht blockiert werden."
"encountered-error": "Fehler „{{message}}“ aufgetreten, siehe Konsole für Details."
},
"hoisted_note": {
"confirm_unhoisting": "Die angeforderte Notiz {{requestedNote}} befindet sich außerhalb des hoisted Bereichs der Notiz {{hoistedNote}}. Du musst sie unhoisten, um auf die Notiz zuzugreifen. Möchtest du mit dem Unhoisting fortfahren?"
@@ -1674,7 +1642,7 @@
"native-title-bar": "Native Anwendungsleiste",
"native-title-bar-description": "In Windows und macOS, sorgt das Deaktivieren der nativen Anwendungsleiste für ein kompakteres Aussehen. Unter Linux, sorgt das Aktivieren der nativen Anwendungsleiste für eine bessere Integration mit anderen Teilen des Systems.",
"background-effects": "Hintergrundeffekte aktivieren (nur Windows 11)",
"background-effects-description": "Der Mica Effekt fügt einen unscharfen, stylischen Hintergrund in Anwendungsfenstern ein. Dieser erzeugt Tiefe und ein modernes Auftreten. \"Native Titelleiste\" muss deaktiviert sein.",
"background-effects-description": "Der Mica Effekt fügt einen unscharfen, stylischen Hintergrund in Anwendungsfenstern ein. Dieser erzeugt Tiefe und ein modernes Auftreten.",
"restart-app-button": "Anwendung neustarten um Änderungen anzuwenden",
"zoom-factor": "Zoomfaktor"
},
@@ -1871,9 +1839,7 @@
"title": "Leistung",
"enable-motion": "Aktiviere Übergänge und Animationen",
"enable-shadows": "Aktiviere Schatten",
"enable-backdrop-effects": "Aktiviere Hintergrundeffekte für Menüs, Pop-up Fenster und Panele",
"enable-smooth-scroll": "Aktiviere sanftes Scrollen",
"app-restart-required": "(Ein Neustart der Anwendung ist erforderlich, damit die Änderungen wirksam werden)"
"enable-backdrop-effects": "Aktiviere Hintergrundeffekte für Menüs, Pop-up Fenster und Panele"
},
"code-editor-options": {
"title": "Editor"
@@ -1912,7 +1878,7 @@
"oauth_title": "OAuth/OpenID",
"oauth_description": "OpenID ist ein standardisiertes Verfahren, mit dem Sie sich über ein Konto eines anderen Dienstes, beispielsweise Google, bei Websites anmelden können, um Ihre Identität zu bestätigen. Der Standardaussteller ist Google, Sie können jedoch jeden anderen OpenID-Anbieter auswählen. Weitere Informationen finden Sie <a href=\"#root/_hidden/_help/_help_Otzi9La2YAUX/_help_WOcw2SLH6tbX/_help_7DAiwaf8Z7Rz\">hier</a>. Befolgen Sie diese <a href=\"https://developers.google.com/identity/openid-connect/openid-connect\">Anweisungen</a>, um einen OpenID-Dienst über Google einzurichten.",
"oauth_description_warning": "Um OAuth/OpenID zu aktivieren, müssen Sie die OAuth/OpenID-Basis-URL, die Client-ID und den Client-Secret in der Datei config.ini festlegen und die Anwendung neu starten. Wenn Sie die Einstellungen über Umgebungsvariablen vornehmen möchten, legen Sie bitte TRILIUM_OAUTH_BASE_URL, TRILIUM_OAUTH_CLIENT_ID und TRILIUM_OAUTH_CLIENT_SECRET fest.",
"oauth_missing_vars": "Fehlende Einstellung: {{-variables}}",
"oauth_missing_vars": "Fehlende Einstellung: {{variables}}",
"oauth_user_account": "Benutzerkonto: ",
"oauth_user_email": "Benutzer E-Mail: ",
"oauth_user_not_logged_in": "Nicht eingeloggt!"
@@ -1977,11 +1943,7 @@
"editorfeatures": {
"title": "Funktionen",
"emoji_completion_enabled": "Emoji-Autovervollständigung aktivieren",
"note_completion_enabled": "Automatisches Vervollständigen von Notizen aktivieren",
"emoji_completion_description": "Wenn aktiviert, können Emojis ganz einfach in den Text eingefügt werden, indem man \":\" gefolgt vom Namen eines Emojis eingibt.",
"note_completion_description": "Wenn aktiviert, können Links zu Notizen erstellt werden, indem man \"@\" gefolgt vom Titel einer Notiz eingibt.",
"slash_commands_enabled": "Aktiviere Slash-Befehle",
"slash_commands_description": "Wenn aktiviert, können Bearbeitungsbefehle wie das Einfügen von Zeilenumbrüchen oder Überschriften durch Eingabe von \"/\" aktiviert werden."
"note_completion_enabled": "Automatisches Vervollständigen von Notizen aktivieren"
},
"table_view": {
"new-row": "Neue Zeile",
@@ -2017,21 +1979,14 @@
"delete_row": "Zeile entfernen"
},
"board_view": {
"delete-note": "Lösche Notiz...",
"delete-note": "Lösche Notiz",
"move-to": "Verschiebe zu",
"insert-above": "Oberhalb einfügen",
"insert-below": "Unterhalb einfügen",
"delete-column": "Spalte entfernen",
"delete-column-confirmation": "Soll die Spalte wirklich gelöscht werden? Abhängige Attribute werden auch in den Notizen unter dieser Spalte gelöscht.",
"new-item": "Neuer Artikel",
"add-column": "Spalte hinzufügen",
"remove-from-board": "Entferne von Tafel",
"archive-note": "archiviere Notiz",
"unarchive-note": "entarchiviere Notiz",
"new-item-placeholder": "Notiz Titel eingeben...",
"add-column-placeholder": "Spaltenname eingeben...",
"edit-note-title": "Klicke zum Editieren des Notiz-Titels",
"edit-column-title": "Klicke zum Editieren des Spalten-Titels"
"add-column": "Spalte hinzufügen"
},
"command_palette": {
"tree-action-name": "Struktur: {{name}}",
@@ -2069,16 +2024,5 @@
},
"units": {
"percentage": "%"
},
"pagination": {
"page_title": "Seite {{startIndex}} von {{endIndex}}",
"total_notes": "{{count}} Notizen"
},
"collections": {
"rendering_error": "Aufgrund eines Fehlers können keine Inhalte angezeigt werden."
},
"presentation_view": {
"edit-slide": "Diese Folie bearbeiten",
"start-presentation": "Präsentation starten"
}
}

View File

@@ -164,7 +164,6 @@
"importIntoNote": "Import into note",
"chooseImportFile": "Choose import file",
"importDescription": "Content of the selected file(s) will be imported as child note(s) into",
"importZipRecommendation": "When importing a ZIP file, the note hierarchy will reflect the subdirectory structure within the archive.",
"options": "Options",
"safeImportTooltip": "Trilium <code>.zip</code> export files can contain executable scripts which may contain harmful behavior. Safe import will deactivate automatic execution of all imported scripts. Uncheck \"Safe import\" only if the imported archive is supposed to contain executable scripts and you completely trust the contents of the import file.",
"safeImport": "Safe import",
@@ -583,7 +582,7 @@
"cannot_find_day_note": "Cannot find day note",
"cannot_find_week_note": "Cannot find week note",
"january": "January",
"february": "February",
"febuary": "February",
"march": "March",
"april": "April",
"may": "May",
@@ -593,18 +592,7 @@
"september": "September",
"october": "October",
"november": "November",
"december": "December",
"week": "Week",
"week_previous": "Previous week",
"week_next": "Next week",
"month": "Month",
"month_previous": "Previous month",
"month_next": "Next month",
"year": "Year",
"year_previous": "Previous year",
"year_next": "Next year",
"list": "List",
"today": "Today"
"december": "December"
},
"close_pane_button": {
"close_this_pane": "Close this pane"
@@ -647,9 +635,7 @@
"about": "About Trilium Notes",
"logout": "Logout",
"show-cheatsheet": "Show Cheatsheet",
"toggle-zen-mode": "Zen Mode",
"new-version-available": "New Update Available",
"download-update": "Get Version {{latestVersion}}"
"toggle-zen-mode": "Zen Mode"
},
"zen_mode": {
"button_exit": "Exit Zen Mode"
@@ -738,7 +724,6 @@
"mobile_detail_menu": {
"insert_child_note": "Insert child note",
"delete_this_note": "Delete this note",
"note_revisions": "Note revisions",
"error_cannot_get_branch_id": "Cannot get branchId for notePath '{{notePath}}'",
"error_unrecognized_command": "Unrecognized command {{command}}"
},
@@ -768,9 +753,7 @@
"calendar": "Calendar",
"table": "Table",
"geo-map": "Geo Map",
"board": "Board",
"presentation": "Presentation",
"include_archived_notes": "Show archived notes"
"board": "Board"
},
"edited_notes": {
"no_edited_notes_found": "No edited notes on this day yet...",
@@ -971,9 +954,7 @@
"no_attachments": "This note has no attachments."
},
"book": {
"no_children_help": "This collection doesn't have any child notes so there's nothing to display. See <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">wiki</a> for details.",
"drag_locked_title": "Locked for editing",
"drag_locked_message": "Dragging not allowed since the collection is locked for editing."
"no_children_help": "This collection doesn't have any child notes so there's nothing to display. See <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">wiki</a> for details."
},
"editable_code": {
"placeholder": "Type the content of your code note here..."
@@ -1418,13 +1399,8 @@
"title": "Localization",
"language": "Language",
"first-day-of-the-week": "First day of the week",
"monday": "Monday",
"tuesday": "Tuesday",
"wednesday": "Wednesday",
"thursday": "Thursday",
"friday": "Friday",
"saturday": "Saturday",
"sunday": "Sunday",
"monday": "Monday",
"first-week-of-the-year": "First week of the year",
"first-week-contains-first-day": "First week contains first day of the year",
"first-week-contains-first-thursday": "First week contains first Thursday of the year",
@@ -1432,8 +1408,7 @@
"min-days-in-first-week": "Minimum days in first week",
"first-week-info": "First week contains first Thursday of the year is based on <a href=\"https://en.wikipedia.org/wiki/ISO_week_date#First_week\">ISO 8601</a> standard.",
"first-week-warning": "Changing first week options may cause duplicate with existing Week Notes and the existing Week Notes will not be updated accordingly.",
"formatting-locale": "Date & number format",
"formatting-locale-auto": "Based on the application's language"
"formatting-locale": "Date & number format"
},
"backup": {
"automatic_backup": "Automatic backup",
@@ -1528,7 +1503,7 @@
"oauth_title": "OAuth/OpenID",
"oauth_description": "OpenID is a standardized way to let you log into websites using an account from another service, like Google, to verify your identity. The default issuer is Google, but you can change it to any other OpenID provider. Check <a href=\"#root/_hidden/_help/_help_Otzi9La2YAUX/_help_WOcw2SLH6tbX/_help_7DAiwaf8Z7Rz\">here</a> for more information. Follow these <a href=\"https://developers.google.com/identity/openid-connect/openid-connect\">instructions</a> to setup an OpenID service through Google.",
"oauth_description_warning": "To enable OAuth/OpenID, you need to set the OAuth/OpenID base URL, client ID and client secret in the config.ini file and restart the application. If you want to set from environment variables, please set TRILIUM_OAUTH_BASE_URL, TRILIUM_OAUTH_CLIENT_ID and TRILIUM_OAUTH_CLIENT_SECRET.",
"oauth_missing_vars": "Missing settings: {{-variables}}",
"oauth_missing_vars": "Missing settings: {{variables}}",
"oauth_user_account": "User Account: ",
"oauth_user_email": "User Email: ",
"oauth_user_not_logged_in": "Not logged in!"
@@ -1601,12 +1576,10 @@
"button-tree-map": "Tree map"
},
"tree-context-menu": {
"open-in-a-new-tab": "Open in a new tab",
"open-in-a-new-tab": "Open in a new tab <kbd>Ctrl+Click</kbd>",
"open-in-a-new-split": "Open in a new split",
"insert-note-after": "Insert note after",
"insert-child-note": "Insert child note",
"archive": "Archive",
"unarchive": "Unarchive",
"delete": "Delete",
"search-in-subtree": "Search in subtree",
"hoist-note": "Hoist note",
@@ -1723,9 +1696,7 @@
"window-on-top": "Keep Window on Top"
},
"note_detail": {
"could_not_find_typewidget": "Could not find typeWidget for type '{{type}}'",
"printing": "Printing in progress...",
"printing_pdf": "Exporting to PDF in progress..."
"could_not_find_typewidget": "Could not find typeWidget for type '{{type}}'"
},
"note_title": {
"placeholder": "type note's title here..."
@@ -1800,9 +1771,7 @@
"ws": {
"sync-check-failed": "Sync check failed!",
"consistency-checks-failed": "Consistency checks failed! See logs for details.",
"encountered-error": "Encountered error \"{{message}}\", check out the console.",
"lost-websocket-connection-title": "Lost connection to the server",
"lost-websocket-connection-message": "Check your reverse proxy (e.g. nginx or Apache) configuration to ensure WebSocket connections are properly allowed and not being blocked."
"encountered-error": "Encountered error \"{{message}}\", check out the console."
},
"hoisted_note": {
"confirm_unhoisting": "Requested note '{{requestedNote}}' is outside of hoisted note '{{hoistedNote}}' subtree and you must unhoist to access the note. Do you want to proceed with unhoisting?"
@@ -1878,7 +1847,7 @@
"native-title-bar": "Native title bar",
"native-title-bar-description": "For Windows and macOS, keeping the native title bar off makes the application look more compact. On Linux, keeping the native title bar on integrates better with the rest of the system.",
"background-effects": "Enable background effects (Windows 11 only)",
"background-effects-description": "The Mica effect adds a blurred, stylish background to app windows, creating depth and a modern look. \"Native title bar\" must be disabled.",
"background-effects-description": "The Mica effect adds a blurred, stylish background to app windows, creating depth and a modern look.",
"restart-app-button": "Restart the application to view the changes",
"zoom-factor": "Zoom factor"
},
@@ -1977,11 +1946,7 @@
"editorfeatures": {
"title": "Features",
"emoji_completion_enabled": "Enable Emoji auto-completion",
"emoji_completion_description": "If enabled, emojis can be easily inserted into text by typing `:`, followed by the name of an emoji.",
"note_completion_enabled": "Enable note auto-completion",
"note_completion_description": "If enabled, links to notes can be created by typing `@` followed by the title of a note.",
"slash_commands_enabled": "Enable slash commands",
"slash_commands_description": "If enabled, editing commands such as inserting line breaks or headings can be toggled by typing `/`."
"note_completion_enabled": "Enable note auto-completion"
},
"table_view": {
"new-row": "New row",
@@ -2017,26 +1982,14 @@
"delete_row": "Delete row"
},
"board_view": {
"delete-note": "Delete note...",
"remove-from-board": "Remove from board",
"archive-note": "Archive note",
"unarchive-note": "Unarchive note",
"delete-note": "Delete Note",
"move-to": "Move to",
"insert-above": "Insert above",
"insert-below": "Insert below",
"delete-column": "Delete column",
"delete-column-confirmation": "Are you sure you want to delete this column? The corresponding attribute will be deleted in the notes under this column as well.",
"new-item": "New item",
"new-item-placeholder": "Enter note title...",
"add-column": "Add Column",
"add-column-placeholder": "Enter column name...",
"edit-note-title": "Click to edit note title",
"edit-column-title": "Click to edit column title"
},
"presentation_view": {
"edit-slide": "Edit this slide",
"start-presentation": "Start presentation",
"slide-overview": "Toggle an overview of the slides"
"add-column": "Add Column"
},
"command_palette": {
"tree-action-name": "Tree: {{name}}",
@@ -2078,12 +2031,5 @@
},
"units": {
"percentage": "%"
},
"pagination": {
"page_title": "Page of {{startIndex}} - {{endIndex}}",
"total_notes": "{{count}} notes"
},
"collections": {
"rendering_error": "Unable to show content due to an error."
}
}

View File

@@ -276,12 +276,7 @@
"mime": "MIME: ",
"file_size": "Tamaño del archivo:",
"preview": "Vista previa:",
"preview_not_available": "La vista previa no está disponible para este tipo de notas.",
"diff_off": "Mostrar contenido",
"diff_on": "Mostrar diferencia",
"diff_off_hint": "Haga clic para mostrar el contenido de la nota",
"diff_not_available": "Diferencias no disponibles.",
"diff_on_hint": "Haga clic para ver las diferencias"
"preview_not_available": "La vista previa no está disponible para este tipo de notas."
},
"sort_child_notes": {
"sort_children_by": "Ordenar hijos por...",
@@ -354,7 +349,7 @@
"calendar_root": "marca la nota que debe usarse como raíz para las notas del día. Sólo uno debe estar marcado como tal.",
"archived": "las notas con esta etiqueta no serán visibles de forma predeterminada en los resultados de búsqueda (tampoco en los cuadros de diálogo Saltar a, Agregar vínculo, etc.).",
"exclude_from_export": "las notas (con su subárbol) no se incluirán en ninguna exportación de notas",
"run": "define en qué eventos debe ejecutarse el script. Los valores posibles son:\n<ul>\n<li>frontendStartup - cuando Trilium frontend se inicia (o se actualiza), pero no en móvil.</li>\n<li>mobileStartup - cuando Trilium frontend se inicia (o se actualiza), en móvil.</li>\n<li>backendStartup - cuando Trilium backend se inicia</li>\n<li>hourly - se ejecuta una vez por hora. Se puede usar la etiqueta adicional <code>runAtHour</code> para especificar a qué hora.</li>\n<li>daily - se ejecuta una vez al día</li>\n</ul>",
"run": "define en qué eventos debe ejecutarse el script. Los valores posibles son:\n<ul>\n<li>frontendStartup - cuando el frontend de Trilium inicia (o es recargado), pero no en dispositivos móviles. </li>\n<li>backendStartup - cuando el backend de Trilium se inicia </li>\n<li>hourly - se ejecuta una vez cada hora. Puede usar etiqueta adicional <code>runAtHour</code> para especificar a la hora. </li>\n<li>daily - ejecutar una vez al día </li>\n</ul>",
"run_on_instance": "Definir en qué instancia de Trilium se debe ejecutar esto. Predeterminado para todas las instancias.",
"run_at_hour": "¿A qué hora debería funcionar? Debe usarse junto con <code>#run=hourly</code>. Se puede definir varias veces para varias ejecuciones durante el día.",
"disable_inclusion": "los scripts con esta etiqueta no se incluirán en la ejecución del script principal.",
@@ -384,7 +379,7 @@
"inbox": "ubicación predeterminada de la bandeja de entrada para nuevas notas - cuando crea una nota usando el botón \"nueva nota\" en la barra lateral, las notas serán creadas como subnotas de la nota marcada con la etiqueta <code>#inbox</code>.",
"workspace_inbox": "ubicación predeterminada de la bandeja de entrada para nuevas notas cuando se anclan a algún antecesor de esta nota del espacio de trabajo",
"sql_console_home": "ubicación predeterminada de las notas de la consola SQL",
"bookmark_folder": "la nota con esta etiqueta aparecerá en los marcadores como carpeta (permitiendo el acceso a sus elementos hijos)",
"bookmark_folder": "la nota con esta etiqueta aparecerá en los marcadores como carpeta (permitiendo el acceso a sus elementos hijos).",
"share_hidden_from_tree": "esta nota está oculta en el árbol de navegación izquierdo, pero aún se puede acceder a ella con su URL",
"share_external_link": "la nota actuará como un enlace a un sitio web externo en el árbol compartido",
"share_alias": "define un alias que al usar la nota va a estar disponible en https://your_trilium_host/share/[tu_alias]",
@@ -582,7 +577,7 @@
"cannot_find_day_note": "No se puede encontrar la nota del día",
"cannot_find_week_note": "No se puede encontrar la nota de la semana",
"january": "Enero",
"february": "Febrero",
"febuary": "Febrero",
"march": "Marzo",
"april": "Abril",
"may": "Mayo",
@@ -592,18 +587,7 @@
"september": "Septiembre",
"october": "Octubre",
"november": "Noviembre",
"december": "Diciembre",
"week": "Semana",
"week_previous": "Semana anterior",
"week_next": "Semana siguiente",
"month": "Mes",
"month_previous": "Mes anterior",
"month_next": "Mes siguiente",
"year": "Año",
"year_previous": "Año anterior",
"year_next": "Año siguiente",
"list": "Lista",
"today": "Hoy"
"december": "Diciembre"
},
"close_pane_button": {
"close_this_pane": "Cerrar este panel"
@@ -646,9 +630,7 @@
"about": "Acerca de Trilium Notes",
"logout": "Cerrar sesión",
"show-cheatsheet": "Mostrar hoja de trucos",
"toggle-zen-mode": "Modo Zen",
"new-version-available": "Nueva actualización disponible",
"download-update": "Obtener versión {{latestVersion}}"
"toggle-zen-mode": "Modo Zen"
},
"zen_mode": {
"button_exit": "Salir del modo Zen"
@@ -738,8 +720,7 @@
"insert_child_note": "Insertar subnota",
"delete_this_note": "Eliminar esta nota",
"error_cannot_get_branch_id": "No se puede obtener el branchID del notePath '{{notePath}}'",
"error_unrecognized_command": "Comando no reconocido {{command}}",
"note_revisions": "Revisiones de notas"
"error_unrecognized_command": "Comando no reconocido {{command}}"
},
"note_icon": {
"change_note_icon": "Cambiar icono de nota",
@@ -767,9 +748,7 @@
"book_properties": "Propiedades de colección",
"table": "Tabla",
"geo-map": "Mapa Geo",
"board": "Tablero",
"include_archived_notes": "Mostrar notas archivadas",
"presentation": "Presentación"
"board": "Tablero"
},
"edited_notes": {
"no_edited_notes_found": "Aún no hay notas editadas en este día...",
@@ -970,9 +949,7 @@
"no_attachments": "Esta nota no tiene archivos adjuntos."
},
"book": {
"no_children_help": "Esta nota de tipo libro no tiene ninguna subnota así que no hay nada que mostrar. Véa la <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">wiki</a> para más detalles.",
"drag_locked_title": "Bloqueado para edición",
"drag_locked_message": "No se permite Arrastrar pues la colección está bloqueada para edición."
"no_children_help": "Esta nota de tipo libro no tiene ninguna subnota así que no hay nada que mostrar. Véa la <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">wiki</a> para más detalles."
},
"editable_code": {
"placeholder": "Escriba el contenido de su nota de código aquí..."
@@ -1014,7 +991,7 @@
"start_dragging_relations": "Empiece a arrastrar relaciones desde aquí y suéltelas en otra nota.",
"note_not_found": "¡Nota {{noteId}} no encontrada!",
"cannot_match_transform": "No se puede coincidir con la transformación: {{transform}}",
"note_already_in_diagram": "La nota \"{{title}}\" ya está en el diagrama.",
"note_already_in_diagram": "Note \"{{title}}\" is already in the diagram.",
"enter_title_of_new_note": "Ingrese el título de la nueva nota",
"default_new_note_title": "nueva nota",
"click_on_canvas_to_place_new_note": "Haga clic en el lienzo para colocar una nueva nota"
@@ -1256,9 +1233,8 @@
"indexing_stopped": "Indexado detenido",
"indexing_in_progress": "Indexado en progreso...",
"last_indexed": "Último indexado",
"n_notes_queued_0": "{{ count }} nota agregada a la cola para indexar",
"n_notes_queued_1": "{{ count }} notas agregadas a la cola para indexar",
"n_notes_queued_2": "",
"n_notes_queued": "{{ count }} nota agregada a la cola para indexado",
"n_notes_queued_plural": "{{ count }} notas agregadas a la cola para indexado",
"note_chat": "Chat de nota",
"notes_indexed": "{{ count }} nota indexada",
"notes_indexed_plural": "{{ count }} notas indexadas",
@@ -1419,13 +1395,7 @@
"min-days-in-first-week": "Días mínimos en la primer semana",
"first-week-info": "Primer semana que contiene al primer jueves del año está basado en el estándar<a href=\"https://en.wikipedia.org/wiki/ISO_week_date#First_week\">ISO 8601</a>.",
"first-week-warning": "Cambiar las opciones de primer semana puede causar duplicados con las Notas Semanales existentes y las Notas Semanales existentes no serán actualizadas respectivamente.",
"formatting-locale": "Fecha y formato de número",
"tuesday": "Martes",
"wednesday": "Miércoles",
"thursday": "Jueves",
"friday": "Viernes",
"saturday": "Sábado",
"formatting-locale-auto": "Basado en el idioma de la aplicación"
"formatting-locale": "Fecha y formato de número"
},
"backup": {
"automatic_backup": "Copia de seguridad automática",
@@ -1518,9 +1488,9 @@
"recovery_keys_used": "Usado: {{date}}",
"recovery_keys_unused": "El código de recuperación {{index}} está sin usar",
"oauth_title": "OAuth/OpenID",
"oauth_description": "OpenID es un método estandarizado que permite iniciar sesión en sitios web usando una cuenta de otro servicio, como Google, para verificar tu identidad. El emisor predeterminado es Google, pero se puede cambiar a cualquier otro proveedor de OpenID. Consulta <a href=\"#root/_hidden/_help/_help_Otzi9La2YAUX/_help_WOcw2SLH6tbX/_help_7DAiwaf8Z7Rz\">aquí</a> para más información. Sigue estas <a href=\"https://developers.google.com/identity/openid-connect/openid-connect\">instrucciones</a> para configurar un servicio OpenID a través de Google.",
"oauth_description": "OpenID es una forma estandarizada de permitirle iniciar sesión en sitios web utilizando una cuenta de otro servicio, como Google, para verificar su identidad. Siga estas <a href = \"https://developers.google.com/identity/openid-connect/openid-connect\">instrucciones</a> para configurar un servicio OpenID a través de Google.",
"oauth_description_warning": "Para habilitar OAuth/OpenID, necesita establecer la URL base de OAuth/OpenID, ID de cliente y secreto de cliente en el archivo config.ini y reiniciar la aplicación. Si desea establecerlas desde variables de ambiente, por favor establezca TRILIUM_OAUTH_BASE_URL, TRILIUM_OAUTH_CLIENT_ID y TRILIUM_OAUTH_CLIENT_SECRET.",
"oauth_missing_vars": "Ajustes faltantes: {{-variables}}",
"oauth_missing_vars": "Ajustes faltantes: {{variables}}",
"oauth_user_account": "Cuenta de usuario: ",
"oauth_user_email": "Correo electrónico de usuario: ",
"oauth_user_not_logged_in": "¡No ha iniciado sesión!"
@@ -1593,7 +1563,7 @@
"button-tree-map": "Mapa de Árbol"
},
"tree-context-menu": {
"open-in-a-new-tab": "Abrir en nueva pestaña",
"open-in-a-new-tab": "Abrir en nueva pestaña <kbd>Ctrl+Click</kbd>",
"open-in-a-new-split": "Abrir en nueva división",
"insert-note-after": "Insertar nota después de",
"insert-child-note": "Insertar subnota",
@@ -1623,13 +1593,11 @@
"apply-bulk-actions": "Aplicar acciones en lote",
"converted-to-attachments": "{{count}} notas han sido convertidas en archivos adjuntos.",
"convert-to-attachment-confirm": "¿Está seguro que desea convertir las notas seleccionadas en archivos adjuntos de sus notas padres?",
"open-in-popup": "Edición rápida",
"archive": "Archivar",
"unarchive": "Desarchivar"
"open-in-popup": "Edición rápida"
},
"shared_info": {
"shared_publicly": "Esta nota está compartida públicamente en {{- link}}.",
"shared_locally": "Esta nota está compartida localmente en {{- link}}.",
"shared_publicly": "Esta nota está compartida públicamente en {{- link}}",
"shared_locally": "Esta nota está compartida localmente en {{- link}}",
"help_link": "Para obtener ayuda visite <a href=\"https://triliumnext.github.io/Docs/Wiki/sharing.html\">wiki</a>."
},
"note_types": {
@@ -1708,8 +1676,7 @@
"hoist-this-note-workspace": "Anclar esta nota (espacio de trabajo)",
"refresh-saved-search-results": "Refrescar resultados de búsqueda guardados",
"create-child-note": "Crear subnota",
"unhoist": "Desanclar",
"toggle-sidebar": "Alternar barra lateral"
"unhoist": "Desanclar"
},
"title_bar_buttons": {
"window-on-top": "Mantener esta ventana en la parte superior"
@@ -1784,15 +1751,13 @@
"undeleting-notes-finished-successfully": "La recuperación de notas finalizó exitosamente."
},
"frontend_script_api": {
"async_warning": "Está pasando una función asíncrona a `api.runOnBackend ()` que probablemente no funcionará como pretendía.\\nO haga la función sincrónica (removiendo la palabra `async`), o use `api.runAsyncOnBackendWithManualTransactionHandling()`.",
"sync_warning": "Estás pasando una función sincrónica a `api.runasynconbackendwithmanualTransactionHandling ()`, \\n while debería usar `api.runonbackend ()` en su lugar."
"async_warning": "Está pasando una función asíncrona a `api.runOnBackend ()` que probablemente no funcionará como pretendía.",
"sync_warning": "Estás pasando una función sincrónica a `api.runasynconbackendwithmanualTransactionHandling ()`, \\ n while debería usar `api.runonbackend ()` en su lugar."
},
"ws": {
"sync-check-failed": "¡La comprobación de sincronización falló!",
"consistency-checks-failed": "¡Las comprobaciones de consistencia fallaron! Vea los registros para más detalles.",
"encountered-error": "Error encontrado \"{{message}}\", compruebe la consola.",
"lost-websocket-connection-title": "Se ha perdido la conexión con el servidor",
"lost-websocket-connection-message": "Compruebe la configuración de su proxy inverso (por ejemplo, nginx o Apache) para asegurarse de que las conexiones WebSocket están correctamente permitidas y no están bloqueadas."
"encountered-error": "Error encontrado \"{{message}}\", compruebe la consola."
},
"hoisted_note": {
"confirm_unhoisting": "La nota requerida '{{requestedNote}}' está fuera del subárbol de la nota anclada '{{hoistedNote}}' y debe desanclarla para acceder a la nota. ¿Desea proceder con el desanclaje?"
@@ -1868,7 +1833,7 @@
"native-title-bar": "Barra de título nativa",
"native-title-bar-description": "Para Windows y macOS, quitar la barra de título nativa hace que la aplicación se vea más compacta. En Linux, mantener la barra de título nativa hace que se integre mejor con el resto del sistema.",
"background-effects": "Habilitar efectos de fondo (sólo en Windows 11)",
"background-effects-description": "El efecto Mica agrega un fondo borroso y elegante a las ventanas de la aplicación, creando profundidad y un aspecto moderno. \"Título nativo de la barra\" debe deshabilitarse.",
"background-effects-description": "El efecto Mica agrega un fondo borroso y elegante a las ventanas de aplicaciones, creando profundidad y un aspecto moderno.",
"restart-app-button": "Reiniciar la aplicación para ver los cambios",
"zoom-factor": "Factor de zoom"
},
@@ -1978,21 +1943,14 @@
"delete_row": "Eliminar fila"
},
"board_view": {
"delete-note": "Eliminar nota...",
"delete-note": "Eliminar nota",
"move-to": "Mover a",
"insert-above": "Insertar arriba",
"insert-below": "Insertar abajo",
"delete-column": "Eliminar columna",
"delete-column-confirmation": "¿Seguro que desea eliminar esta columna? El atributo correspondiente también se eliminará de las notas de esta columna.",
"add-column": "Añadir columna",
"new-item": "Nuevo elemento",
"archive-note": "Archivar nota",
"unarchive-note": "Desarchivar nota",
"new-item-placeholder": "Ingresar título de la nota...",
"add-column-placeholder": "Ingresar título de la columna...",
"edit-note-title": "Haga clic para editar el título de la nota",
"edit-column-title": "Haga clic para editar el título de la columna",
"remove-from-board": "Eliminar del tablero"
"new-item": "Nuevo elemento"
},
"content_renderer": {
"open_externally": "Abrir externamente"
@@ -2020,11 +1978,7 @@
"editorfeatures": {
"note_completion_enabled": "Activar autocompletado de notas",
"emoji_completion_enabled": "Activar autocompletado de emojis",
"title": "Funciones",
"emoji_completion_description": "Si está habilitado, los emojis pueden fácilmente insertarse en el texto escribiendo `:`, seguido del nombre de un emoji.",
"note_completion_description": "Si está habilitado, los vínculos a notas pueden crearse escribiendo `@` seguido del título de una nota.",
"slash_commands_enabled": "Habilitar comandos de barra",
"slash_commands_description": "Si está habilitado, editar comandos como insertar saltos de línea o títulos, puede alternarse escribiendo `/`."
"title": "Funciones"
},
"command_palette": {
"tree-action-name": "Árbol:{{name}}",
@@ -2047,7 +2001,7 @@
},
"call_to_action": {
"next_theme_title": "Prueba el nuevo tema de Trilium",
"next_theme_message": "Estás usando actualmente el tema heredado. ¿Te gustaría probar el nuevo tema?",
"next_theme_message": "Estas usando actualmente el tema heredado, ¿Te gustaría probar el nuevo tema?",
"next_theme_button": "Prueba el nuevo tema",
"background_effects_title": "Los efectos de fondo son ahora estables",
"background_effects_message": "En los dispositivos Windows, los efectos de fondo ya son totalmente estables. Los efectos de fondo añaden un toque de color a la interfaz de usuario difuminando el fondo que hay detrás. Esta técnica también se utiliza en otras aplicaciones como el Explorador de Windows.",
@@ -2058,9 +2012,7 @@
"title": "Rendimiento",
"enable-motion": "Habilitar transiciones y animaciones",
"enable-shadows": "Activar sombras",
"enable-backdrop-effects": "Habilitar efectos de fondo para menús, ventanas emergentes y paneles",
"enable-smooth-scroll": "Habilitar desplazamiento suave",
"app-restart-required": "(es necesario reiniciar la aplicación para que el cambio surta efecto)"
"enable-backdrop-effects": "Habilitar efectos de fondo para menús, ventanas emergentes y paneles"
},
"settings": {
"related_settings": "Configuración relacionada"
@@ -2071,17 +2023,5 @@
},
"units": {
"percentage": "%"
},
"pagination": {
"total_notes": "{{count}} notas",
"page_title": "Página de {{startIndex}} - {{endIndex}}"
},
"presentation_view": {
"edit-slide": "Editar este slide",
"start-presentation": "Iniciar presentación",
"slide-overview": "Alternar vista general de los slides"
},
"collections": {
"rendering_error": "No se puede mostrar contenido debido a un error."
}
}

View File

@@ -15,9 +15,6 @@
},
"widget-error": {
"title": "Widgetin luonti epäonnistui"
},
"bundle-error": {
"title": "Mukautetun skriptin lataus epäonnistui"
}
},
"add_link": {

View File

@@ -276,12 +276,7 @@
"preview": "Aperçu :",
"preview_not_available": "L'aperçu n'est pas disponible pour ce type de note.",
"restore_button": "Restaurer",
"delete_button": "Supprimer",
"diff_on": "Afficher les différences",
"diff_off": "Afficher le contenu",
"diff_on_hint": "Cliquez pour afficher les différences de la note d'origine",
"diff_off_hint": "Cliquez pour afficher le contenu de la note",
"diff_not_available": "La comparaison n'est pas disponible."
"delete_button": "Supprimer"
},
"sort_child_notes": {
"sort_children_by": "Trier les enfants par...",
@@ -581,7 +576,7 @@
"sun": "Dim",
"cannot_find_day_note": "Note journalière introuvable",
"january": "Janvier",
"february": "Février",
"febuary": "Février",
"march": "Mars",
"april": "Avril",
"may": "Mai",
@@ -592,18 +587,7 @@
"october": "Octobre",
"november": "Novembre",
"december": "Décembre",
"cannot_find_week_note": "Impossible de trouver la note de la semaine",
"week": "Semaine",
"week_previous": "Semaine précédente",
"week_next": "Semaine suivante",
"month": "Mois",
"month_previous": "Mois précédent",
"month_next": "Mois suivant",
"year": "Année",
"year_previous": "Année précédente",
"year_next": "Année suivante",
"list": "Liste",
"today": "Aujourd'hui"
"cannot_find_week_note": "Impossible de trouver la note de la semaine"
},
"close_pane_button": {
"close_this_pane": "Fermer ce volet"
@@ -736,8 +720,7 @@
"insert_child_note": "Insérer une note enfant",
"delete_this_note": "Supprimer cette note",
"error_cannot_get_branch_id": "Impossible d'obtenir branchId pour notePath '{{notePath}}'",
"error_unrecognized_command": "Commande non reconnue {{command}}",
"note_revisions": "Révision de la note"
"error_unrecognized_command": "Commande non reconnue {{command}}"
},
"note_icon": {
"change_note_icon": "Changer l'icône de note",
@@ -749,8 +732,7 @@
"note_type": "Type de note",
"editable": "Modifiable",
"basic_properties": "Propriétés de base",
"language": "Langage",
"configure_code_notes": "Configurer les notes de code..."
"language": "Langage"
},
"book_properties": {
"view_type": "Type d'affichage",
@@ -765,8 +747,7 @@
"book_properties": "Propriétés de la collection",
"table": "Tableau",
"geo-map": "Carte géographique",
"board": "Tableau de bord",
"include_archived_notes": "Afficher les notes archivées"
"board": "Tableau de bord"
},
"edited_notes": {
"no_edited_notes_found": "Aucune note modifiée ce jour-là...",
@@ -967,9 +948,7 @@
"no_attachments": "Cette note ne contient aucune pièce jointe."
},
"book": {
"no_children_help": "Cette note de type Livre n'a aucune note enfant, donc il n'y a rien à afficher. Consultez le <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">wiki</a> pour plus de détails.",
"drag_locked_title": "Edition verrouillée",
"drag_locked_message": "Le glisser-déposer n'est pas autorisé car l'édition de cette collection est verrouillé."
"no_children_help": "Cette note de type Livre n'a aucune note enfant, donc il n'y a rien à afficher. Consultez le <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">wiki</a> pour plus de détails."
},
"editable_code": {
"placeholder": "Saisir le contenu de votre note de code ici..."
@@ -1378,7 +1357,7 @@
"button-tree-map": "Carte de l'arborescence"
},
"tree-context-menu": {
"open-in-a-new-tab": "Ouvrir dans un nouvel onglet",
"open-in-a-new-tab": "Ouvrir dans un nouvel onglet <kbd>Ctrl+Clic</kbd>",
"open-in-a-new-split": "Ouvrir dans une nouvelle division",
"insert-note-after": "Insérer une note après",
"insert-child-note": "Insérer une note enfant",
@@ -1631,8 +1610,7 @@
"link_context_menu": {
"open_note_in_new_tab": "Ouvrir la note dans un nouvel onglet",
"open_note_in_new_split": "Ouvrir la note dans une nouvelle division",
"open_note_in_new_window": "Ouvrir la note dans une nouvelle fenêtre",
"open_note_in_popup": "Édition rapide"
"open_note_in_new_window": "Ouvrir la note dans une nouvelle fenêtre"
},
"electron_integration": {
"desktop-application": "Application de bureau",
@@ -1712,79 +1690,6 @@
"anthropic_configuration": "Configuration Anthropic",
"voyage_configuration": "Configuration IA Voyage",
"voyage_url_description": "Défaut: https://api.voyageai.com/v1",
"ollama_configuration": "Configuration Ollama",
"total_notes": "Notes totales",
"progress": "Progrès",
"queued_notes": "Notes dans la file d'attente",
"refresh_stats": "Rafraîchir les statistiques",
"enable_ai_features": "Activer les fonctionnalités IA/LLM",
"enable_ai_description": "Activer les fonctionnalités IA telles que le résumé des notes, la génération de contenu et autres fonctionnalités LLM",
"openai_tab": "OpenAI",
"anthropic_tab": "Anthropic",
"voyage_tab": "Voyage AI",
"ollama_tab": "Ollama",
"enable_ai": "Activer les fonctionnalités IA/LLM",
"enable_ai_desc": "Activer les fonctionnalités IA telles que le résumé des notes, la génération de contenu et autres fonctionnalités LLM",
"provider_configuration": "Configuration du fournisseur IA",
"provider_precedence_description": "Liste de fournisseurs séparés par virgule, par ordre de préférence (ex. 'openai,anthopic,ollama')",
"temperature": "Température",
"temperature_description": "Contrôle de l'aléatoirité dans les réponses (0 = déterministe, 2 = hasard maximum)",
"system_prompt": "Prompt système",
"system_prompt_description": "Prompt système par défaut pour toutes les intéractions IA",
"openai_configuration": "Configuration OpenAI",
"openai_settings": "Options OpenAI",
"api_key": "Clef API",
"url": "URL de base",
"model": "Modèle",
"openai_api_key_description": "Votre clef API OpenAI pour accéder à leurs services IA",
"anthropic_api_key_description": "Votre clef API Anthropic pour accéder aux modèles Claude",
"default_model": "Modèle par défaut",
"openai_model_description": "Exemples : gpt-4o, gpt-4-turbo, gpt-3.5-turbo",
"base_url": "URL de base",
"openai_url_description": "Défaut : https://api.openai.com/v1",
"anthropic_settings": "Réglages Anthropic",
"enable_ollama": "Activer Ollama",
"enable_ollama_description": "Activer Ollama comme modèle d'IA local",
"ollama_url": "URL Ollama",
"ollama_model": "Modèle Ollama",
"refresh_models": "Rafraîchir les modèles",
"refreshing_models": "Mise à jour...",
"enable_automatic_indexing": "Activer l'indexage automatique",
"rebuild_index": "Rafraîchir l'index",
"rebuild_index_error": "Erreur dans le démarrage du rafraichissement de l'index. Veuillez consulter les logs pour plus de détails.",
"note_title": "Titre de la note",
"error": "Erreur",
"last_attempt": "Dernier essai",
"actions": "Actions",
"retry": "Réessayer",
"partial": "Complété à {{ percentage }}%",
"retry_queued": "Note ajoutée à la file d'attente",
"retry_failed": "Echec de l'ajout de la note à la file d'attente",
"max_notes_per_llm_query": "Notes maximum par requête",
"max_notes_per_llm_query_description": "Nombre maximum de notes similaires à inclure dans le contexte IA",
"active_providers": "Fournisseurs actifs",
"disabled_providers": "Fournisseurs désactivés",
"remove_provider": "Retirer le fournisseur de la recherche",
"similarity_threshold": "Seuil de similarité",
"similarity_threshold_description": "Seuil de similarité minimum (0-1) pour que inclure les notes dans le contexte d'une requête IA",
"reprocess_index": "Rafraîchir l'index de recherche",
"reprocessing_index": "Mise à jour...",
"reprocess_index_started": "L'optimisation de l'indice de recherche à commencer en arrière-plan",
"reprocess_index_error": "Erreur dans le rafraichissement de l'indice de recherche",
"failed_notes": "Notes échouées",
"last_processed": "Dernier traitement",
"restore_provider": "Restaurer le fournisseur de la recherche",
"index_rebuild_progress": "Progression de la reconstruction de l'index",
"index_rebuilding": "Optimisation de l'index ({{percentage}}%)",
"index_rebuild_complete": "Optimisation de l'index terminée",
"index_rebuild_status_error": "Erreur lors de la vérification de l'état de reconstruction de l'index"
},
"ui-performance": {
"title": "Performance",
"enable-motion": "Activer les transitions et animations",
"enable-shadows": "Activer les ombres",
"enable-backdrop-effects": "Activer les effets d'arrière plan pour les menus, popups et panneaux",
"enable-smooth-scroll": "Active le défilement fluide",
"app-restart-required": "(redémarrer l'application pour appliquer les changements)"
"ollama_configuration": "Configuration Ollama"
}
}

View File

@@ -1 +0,0 @@
{}

View File

@@ -1,32 +0,0 @@
{
"about": {
"title": "Tentang Trilium Notes",
"homepage": "Halaman utama:",
"app_version": "Versi Aplikasi:",
"db_version": "Versi DB:",
"sync_version": "Versi sinkronisasi:",
"build_date": "Tanggal pembuatan:",
"build_revision": "Revisi pembuatan:",
"data_directory": "Direktori data:"
},
"toast": {
"critical-error": {
"title": "Kesalahan kritis",
"message": "Telah terjadi kesalahan kritis yang mencegah aplikasi klien untuk memulai:\n\n{{message}}\n\nHal ini kemungkinan besar disebabkan oleh skrip yang gagal secara tidak terduga. Coba jalankan aplikasi dalam mode aman dan atasi masalahnya."
},
"widget-error": {
"title": "Gagal menginisialisasi widget",
"message-custom": "Widget kustom dari catatan dengan ID \"{{id}}\", berjudul \"{{title}}\" tidak dapat diinisialisasi karena:\n\n{{message}}",
"message-unknown": "Widget tidak dikenal tidak dapat diinisialisasi karena:\n\n{{message}}"
},
"bundle-error": {
"title": "Gagal memuat skrip kustom",
"message": "Skrip dari catatan dengan ID \"{{id}}\", berjudul \"{{title}}\" tidak dapat dijalankan karena:\n\n{{message}}"
}
},
"add_link": {
"add_link": "Tambah tautan",
"help_on_links": "Bantuan pada tautan",
"note": "Catatan"
}
}

View File

@@ -20,7 +20,7 @@
},
"widget-error": {
"title": "Impossibile inizializzare un widget",
"message-custom": "Il widget personalizzato dalla nota con ID {{id}}”, intitolato “{{title}}”, non è stato possibile inizializzare a causa di:\n\n{{message}}",
"message-custom": "Il widget personalizzato della nota con ID \"{{id}}\", dal titolo \"{{title}}\" non è stato inizializzato a causa di:\n\n{{message}}",
"message-unknown": "Un widget sconosciuto non è stato inizializzato a causa di:\n\n{{message}}"
}
},
@@ -31,7 +31,7 @@
"link_title_mirrors": "il titolo del collegamento rispecchia il titolo della nota corrente",
"link_title_arbitrary": "il titolo del collegamento può essere modificato arbitrariamente",
"link_title": "Titolo del collegamento",
"button_add_link": "Aggiungi il collegamento",
"button_add_link": "Aggiungi il collegamento <kbd>invio</kbd>",
"help_on_links": "Aiuto sui collegamenti"
},
"branch_prefix": {
@@ -63,7 +63,7 @@
"search_for_note_by_its_name": "cerca una nota per nome",
"cloned_note_prefix_title": "Le note clonate saranno mostrate nell'albero delle note con il dato prefisso",
"prefix_optional": "Prefisso (opzionale)",
"clone_to_selected_note": "Clona verso la nota selezionata <kbd>invio</kbd>",
"clone_to_selected_note": "Clona sotto la nota selezionata <kbd>invio</kbd>",
"no_path_to_clone_to": "Nessun percorso per clonare dentro.",
"note_cloned": "La nota \"{{clonedTitle}}\" è stata clonata in \"{{targetTitle}}\""
},
@@ -79,19 +79,18 @@
"ok": "OK",
"close": "Chiudi",
"delete_notes_preview": "Anteprima di eliminazione delle note",
"delete_all_clones_description": "Elimina anche tutti i cloni (può essere ripristinato nella sezione cambiamenti recenti)",
"delete_all_clones_description": "Elimina anche tutti i cloni (può essere disfatto tramite i cambiamenti recenti)",
"erase_notes_description": "L'eliminazione normale (soft) marca le note come eliminate e potranno essere recuperate entro un certo lasso di tempo (dalla finestra dei cambiamenti recenti). Selezionando questa opzione le note si elimineranno immediatamente e non sarà possibile recuperarle.",
"erase_notes_warning": "Elimina le note in modo permanente (non potrà essere disfatto), compresi tutti i cloni. Ciò forzerà un nuovo caricamento dell'applicazione.",
"cancel": "Annulla",
"notes_to_be_deleted": "Le seguenti note saranno eliminate ({{notesCount}})",
"notes_to_be_deleted": "Le seguenti note saranno eliminate ({{- noteCount}})",
"no_note_to_delete": "Nessuna nota sarà eliminata (solo i cloni).",
"broken_relations_to_be_deleted": "Le seguenti relazioni saranno interrotte ed eliminate ({{relationCount}})",
"broken_relations_to_be_deleted": "Le seguenti relazioni saranno interrotte ed eliminate ({{- relationCount}})",
"deleted_relation_text": "La nota {{- note}} (da eliminare) è referenziata dalla relazione {{- relation}} originata da {{- source}}."
},
"info": {
"okButton": "OK",
"closeButton": "Chiudi",
"modalTitle": "Messaggio informativo"
"closeButton": "Chiudi"
},
"export": {
"close": "Chiudi",
@@ -106,30 +105,21 @@
"format_html": "HTML - raccomandato in quanto mantiene tutti i formati",
"format_html_zip": "HTML in archivio ZIP - questo è raccomandato in quanto conserva tutta la formattazione.",
"format_markdown": "MArkdown - questo conserva la maggior parte della formattazione.",
"export_type_single": "Solo questa nota, senza le sottostanti",
"format_opml": "OPML - formato per scambio informazioni outline. Formattazione, immagini e files non sono inclusi.",
"opml_version_1": "OPML v.1.0 - solo testo semplice",
"opml_version_2": "OPML v2.0 - supporta anche HTML"
"export_type_single": "Solo questa nota, senza le sottostanti"
},
"password_not_set": {
"body1": "Le note protette sono crittografate utilizzando una password utente, ma la password non è stata ancora impostata.",
"body2": "Per proteggere le note, clicca sul pulsante sottostante per aprire la finestra di dialogo Opzioni e impostare la tua password.",
"title": "La password non è impostata",
"go_to_password_options": "Vai alle opzioni della password"
"body2": "Per proteggere le note, fare clic su <a class=\"open-password-options-button\" href=\"javascript:\">qui</a> per aprire la finestra di dialogo Opzioni e impostare la password."
},
"protected_session_password": {
"close_label": "Chiudi",
"modal_title": "Sessione protetta",
"help_title": "Aiuto sulle note protette",
"form_label": "Per procedere con lazione richiesta, è necessario avviare una sessione protetta inserendo la password:",
"start_button": "Avvia sessione protetta"
"close_label": "Chiudi"
},
"abstract_bulk_action": {
"remove_this_search_action": "Rimuovi questa azione di ricerca"
},
"etapi": {
"new_token_title": "Nuovo token ETAPI",
"new_token_message": "Inserisci il nome del nuovo token"
"new_token_message": "Inserire il nuovo nome del token"
},
"electron_integration": {
"zoom-factor": "Fattore di ingrandimento",
@@ -137,7 +127,7 @@
},
"note_autocomplete": {
"search-for": "Cerca \"{{term}}\"",
"create-note": "Crea e collega la nota secondaria {{term}}",
"create-note": "Crea e collega la nota figlia \"{{term}}\"",
"insert-external-link": "Inserisci il collegamento esterno a \"{{term}}\"",
"clear-text-field": "Pulisci il campo di testo",
"show-recent-notes": "Mostra le note recenti",
@@ -162,20 +152,20 @@
},
"database_anonymization": {
"light_anonymization": "Anonimizzazione parziale",
"title": "Anonimizzazione dei database",
"title": "Anonimizzazione del Database",
"full_anonymization": "Anonimizzazione completa",
"full_anonymization_description": "Questa azione creerà una nuova copia del database e la renderà anonima (rimuovendo tutto il contenuto delle note e lasciando solo la struttura e alcuni metadati non sensibili) per poterla condividere online a scopo di debug senza timore di divulgare i tuoi dati personali.",
"save_fully_anonymized_database": "Salva database completamente anonimizzato",
"full_anonymization_description": "Questa azione creerà una nuova copia del database e lo anonimizzerà (rimuove tutti i contenuti delle note, lasciando solo la struttura e qualche metadato non sensibile) per condividerlo online allo scopo di debugging, senza paura di far trapelare i tuoi dati personali.",
"save_fully_anonymized_database": "Salva il database completamente anonimizzato",
"light_anonymization_description": "Questa azione creerà una nuova copia del database e lo anonimizzerà in parzialmente — in particolare, solo il contenuto delle note sarà rimosso, ma i titoli e gli attributi rimarranno. Inoltre, note con script personalizzati JS di frontend/backend e widget personalizzati lasciando rimarranno. Ciò mette a disposizione più contesto per il debug dei problemi.",
"choose_anonymization": "Puoi decidere da solo se fornire un database completamente o parzialmente anonimizzato. Anche un database completamente anonimizzato è molto utile, sebbene in alcuni casi i database parzialmente anonimizzati possono accelerare il processo di identificazione dei bug e la loro correzione.",
"no_anonymized_database_yet": "Ancora nessun database anonimizzato.",
"save_lightly_anonymized_database": "Salva database leggermente anonimizzato",
"no_anonymized_database_yet": "Nessun database ancora anonimizzato.",
"save_lightly_anonymized_database": "Salva il database parzialmente anonimizzato",
"successfully_created_fully_anonymized_database": "Database completamente anonimizzato creato in {{anonymizedFilePath}}",
"successfully_created_lightly_anonymized_database": "Database parzialmente anonimizzato creato in {{anonymizedFilePath}}"
},
"cpu_arch_warning": {
"title": "Per favore scarica la versione ARM64",
"continue_anyway": "Continua comunque",
"continue_anyway": "Continua Comunque",
"dont_show_again": "Non mostrare più questo avviso",
"download_link": "Scarica la Versione Nativa"
},
@@ -255,7 +245,7 @@
"debug": "debug",
"action": "azione",
"add_search_option": "Aggiungi un opzione di ricerca:",
"search_string": "stringa di ricerca",
"search_string": "cerca la stringa",
"limit": "limite"
},
"modal": {
@@ -276,10 +266,8 @@
"date-and-time": "Data e ora",
"path": "Percorso",
"database_backed_up_to": "Il database è stato archiviato in {{backupFilePath}}",
"enable_daily_backup": "Abilita i backup giornalieri",
"no_backup_yet": "Ancora nessuna archiviazione",
"automatic_backup": "Backup Automatico",
"automatic_backup_description": "Trilium può eseguire automaticamente il backup del database:"
"enable_daily_backup": "Abilita le archiviazioni giornaliere",
"no_backup_yet": "Ancora nessuna archiviazione"
},
"backend_log": {
"refresh": "Aggiorna"
@@ -340,12 +328,12 @@
},
"heading_style": {
"title": "Stile dell'Intestazione",
"plain": "Semplice",
"plain": "Normale",
"underline": "Sottolineato",
"markdown": "Stile Markdown"
},
"highlights_list": {
"title": "Elenco dei punti salienti"
"title": "Punti salienti"
},
"highlights_list_2": {
"title": "Punti salienti",
@@ -360,346 +348,6 @@
"collapseExpand": "collassa/espande il nodo",
"notSet": "non impostato",
"goBackForwards": "indietro/avanti nella cronologia",
"showJumpToNoteDialog": "mostra <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/note-navigation.html#jump-to-note\">finestra di dialogo “Vai a”</a>",
"title": "Scheda riassuntiva",
"noteNavigation": "Nota navigazione",
"scrollToActiveNote": "scorri fino alla nota attiva",
"jumpToParentNote": "vai alla nota principale",
"collapseWholeTree": "comprimi l'intero albero delle note",
"collapseSubTree": "comprimi sottoalbero",
"tabShortcuts": "Scorciatoie delle schede",
"newTabNoteLink": "Il link alla nota apre la nota in una nuova scheda",
"newTabWithActivationNoteLink": "Il link alla nota si apre e attiva la nota in una nuova scheda",
"onlyInDesktop": "Solo nella versione desktop (Electron build)",
"openEmptyTab": "apri scheda vuota",
"closeActiveTab": "chiudi scheda attiva",
"activateNextTab": "attiva la scheda successiva",
"activatePreviousTab": "attiva la scheda precedente",
"creatingNotes": "Creazione di note",
"createNoteAfter": "crea una nuova nota dopo quella attiva",
"createNoteInto": "crea una nuova sotto-nota nella nota attiva",
"editBranchPrefix": "modifica <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/tree-concepts.html#prefix\">prefisso</a> del clone della nota attiva",
"movingCloningNotes": "Spostamento / clonazione delle note",
"moveNoteUpDown": "spostare la nota verso l'alto/verso il basso nell'elenco delle note",
"moveNoteUpHierarchy": "spostare la nota verso l'alto nella gerarchia",
"multiSelectNote": "nota multi-selezione sopra/sotto",
"selectAllNotes": "seleziona tutte le note del livello corrente",
"selectNote": "seleziona nota",
"copyNotes": "copia la nota attiva (o la selezione corrente) negli appunti (utilizzata per la <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/cloning-notes.html#cloning-notes\">clonazione</a>)",
"cutNotes": "taglia la nota corrente (o la selezione corrente) negli appunti (utilizzato per spostare le note)",
"pasteNotes": "Incolla le note come sotto-note nella nota attiva (che viene spostata o clonata a seconda che sia stata copiata o tagliata negli appunti)",
"deleteNotes": "eliminazione nota / sottoalbero",
"editingNotes": "Modifica delle note",
"editNoteTitle": "nel riquadro ad albero passa dal riquadro ad albero al titolo della nota. Premendo Invio dal titolo della nota, il focus passerà all'editor di testo. <kbd>Ctrl+.</kbd> riporterà il focus dall'editor al riquadro ad albero.",
"createEditLink": "crea / modifica collegamento esterno",
"createInternalLink": "creare un collegamento interno",
"followLink": "segui il link sotto il cursore",
"insertDateTime": "inserisci la data e l'ora correnti nella posizione del cursore",
"jumpToTreePane": "passa al riquadro dell'albero e scorri fino alla nota attiva",
"markdownAutoformat": "Formattazione automatica simile a Markdown",
"headings": "<code>##</code>, <code>###</code>, <code>####</code> ecc. seguiti da uno spazio per i titoli",
"bulletList": "<code>*</code> o <code>-</code> seguito da uno spazio per un elenco puntato",
"numberedList": "<code>1.</code> o <code>1)</code> seguito da uno spazio per un elenco numerato",
"blockQuote": "inizia una riga con <code>></code> seguito da uno spazio per il blocco di citazione",
"troubleshooting": "Risoluzione dei problemi",
"reloadFrontend": "ricarica il frontend Trilium",
"showDevTools": "mostra strumenti di sviluppo",
"showSQLConsole": "mostra console SQL",
"other": "Altro",
"quickSearch": "concentrati sull'input della ricerca rapida",
"inPageSearch": "ricerca all'interno della pagina"
},
"i18n": {
"saturday": "Sabato",
"sunday": "Domenica",
"first-week-of-the-year": "Prima settimana dell'anno",
"first-week-contains-first-day": "La prima settimana contiene il primo giorno dell'anno",
"first-week-contains-first-thursday": "La prima settimana contiene il primo giovedì dell'anno",
"first-week-has-minimum-days": "La prima settimana ha giorni ridotti",
"min-days-in-first-week": "Giorni minimi nella prima settimana",
"first-week-info": "La prima settimana che contiene il primo giovedì dell'anno si basa su <a href=\"https://en.wikipedia.org/wiki/ISO_week_date#First_week\">ISO 8601</a> standard.",
"first-week-warning": "La modifica delle opzioni della prima settimana può causare duplicati con le note settimanali esistenti e queste ultime non verranno aggiornate di conseguenza.",
"formatting-locale": "Formato data e numero",
"formatting-locale-auto": "In base alla lingua dell'applicazione"
},
"ai_llm": {
"n_notes_queued_0": "{{ count }} nota in coda per l'indicizzazione",
"n_notes_queued_1": "{{ count }} note in coda per l'indicizzazione",
"n_notes_queued_2": "{{ count }} note in coda per l'indicizzazione",
"notes_indexed_0": "{{ count }} nota indicizzata",
"notes_indexed_1": "{{ count }} note indicizzate",
"notes_indexed_2": "{{ count }} note indicizzate"
},
"import": {
"importIntoNote": "Importa nella nota",
"chooseImportFile": "Scegli file di importazione",
"importDescription": "Il contenuto dei file selezionati verranno importati come note secondarie in",
"options": "Opzioni",
"safeImportTooltip": "I file di esportazione Trilium <code>.zip</code> possono contenere script eseguibili che potrebbero avere comportamenti dannosi. L'importazione sicura disattiverà l'esecuzione automatica di tutti gli script importati. Deseleziona “Importazione sicura” solo se l'archivio importato dovrebbe contenere script eseguibili e ti fidi completamente del contenuto del file di importazione.",
"safeImport": "Importazione sicura",
"explodeArchivesTooltip": "Se questa opzione è selezionata, Trilium leggerà i file <code>.zip</code>, <code>.enex</code> e <code>.opml</code> e creerà delle note dai file contenuti in tali archivi. Se l'opzione non è selezionata, Trilium allegherà gli archivi stessi alla nota.",
"shrinkImages": "Riduci immagini",
"explodeArchives": "Leggi il contenuto degli archivi <code>.zip</code>, <code>.enex</code> e <code>.opml</code> .",
"html_import_tags": {
"title": "Tag di importazione HTML",
"description": "Configura quali tag HTML devono essere mantenuti durante l'importazione delle note. I tag che non sono presenti in questo elenco verranno rimossi durante l'importazione. Alcuni tag (come 'script') vengono sempre rimossi per motivi di sicurezza.",
"placeholder": "Inserisci i tag HTML, uno per riga",
"reset_button": "Ripristina elenco predefinito"
},
"import-status": "Stato importazione",
"in-progress": "Importazione in corso: {{progress}}",
"successful": "Importazione completata con successo.",
"shrinkImagesTooltip": "<p>Se selezioni questa opzione, Trilium tenterà di ridurre le immagini importate tramite ridimensionamento e ottimizzazione, il che potrebbe influire sulla qualità percepita dellimmagine. Se non selezionata, le immagini verranno importate senza modifiche.</p><p>Questo non si applica alle importazioni <code>.zip</code> con metadati, poiché si presume che questi file siano già ottimizzati.</p>",
"textImportedAsText": "Importa HTML, Markdown e TXT come note di testo se non è chiaro dai metadati",
"codeImportedAsCode": "Importa i file di codice riconosciuti (ad esempio <code>.json</code>) come note di codice se non è chiaro dai metadati",
"replaceUnderscoresWithSpaces": "Sostituisci i trattini bassi con spazi nei nomi delle note importate",
"import": "Importa",
"failed": "Importazione fallita: {{message}}."
},
"include_note": {
"dialog_title": "Includi nota",
"label_note": "Note",
"placeholder_search": "cerca una nota per nome",
"box_size_prompt": "Dimensione della casella della nota inclusa:",
"box_size_small": "piccola (~ 10 righe)",
"box_size_medium": "media (~ 30 righe)",
"box_size_full": "completa (la casella mostra il testo completo)",
"button_include": "Includi nota"
},
"jump_to_note": {
"search_placeholder": "Cerca una nota per nome oppure digita > per i comandi...",
"search_button": "Cerca nel testo completo"
},
"markdown_import": {
"dialog_title": "Importazione Markdown",
"modal_body_text": "A causa del sandbox del browser non è possibile leggere direttamente gli appunti tramite JavaScript. Incolla il Markdown da importare nell'area di testo sottostante e clicca sul pulsante Importa",
"import_button": "Importa",
"import_success": "Il contenuto Markdown è stato importato nel documento."
},
"move_to": {
"target_parent_note": "Nota principale di destinazione",
"dialog_title": "Sposta note in ...",
"notes_to_move": "Note da spostare",
"search_placeholder": "cerca una nota per nome",
"move_button": "Sposta nella nota selezionata",
"error_no_path": "Nessun percorso in cui spostarsi.",
"move_success_message": "Le note selezionate sono state spostate in "
},
"note_type_chooser": {
"change_path_prompt": "Cambia dove creare la nuova nota:",
"search_placeholder": "cerca percorso per nome (predefinito se vuoto)",
"modal_title": "Scegli il tipo di nota",
"modal_body": "Scegli il tipo / modello della nuova nota:",
"templates": "Modelli",
"builtin_templates": "Modelli incorporati"
},
"prompt": {
"title": "Richiesta",
"ok": "OK",
"defaultTitle": "Richiesta"
},
"recent_changes": {
"title": "Modifiche recenti",
"erase_notes_button": "Cancella ora le note eliminate",
"deleted_notes_message": "Le note eliminate sono state cancellate.",
"no_changes_message": "Nessuna modifica ancora...",
"undelete_link": "ripristinare",
"confirm_undelete": "Vuoi ripristinare questa nota e le sue sotto-note?"
},
"revisions": {
"note_revisions": "Note Revisioni",
"delete_all_revisions": "Elimina tutte le revisioni di questa nota",
"delete_all_button": "Elimina tutte le revisioni",
"help_title": "Aiuto sulle revisioni delle note",
"revision_last_edited": "Questa revisione è stata modificata l'ultima volta il {{date}}",
"confirm_delete_all": "Vuoi eliminare tutte le revisioni di questa nota?",
"no_revisions": "Ancora nessuna revisione per questa nota...",
"restore_button": "Ripristina",
"diff_on": "Mostra differenze",
"diff_off": "Mostra contenuto",
"diff_on_hint": "Clicca per mostrare la fonte della nota diff",
"diff_off_hint": "Clicca per visualizzare il contenuto della nota",
"diff_not_available": "Diff non è disponibile.",
"confirm_restore": "Vuoi ripristinare questa revisione? Questo sovrascriverà il titolo e il contenuto attuali della nota con questa revisione.",
"delete_button": "Elimina",
"confirm_delete": "Vuoi eliminare questa revisione?",
"revisions_deleted": "Le revisioni delle note sono state eliminate.",
"revision_restored": "La revisione della nota è stata ripristinata.",
"revision_deleted": "La revisione della nota è stata eliminata.",
"snapshot_interval": "Nota Intervallo di revisione istantanea: {{seconds}}.",
"maximum_revisions": "Nota Limite istantaneo di revisione: {{number}}.",
"settings": "Nota Impostazioni di revisione",
"download_button": "Scarica",
"mime": "MIME: ",
"file_size": "Dimensione del file:",
"preview": "Anteprima:",
"preview_not_available": "L'anteprima non è disponibile per questo tipo di nota."
},
"sort_child_notes": {
"sort_children_by": "Ordina i bambini per...",
"sorting_criteria": "Criteri di ordinamento",
"title": "titolo",
"date_created": "data di creazione",
"date_modified": "data di modifica",
"sorting_direction": "Direzione",
"ascending": "ascendente",
"descending": "discendente",
"folders": "Cartelle",
"sort_folders_at_top": "ordina le cartelle in alto",
"natural_sort": "Ordinamento naturale",
"sort_with_respect_to_different_character_sorting": "ordinare in base alle diverse regole di ordinamento e collazione dei caratteri nelle diverse lingue o regioni.",
"natural_sort_language": "Linguaggio di ordinamento naturale",
"the_language_code_for_natural_sort": "Il codice lingua per l'ordinamento naturale, ad esempio \"zh-CN\" per il cinese.",
"sort": "Ordina"
},
"upload_attachments": {
"upload_attachments_to_note": "Carica allegati alla nota",
"choose_files": "Scegli i file",
"files_will_be_uploaded": "I file saranno caricati come allegati in {{noteTitle}}",
"options": "Opzioni",
"shrink_images": "Riduci immagini",
"upload": "Carica",
"tooltip": "Se selezioni questa opzione, Trilium tenterà di ridurre le immagini caricate tramite ridimensionamento e ottimizzazione, il che potrebbe influire sulla qualità percepita delle immagini. Se non selezionata, le immagini verranno caricate senza modifiche."
},
"attribute_detail": {
"attr_detail_title": "Titolo dettagli attributo",
"close_button_title": "Annulla modifiche e chiudi",
"attr_is_owned_by": "L'attributo è di proprietà di",
"attr_name_title": "Il nome dell'attributo può essere composto solo da caratteri alfanumerici, due punti e trattino basso",
"name": "Nome",
"app_theme_base": "impostare su \"next\", \"next-light\" o \"next-dark\" per utilizzare il tema TriliumNext corrispondente (automatico, chiaro o scuro) come base per un tema personalizzato, invece di quello precedente.",
"css_class": "Il valore di questa etichetta viene quindi aggiunto come classe CSS al nodo che rappresenta una determinata nota nell'albero. Ciò può essere utile per la personalizzazione avanzata dei temi. Può essere utilizzato nelle note dei modelli.",
"icon_class": "Il valore di questa etichetta viene aggiunto come classe CSS all'icona sull'albero, il che può aiutare a distinguere visivamente le note nell'albero. Un esempio potrebbe essere bx bx-home - le icone sono prese da boxicons. Può essere utilizzato nelle note del modello.",
"page_size": "numero di elementi per pagina nell'elenco delle note",
"custom_request_handler": "vedi <a href=\"javascript:\" data-help-page=\"custom-request-handler.html\">Gestore richieste personalizzato</a>",
"custom_resource_provider": "vedi <a href=\"javascript:\" data-help-page=\"custom-request-handler.html\">Gestore richieste personalizzato</a>",
"widget": "contrassegna questa nota come widget personalizzato che verrà aggiunto all'albero dei componenti Trilium",
"workspace": "contrassegna questa nota come area di lavoro che consente un facile ancoraggio",
"workspace_icon_class": "definisce la classe CSS dell'icona della casella che verrà utilizzata nella scheda quando viene sollevata su questa nota",
"workspace_tab_background_color": "Colore CSS utilizzato nella scheda delle note quando viene sollevato su questa nota",
"workspace_calendar_root": "Definisce la radice del calendario per ogni area di lavoro",
"workspace_template": "Questa nota apparirà nella selezione dei modelli disponibili quando si crea una nuova nota, ma solo se inserita in un'area di lavoro che contiene questo modello",
"search_home": "verranno create nuove note di ricerca come sottovoci di questa nota",
"value": "Valore",
"target_note_title": "La relazione è una connessione denominata tra la nota di origine e la nota di destinazione.",
"target_note": "Nota obiettivo",
"promoted_title": "L'attributo promosso viene visualizzato in modo ben visibile sulla nota.",
"promoted": "Promosso",
"promoted_alias_title": "Il nome da visualizzare nell'interfaccia utente degli attributi promossi.",
"promoted_alias": "Alias",
"multiplicity_title": "La molteplicità definisce quanti attributi con lo stesso nome possono essere creati: al massimo 1 o più di 1.",
"multiplicity": "Molteplicità",
"single_value": "Valore singolo",
"multi_value": "Valore multiplo",
"label_type_title": "Il tipo di etichetta aiuterà Trilium a scegliere l'interfaccia adatta per inserire il valore dell'etichetta.",
"label_type": "Tipo",
"text": "Testo",
"number": "Numero",
"boolean": "Booleano",
"date": "Data",
"date_time": "Data e Ora",
"time": "Ora",
"url": "URL",
"precision_title": "Quante cifre dopo la virgola mobile dovrebbero essere disponibili nell'interfaccia di impostazione del valore.",
"precision": "Precisione",
"digits": "cifre",
"inverse_relation_title": "Impostazione facoltativa per definire a quale relazione è opposta questa. Esempio: padre e figlio sono relazioni inverse l'una rispetto all'altra.",
"inheritable": "Ereditabile",
"inverse_relation": "Relazione inversa",
"inheritable_title": "L'attributo ereditario verrà ereditato da tutti i discendenti sotto questo albero.",
"save_and_close": "Salva e chiudi <kbd>Ctrl+Enter</kbd>",
"delete": "Eliminazione",
"related_notes_title": "Altre note con questa etichetta",
"more_notes": "Altre note",
"label": "Dettagli etichetta",
"label_definition": "Dettagli definizione etichetta",
"relation": "Dettagli relazione",
"relation_definition": "Dettagli definizione relazione",
"disable_versioning": "disabilita il versioning automatico. Utile ad esempio per note di grandi dimensioni ma non importanti, come le grandi librerie JS utilizzate per lo scripting",
"calendar_root": "segna le note che devono essere utilizzate come note principali per le note giornaliere. Solo una deve essere contrassegnata come tale.",
"archived": "Le note con questa etichetta non saranno visibili per impostazione predefinita nei risultati di ricerca (anche nelle finestre di dialogo Vai a, Aggiungi collegamento ecc.).",
"run_on_instance": "Definire su quale istanza di Trilium eseguire questa operazione. L'impostazione predefinita è tutte le istanze.",
"exclude_from_export": "le note (con la loro sottostruttura) non saranno incluse in nessuna esportazione di note",
"run": "definisce su quali eventi deve essere eseguito lo script. I valori possibili sono:\n<ul>\n<li>frontendStartup - quando il frontend Trilium viene avviato (o aggiornato), ma non su dispositivi mobili.</li>\n<li>mobileStartup - quando il frontend Trilium viene avviato (o aggiornato) su dispositivi mobili.</li>\n<li>backendStartup - quando viene avviato il backend Trilium</li>\n<li>hourly - eseguire una volta all'ora. È possibile utilizzare l'etichetta aggiuntiva <code>runAtHour</code> per specificare a che ora.</li>\n<li>daily - eseguire una volta al giorno</li>\n</ul>",
"run_at_hour": "A che ora deve essere eseguito. Deve essere utilizzato insieme a <code>#run=hourly</code>. Può essere definito più volte per più esecuzioni durante il giorno.",
"disable_inclusion": "gli script con questa etichetta non saranno inclusi nell'esecuzione dello script principale.",
"sorted": "mantiene le note figlie ordinate alfabeticamente per titolo",
"sort_direction": "ASC (impostazione predefinita) o DESC",
"sort_folders_first": "Le cartelle (note con figlie) devono essere ordinate in cima",
"top": "mantieni la nota in cima al suo genitore (si applica solo ai genitori ordinati)",
"hide_promoted_attributes": "Nascondi gli attributi promossi in questa nota",
"read_only": "L'editor è in modalità di sola lettura. Funziona solo per note di testo e codice.",
"auto_read_only_disabled": "Le note di testo/codice possono essere impostate automaticamente in modalità di lettura quando sono troppo grandi. È possibile disabilitare questo comportamento per ogni singola nota aggiungendo questa etichetta alla nota",
"app_css": "contrassegna le note CSS che vengono caricate nell'applicazione Trilium e possono quindi essere utilizzate per modificare l'aspetto di Trilium.",
"app_theme": "contrassegna le note CSS che sono temi Trilium completi e sono quindi disponibili nelle opzioni Trilium.",
"workspace_search_home": "nuove note di ricerca verranno create come figlie di questa nota quando sollevate a qualche antenato di questa nota dell'area di lavoro",
"inbox": "Posizione predefinita della casella di posta in arrivo per le nuove note: quando crei una nota utilizzando il pulsante \"Nuova nota\" nella barra laterale, le note verranno create come note secondarie nella nota contrassegnata con l'etichetta <code>#inbox</code>.",
"workspace_inbox": "posizione predefinita della casella di posta in arrivo per le nuove note quando vengono trasferite a un antenato di questa nota dell'area di lavoro",
"sql_console_home": "posizione predefinita delle note della console SQL",
"bookmark_folder": "le note con questa etichetta appariranno nei segnalibri come cartelle (consentendo l'accesso ai loro elementi secondari)",
"share_hidden_from_tree": "questa nota è nascosta dall'albero di navigazione a sinistra, ma è comunque accessibile tramite il suo URL",
"share_external_link": "La nota fungerà da collegamento a un sito web esterno nell'albero di condivisione",
"share_alias": "definisci un alias con cui la nota sarà disponibile all'indirizzo https://your_trilium_host/share/[your_alias]",
"share_omit_default_css": "Il CSS predefinito della pagina di condivisione verrà omesso. Utilizzarlo quando si apportano modifiche stilistiche significative.",
"keep_current_hoisting": "L'apertura di questo link non modificherà l'ancoraggio anche se la nota non è visualizzabile nell'attuale sottoalbero ancorato.",
"share_description": "definire il testo da aggiungere al meta tag HTML per la descrizione",
"share_raw": "La nota verrà visualizzata nel suo formato originale, senza wrapper HTML",
"share_disallow_robot_indexing": "impedirà l'indicizzazione robotica di questa nota tramite l'intestazione <code>X-Robots-Tag: noindex</code>",
"share_credentials": "richiedono credenziali per accedere a questa nota condivisa. Il valore deve essere nel formato 'username:password'. Non dimenticare di renderlo ereditabile affinché si applichi alle note/immagini secondarie.",
"share_index": "La nota con questa etichetta elencherà tutte le radici delle note condivise",
"display_relations": "nomi delle relazioni delimitati da virgola che devono essere visualizzati. Tutti gli altri saranno nascosti.",
"hide_relations": "nomi delle relazioni delimitati da virgola che devono essere nascosti. Tutti gli altri saranno visualizzati.",
"title_template": "titolo predefinito delle note create come figlie di questa nota. Il valore viene valutato come stringa JavaScript. \n e quindi può essere arricchito con contenuti dinamici tramite le variabili <code>now</code> e <code>parentNote</code> inserite. Esempi:\n \n <ul>\n <li><code>${parentNote.getLabelValue('authorName')}'s opere letterarie</code></li>\n <li><code>Log per ${now.format('YYYY-MM-DD HH:mm:ss')}</code></li>\n </ul>\n \n Per ulteriori dettagli, consultare <a href=\"https://triliumnext.github.io/Docs/Wiki/default-note-title.html\">wiki con i dettagli</a>, la documentazione API per <a href=\"https://zadam.github.io/trilium/backend_api/Note.html\">parentNote</a> e <a href=\"https://day.js.org/docs/en/display/format\">now</a>.",
"template": "Questa nota apparirà nella selezione dei modelli disponibili durante la creazione di una nuova nota",
"toc": "<code>#toc</code> o <code>#toc=show</code> forzeranno la visualizzazione del sommario, mentre <code>#toc=hide</code> ne forzerà la non visualizzazione. Se l'etichetta non esiste, verrà applicata l'impostazione globale",
"color": "definisce il colore della nota nell'albero delle note, nei link ecc. Utilizza qualsiasi valore di colore CSS valido come \"red\" o #a13d5f",
"keyboard_shortcut": "Definisce una scorciatoia da tastiera che consentirà di passare immediatamente a questa nota. Esempio: \"ctrl+alt+e\". Per rendere effettiva la modifica è necessario ricaricare il frontend.",
"execute_button": "Titolo del pulsante che eseguirà il codice della nota corrente",
"execute_description": "Descrizione più dettagliata della nota di codice corrente visualizzata insieme al pulsante di esecuzione",
"exclude_from_note_map": "Le note con questa etichetta saranno nascoste dalla mappa delle note",
"new_notes_on_top": "Le nuove note verranno create nella parte superiore della nota principale, non nella parte inferiore.",
"hide_highlight_widget": "Nascondi widget Elenco evidenziazioni",
"run_on_note_creation": "Viene eseguito quando viene creata una nota sul backend. Utilizza questa relazione se desideri eseguire lo script per tutte le note create in una sottostruttura specifica. In tal caso, crealo sulla nota radice della sottostruttura e rendilo ereditabile. Una nuova nota creata all'interno della sottostruttura (a qualsiasi profondità) attiverà lo script.",
"run_on_child_note_creation": "viene eseguito quando viene creata una nuova nota sotto la nota in cui è definita questa relazione",
"run_on_note_title_change": "viene eseguito quando viene modificato il titolo della nota (include anche la creazione della nota)",
"run_on_note_content_change": "Viene eseguito quando il contenuto della nota viene modificato (compresa la creazione della nota).",
"run_on_note_change": "Viene eseguito quando la nota viene modificata (compresa la creazione della nota). Non include le modifiche al contenuto",
"run_on_note_deletion": "viene eseguito quando la nota viene eliminata",
"run_on_branch_creation": "Viene eseguito quando viene creato un ramo. Il ramo è un collegamento tra la nota principale e la nota secondaria e viene creato, ad esempio, quando si clona o si sposta una nota.",
"run_on_branch_change": "viene eseguito quando un ramo viene aggiornato.",
"run_on_branch_deletion": "Viene eseguito quando viene eliminato un ramo. Il ramo è un collegamento tra una nota padre e una nota figlio e viene eliminato, ad esempio, quando si sposta una nota (il vecchio ramo/collegamento viene eliminato).",
"run_on_attribute_creation": "viene eseguito quando viene creato un nuovo attributo per la nota che definisce questa relazione",
"run_on_attribute_change": " viene eseguito quando viene modificato l'attributo di una nota che definisce questa relazione. Viene attivato anche quando l'attributo viene eliminato",
"relation_template": "Gli attributi della nota saranno ereditati anche senza una relazione padre-figlio, mentre il contenuto e la sottostruttura della nota saranno aggiunti alle note dell'istanza se vuote. Per ulteriori dettagli, consultare la documentazione.",
"inherit": "Gli attributi della nota saranno ereditati anche senza una relazione padre-figlio. Vedi relazione modello per un concetto simile. Vedi eredità degli attributi nella documentazione.",
"render_note": "le note di tipo \"renderizza nota HTML\" saranno renderizzate utilizzando una nota codice (HTML o script) ed è necessario indicare utilizzando questa relazione quale nota deve essere renderizzata",
"widget_relation": "L'obiettivo di questa relazione verrà eseguito e visualizzato come widget nella barra laterale",
"share_css": "Nota CSS che verrà inserita nella pagina condivisa. Anche la nota CSS deve trovarsi nella sottostruttura condivisa. Valuta anche l'utilizzo di 'share_hidden_from_tree' e 'share_omit_default_css'.",
"share_js": "Nota JavaScript che verrà inserita nella pagina di condivisione. Anche la nota JS deve trovarsi nella sottostruttura condivisa. Valuta l'utilizzo di 'share_hidden_from_tree'.",
"share_template": "Nota JavaScript incorporata che verrà utilizzata come modello per la visualizzazione della nota condivisa. Se non disponibile, verrà utilizzato il modello predefinito. Si consiglia di utilizzare 'share_hidden_from_tree'.",
"share_favicon": "Nota Favicon da impostare nella pagina condivisa. In genere è preferibile impostarla su \"condivisione radice\" e renderla ereditabile. Anche la nota Favicon deve trovarsi nella sottostruttura condivisa. Valutare l'utilizzo di 'share_hidden_from_tree'.",
"is_owned_by_note": "è di proprietà di nota",
"other_notes_with_name": "Altre note con {{attributeType}} nome \"{{attributeName}}\"",
"and_more": "... e altri {{count}}.",
"print_landscape": "Quando si esporta in PDF, cambia l'orientamento della pagina da verticale a orizzontale.",
"print_page_size": "Quando si esporta in PDF, modifica le dimensioni della pagina. Valori supportati: <code>A0</code>, <code>A1</code>, <code>A2</code>, <code>A3</code>, <code>A4</code>, <code>A5</code>, <code>A6</code>, <code>Legal</code>, <code>Letter</code>, <code>Tabloid</code>, <code>Ledger</code>.",
"color_type": "Colore",
"share_root": "segna la nota che viene servita su /share root."
},
"attribute_editor": {
"help_text_body1": "Per aggiungere un'etichetta, basta digitare ad esempio <code>#rock</code> oppure, se si desidera aggiungere anche un valore, ad esempio <code>#year = 2020</code>",
"help_text_body2": "Per la relazione, digita <code>~author = @</code>, che dovrebbe far apparire un completamento automatico in cui puoi cercare la nota desiderata.",
"help_text_body3": "In alternativa, è possibile aggiungere etichette e relazioni utilizzando il pulsante <code>+</code> sul lato destro.",
"save_attributes": "Salva attributi <enter>",
"add_a_new_attribute": "Aggiungi un nuovo attributo",
"add_new_label": "Aggiungi nuova etichetta <kbd data-command=\"addNewLabel\"></kbd>",
"add_new_relation": "Aggiungi nuova relazione <kbd data-command=\"addNewRelation\"></kbd>",
"add_new_relation_definition": "Aggiungi una nuova definizione di relazione",
"placeholder": "Digitare qui le etichette e le relazioni"
},
"execute_script": {
"execute_script": "Esegui script",
"help_text": "È possibile eseguire semplici script sulle note abbinate.",
"example_1": "Ad esempio, per aggiungere una stringa al titolo di una nota, utilizzare questo piccolo script:"
"showJumpToNoteDialog": "mostra <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/note-navigation.html#jump-to-note\">la finestra di dialogo \"Salta alla nota\"<a>"
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -15,45 +15,15 @@
"message": "클라이언트 애플리케이션 시작 도중 심각한 오류가 발생했습니다:\n\n{{message}}\n\n이는 스크립트가 예기치 않게 실패하면서 발생한 것일 수 있습니다. 애플리케이션을 안전 모드로 시작한 뒤 문제를 해결해 보세요."
},
"widget-error": {
"title": "위젯 초기화 실패",
"message-custom": "ID가 \"{{id}}\"고 ,제목이 \"{{title}}\" 인 노트에서 사용자 지정 위젯을 초기화 하는데 실패했습니다:\n\n{{message}}",
"message-unknown": "알 수 없는 위젯이 초기화 하는데 실패했습니다:\n\n{{message}}"
},
"bundle-error": {
"title": "사용자 정의 스크립트를 불러오는데 실패했습니다",
"message": "ID가 \"{{id}}\"고, 제목이 \"{{title}}\"인 노트에서 스크립트가 실행되지 못했습니다:\n\n{{message}}"
"title": "위젯 초기화 실패"
}
},
"add_link": {
"add_link": "링크 추가",
"note": "노트",
"search_note": "이름으로 노트 검색하기",
"help_on_links": "링크 관련 도움말",
"link_title_mirrors": "링크 제목은 노트의 현재 제목을 반영합니다",
"link_title_arbitrary": "링크 제목은 임의로 변경될 수 있습니다",
"link_title": "링크 제목",
"button_add_link": "링크 추가"
"search_note": "이름으로 노트 검색하기"
},
"branch_prefix": {
"save": "저장",
"edit_branch_prefix": "브랜치 접두사 편집",
"help_on_tree_prefix": "트리 접두사에 대한 도움말",
"prefix": "접두사: ",
"branch_prefix_saved": "브랜치 접두사가 저장되었습니다."
},
"bulk_actions": {
"bulk_actions": "대량 작업",
"affected_notes": "영향을 받은 노트들",
"include_descendants": "선택한 노트의 자손 포함",
"available_actions": "가능한 액션들",
"chosen_actions": "선택한 액션들",
"execute_bulk_actions": "대량 액션들 실행",
"bulk_actions_executed": "대량 액션들이 성공적으로 실행되었습니다."
},
"i18n": {
"saturday": "토요일",
"sunday": "일요일",
"first-week-of-the-year": "일년의 첫째 주",
"first-week-contains-first-day": "첫 번째 주에는 올해의 첫날이 포함됩니다"
"save": "저장"
}
}

View File

@@ -1 +0,0 @@
{}

Some files were not shown because too many files have changed in this diff Show More