mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 10:26:08 +01:00 
			
		
		
		
	Merge branch 'develop' into feature/MFA
This commit is contained in:
		| @@ -34,6 +34,7 @@ npm-debug.log | |||||||
|  |  | ||||||
| # exceptions | # exceptions | ||||||
| !/bin/copy-dist.ts | !/bin/copy-dist.ts | ||||||
|  | !/bin/electron-forge/sign-windows.cjs | ||||||
|  |  | ||||||
| # temporary exception to make copy-dist inside Docker build not fail | # temporary exception to make copy-dist inside Docker build not fail | ||||||
| # TriliumNextTODO: make copy-dist *not* requiring to copy this file for builds other than electron-forge | # TriliumNextTODO: make copy-dist *not* requiring to copy this file for builds other than electron-forge | ||||||
|   | |||||||
							
								
								
									
										82
									
								
								.github/actions/build-electron/action.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										82
									
								
								.github/actions/build-electron/action.yml
									
									
									
									
										vendored
									
									
								
							| @@ -8,8 +8,11 @@ inputs: | |||||||
|   arch: |   arch: | ||||||
|     description: "The architecture to build for: x64, arm64" |     description: "The architecture to build for: x64, arm64" | ||||||
|     required: true |     required: true | ||||||
|   extension: |   shell: | ||||||
|     description: "Platform specific extensions to copy in the output: dmg, deb, rpm, exe, zip" |     description: "Which shell to use" | ||||||
|  |     required: true | ||||||
|  |   forge_platform: | ||||||
|  |     description: "The --platform to pass to Electron Forge" | ||||||
|     required: true |     required: true | ||||||
|  |  | ||||||
| runs: | runs: | ||||||
| @@ -38,21 +41,21 @@ runs: | |||||||
|  |  | ||||||
|     - name: Verify certificates |     - name: Verify certificates | ||||||
|       if: inputs.os == 'macos' |       if: inputs.os == 'macos' | ||||||
|       shell: bash |       shell: ${{ inputs.shell }} | ||||||
|       run: | |       run: | | ||||||
|         echo "Available signing identities:" |         echo "Available signing identities:" | ||||||
|         security find-identity -v -p codesigning build.keychain |         security find-identity -v -p codesigning build.keychain | ||||||
|  |  | ||||||
|     - name: Set up Python and other macOS dependencies |     - name: Set up Python and other macOS dependencies | ||||||
|       if: ${{ inputs.os == 'macos' }} |       if: ${{ inputs.os == 'macos' }} | ||||||
|       shell: bash |       shell: ${{ inputs.shell }} | ||||||
|       run: | |       run: | | ||||||
|         brew install python-setuptools |         brew install python-setuptools | ||||||
|         brew install create-dmg |         brew install create-dmg | ||||||
|  |  | ||||||
|     - name: Install dependencies for RPM and Flatpak package building |     - name: Install dependencies for RPM and Flatpak package building | ||||||
|       if: ${{ inputs.os == 'linux' }} |       if: ${{ inputs.os == 'linux' }} | ||||||
|       shell: bash |       shell: ${{ inputs.shell }} | ||||||
|       run: | |       run: | | ||||||
|         sudo apt-get update && sudo apt-get install rpm flatpak-builder elfutils |         sudo apt-get update && sudo apt-get install rpm flatpak-builder elfutils | ||||||
|         flatpak remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo |         flatpak remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo | ||||||
| @@ -62,39 +65,32 @@ runs: | |||||||
|  |  | ||||||
|     # Build setup |     # Build setup | ||||||
|     - name: Install dependencies |     - name: Install dependencies | ||||||
|       shell: bash |       shell: ${{ inputs.shell }} | ||||||
|       run: npm ci |       run: npm ci | ||||||
|  |  | ||||||
|     - name: Update build info |     - name: Update build info | ||||||
|       shell: bash |       shell: ${{ inputs.shell }} | ||||||
|       run: npm run chore:update-build-info |       run: npm run chore:update-build-info | ||||||
|  |  | ||||||
|     # Critical debugging configuration |     # Critical debugging configuration | ||||||
|     - name: Run electron-forge build with enhanced logging |     - name: Run electron-forge build with enhanced logging | ||||||
|       shell: bash |       shell: ${{ inputs.shell }} | ||||||
|       env: |       env: | ||||||
|         # Pass through required environment variables for signing and notarization |         # Pass through required environment variables for signing and notarization | ||||||
|         APPLE_TEAM_ID: ${{ env.APPLE_TEAM_ID }} |         APPLE_TEAM_ID: ${{ env.APPLE_TEAM_ID }} | ||||||
|         APPLE_ID: ${{ env.APPLE_ID }} |         APPLE_ID: ${{ env.APPLE_ID }} | ||||||
|         APPLE_ID_PASSWORD: ${{ env.APPLE_ID_PASSWORD }} |         APPLE_ID_PASSWORD: ${{ env.APPLE_ID_PASSWORD }} | ||||||
|  |         WINDOWS_SIGN_EXECUTABLE: ${{ env.WINDOWS_SIGN_EXECUTABLE }} | ||||||
|  |         TRILIUM_ARTIFACT_NAME_HINT: TriliumNextNotes ${{ inputs.os }} ${{ inputs.arch }} | ||||||
|       run: | |       run: | | ||||||
|         # Map OS names to Electron Forge platform names |  | ||||||
|         if [ "${{ inputs.os }}" = "macos" ]; then |  | ||||||
|           PLATFORM="darwin" |  | ||||||
|         elif [ "${{ inputs.os }}" = "windows" ]; then |  | ||||||
|           PLATFORM="win32" |  | ||||||
|         else |  | ||||||
|           PLATFORM="${{ inputs.os }}" |  | ||||||
|         fi |  | ||||||
|  |  | ||||||
|         npm run electron-forge:make -- \ |         npm run electron-forge:make -- \ | ||||||
|           --arch=${{ inputs.arch }} \ |           --arch=${{ inputs.arch }} \ | ||||||
|           --platform=$PLATFORM |           --platform=${{ inputs.forge_platform }} | ||||||
|  |  | ||||||
|     # Add DMG signing step |     # Add DMG signing step | ||||||
|     - name: Sign DMG |     - name: Sign DMG | ||||||
|       if: inputs.os == 'macos' |       if: inputs.os == 'macos' | ||||||
|       shell: bash |       shell: ${{ inputs.shell }} | ||||||
|       run: | |       run: | | ||||||
|         echo "Signing DMG file..." |         echo "Signing DMG file..." | ||||||
|         dmg_file=$(find ./dist -name "*.dmg" -print -quit) |         dmg_file=$(find ./dist -name "*.dmg" -print -quit) | ||||||
| @@ -119,7 +115,7 @@ runs: | |||||||
|  |  | ||||||
|     - name: Verify code signing |     - name: Verify code signing | ||||||
|       if: inputs.os == 'macos' |       if: inputs.os == 'macos' | ||||||
|       shell: bash |       shell: ${{ inputs.shell }} | ||||||
|       run: | |       run: | | ||||||
|         echo "Verifying code signing for all artifacts..." |         echo "Verifying code signing for all artifacts..." | ||||||
|  |  | ||||||
| @@ -165,49 +161,3 @@ runs: | |||||||
|           echo "Found ZIP: $zip_file" |           echo "Found ZIP: $zip_file" | ||||||
|           echo "Note: ZIP files are not code signed, but their contents should be" |           echo "Note: ZIP files are not code signed, but their contents should be" | ||||||
|         fi |         fi | ||||||
|  |  | ||||||
|     - name: Prepare artifacts |  | ||||||
|       shell: bash |  | ||||||
|       run: | |  | ||||||
|         mkdir -p upload |  | ||||||
|  |  | ||||||
|         if [ "${{ inputs.os }}" = "macos" ]; then |  | ||||||
|           # For macOS, we need to look in specific directories based on the maker |  | ||||||
|           echo "Collecting macOS artifacts..." |  | ||||||
|  |  | ||||||
|           # Look for DMG files recursively |  | ||||||
|           echo "Looking for DMG files..." |  | ||||||
|           dmg_file=$(find ./dist -name "*.dmg" -print -quit) |  | ||||||
|           if [ -n "$dmg_file" ]; then |  | ||||||
|             echo "Found DMG: $dmg_file" |  | ||||||
|             cp "$dmg_file" "upload/TriliumNextNotes-${{ github.ref_name }}-macos-${{ inputs.arch }}.dmg" |  | ||||||
|           else |  | ||||||
|             echo "Warning: No DMG file found" |  | ||||||
|           fi |  | ||||||
|  |  | ||||||
|           # Look for ZIP files recursively |  | ||||||
|           echo "Looking for ZIP files..." |  | ||||||
|           zip_file=$(find ./dist -name "*.zip" -print -quit) |  | ||||||
|           if [ -n "$zip_file" ]; then |  | ||||||
|             echo "Found ZIP: $zip_file" |  | ||||||
|             cp "$zip_file" "upload/TriliumNextNotes-${{ github.ref_name }}-macos-${{ inputs.arch }}.zip" |  | ||||||
|           else |  | ||||||
|             echo "Warning: No ZIP file found" |  | ||||||
|           fi |  | ||||||
|         else |  | ||||||
|           # For other platforms, use the existing logic but with better error handling |  | ||||||
|           echo "Collecting artifacts for ${{ inputs.os }}..." |  | ||||||
|           for ext in ${{ inputs.extension }}; do |  | ||||||
|             echo "Looking for .$ext files..." |  | ||||||
|             file=$(find ./dist -name "*.$ext" -print -quit) |  | ||||||
|             if [ -n "$file" ]; then |  | ||||||
|               echo "Found $file for extension $ext" |  | ||||||
|               cp "$file" "upload/TriliumNextNotes-${{ github.ref_name }}-${{ inputs.os }}-${{ inputs.arch }}.$ext" |  | ||||||
|             else |  | ||||||
|               echo "Warning: No file found with extension .$ext" |  | ||||||
|             fi |  | ||||||
|           done |  | ||||||
|         fi |  | ||||||
|  |  | ||||||
|         echo "Final contents of upload directory:" |  | ||||||
|         ls -la upload/ |  | ||||||
|   | |||||||
							
								
								
									
										93
									
								
								.github/workflows/main.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										93
									
								
								.github/workflows/main.yml
									
									
									
									
										vendored
									
									
								
							| @@ -1,93 +0,0 @@ | |||||||
| name: Main |  | ||||||
| on: |  | ||||||
|   push: |  | ||||||
|     branches: |  | ||||||
|       - "feature/update**" |  | ||||||
|       - "feature/server_esm**" |  | ||||||
|     paths-ignore: |  | ||||||
|       - "docs/**" |  | ||||||
|       - ".github/workflows/main-docker.yml" |  | ||||||
|   workflow_dispatch: |  | ||||||
|  |  | ||||||
| concurrency: |  | ||||||
|   group: ${{ github.workflow }}-${{ github.ref }} |  | ||||||
|   cancel-in-progress: true |  | ||||||
|  |  | ||||||
| jobs: |  | ||||||
|   make-electron: |  | ||||||
|     name: Make Electron |  | ||||||
|     strategy: |  | ||||||
|       fail-fast: false |  | ||||||
|       matrix: |  | ||||||
|         arch: [x64, arm64] |  | ||||||
|         os: |  | ||||||
|           - name: macos |  | ||||||
|             image: macos-latest |  | ||||||
|             extension: [dmg, zip] |  | ||||||
|           - name: linux |  | ||||||
|             image: ubuntu-latest |  | ||||||
|             extension: [deb, rpm, zip, flatpak] |  | ||||||
|           - name: windows |  | ||||||
|             image: windows-latest |  | ||||||
|             extension: [exe, zip] |  | ||||||
|     runs-on: ${{ matrix.os.image }} |  | ||||||
|     steps: |  | ||||||
|       - uses: actions/checkout@v4 |  | ||||||
|       - name: Set up node & dependencies |  | ||||||
|         uses: actions/setup-node@v4 |  | ||||||
|         with: |  | ||||||
|           node-version: 20 |  | ||||||
|       - name: Run the build |  | ||||||
|         uses: ./.github/actions/build-electron |  | ||||||
|         with: |  | ||||||
|           os: ${{ matrix.os.name }} |  | ||||||
|           arch: ${{ matrix.arch }} |  | ||||||
|           extension: ${{ matrix.os.extension }} |  | ||||||
|         env: |  | ||||||
|           APPLE_APP_CERTIFICATE_BASE64: ${{ secrets.APPLE_APP_CERTIFICATE_BASE64 }} |  | ||||||
|           APPLE_APP_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_APP_CERTIFICATE_PASSWORD }} |  | ||||||
|           APPLE_INSTALLER_CERTIFICATE_BASE64: ${{ secrets.APPLE_INSTALLER_CERTIFICATE_BASE64 }} |  | ||||||
|           APPLE_INSTALLER_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_INSTALLER_CERTIFICATE_PASSWORD }} |  | ||||||
|           APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} |  | ||||||
|           APPLE_ID: ${{ secrets.APPLE_ID }} |  | ||||||
|           APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} |  | ||||||
|  |  | ||||||
|       # Clean up keychain after build |  | ||||||
|       - name: Clean up keychain |  | ||||||
|         if: matrix.os.name == 'macos' && always() |  | ||||||
|         run: | |  | ||||||
|           security delete-keychain build.keychain |  | ||||||
|  |  | ||||||
|       - name: Publish artifacts |  | ||||||
|         uses: actions/upload-artifact@v4 |  | ||||||
|         with: |  | ||||||
|           name: TriliumNextNotes ${{ matrix.os.name }} ${{ matrix.arch }}.zip |  | ||||||
|           path: upload/*.zip |  | ||||||
|       - name: Publish installer artifacts |  | ||||||
|         uses: actions/upload-artifact@v4 |  | ||||||
|         with: |  | ||||||
|           name: TriliumNextNotes ${{ matrix.os.name }} ${{ matrix.arch }}.${{matrix.os.extension}} |  | ||||||
|           path: upload/*.${{ matrix.os.extension }} |  | ||||||
|  |  | ||||||
|   build_linux_server: |  | ||||||
|     name: Build Linux Server |  | ||||||
|     strategy: |  | ||||||
|       fail-fast: false |  | ||||||
|       matrix: |  | ||||||
|         arch: [x64, arm64] |  | ||||||
|         include: |  | ||||||
|           - arch: x64 |  | ||||||
|             runs-on: ubuntu-latest |  | ||||||
|           - arch: arm64 |  | ||||||
|             runs-on: ubuntu-24.04-arm |  | ||||||
|     runs-on: ${{ matrix.runs-on }} |  | ||||||
|     steps: |  | ||||||
|       - uses: actions/checkout@v4 |  | ||||||
|       - name: Run the build |  | ||||||
|         uses: ./.github/actions/build-server |  | ||||||
|         with: |  | ||||||
|           arch: ${{ matrix.arch }} |  | ||||||
|       - uses: actions/upload-artifact@v4 |  | ||||||
|         with: |  | ||||||
|           name: TriliumNextNotes linux server ${{ matrix.arch }} |  | ||||||
|           path: upload/TriliumNextNotes-linux-${{ matrix.arch }}-${{ github.ref_name }}.tar.xz |  | ||||||
							
								
								
									
										55
									
								
								.github/workflows/nightly.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										55
									
								
								.github/workflows/nightly.yml
									
									
									
									
										vendored
									
									
								
							| @@ -5,6 +5,9 @@ on: | |||||||
|     - cron: "0 2 * * *" # run at 2 AM UTC |     - cron: "0 2 * * *" # run at 2 AM UTC | ||||||
|   # This can be used to allow manually triggering nightlies from the web interface |   # This can be used to allow manually triggering nightlies from the web interface | ||||||
|   workflow_dispatch: |   workflow_dispatch: | ||||||
|  |   pull_request: | ||||||
|  |     paths: | ||||||
|  |       - .github/actions/build-electron/* | ||||||
| env: | env: | ||||||
|   GITHUB_UPLOAD_URL: https://uploads.github.com/repos/TriliumNext/Notes/releases/179589950/assets{?name,label} |   GITHUB_UPLOAD_URL: https://uploads.github.com/repos/TriliumNext/Notes/releases/179589950/assets{?name,label} | ||||||
|   GITHUB_RELEASE_ID: 179589950 |   GITHUB_RELEASE_ID: 179589950 | ||||||
| @@ -20,13 +23,16 @@ jobs: | |||||||
|         os: |         os: | ||||||
|           - name: macos |           - name: macos | ||||||
|             image: macos-latest |             image: macos-latest | ||||||
|             extension: [dmg, zip] |             shell: bash | ||||||
|  |             forge_platform: darwin | ||||||
|           - name: linux |           - name: linux | ||||||
|             image: ubuntu-latest |             image: ubuntu-latest | ||||||
|             extension: [deb, rpm, zip, flatpak] |             shell: bash | ||||||
|  |             forge_platform: linux | ||||||
|           - name: windows |           - name: windows | ||||||
|             image: windows-latest |             image: win-signing | ||||||
|             extension: [exe, zip] |             shell: cmd | ||||||
|  |             forge_platform: win32 | ||||||
|     runs-on: ${{ matrix.os.image }} |     runs-on: ${{ matrix.os.image }} | ||||||
|     steps: |     steps: | ||||||
|       - uses: actions/checkout@v4 |       - uses: actions/checkout@v4 | ||||||
| @@ -35,7 +41,6 @@ jobs: | |||||||
|         with: |         with: | ||||||
|           node-version: 20 |           node-version: 20 | ||||||
|       - name: Install dependencies |       - name: Install dependencies | ||||||
|         shell: bash |  | ||||||
|         run: npm ci |         run: npm ci | ||||||
|       - name: Update nightly version |       - name: Update nightly version | ||||||
|         run: npm run chore:ci-update-nightly-version |         run: npm run chore:ci-update-nightly-version | ||||||
| @@ -44,7 +49,8 @@ jobs: | |||||||
|         with: |         with: | ||||||
|           os: ${{ matrix.os.name }} |           os: ${{ matrix.os.name }} | ||||||
|           arch: ${{ matrix.arch }} |           arch: ${{ matrix.arch }} | ||||||
|           extension: ${{ join(matrix.os.extension, ' ') }} |           shell: ${{ matrix.os.shell }} | ||||||
|  |           forge_platform: ${{ matrix.os.forge_platform }} | ||||||
|         env: |         env: | ||||||
|           APPLE_APP_CERTIFICATE_BASE64: ${{ secrets.APPLE_APP_CERTIFICATE_BASE64 }} |           APPLE_APP_CERTIFICATE_BASE64: ${{ secrets.APPLE_APP_CERTIFICATE_BASE64 }} | ||||||
|           APPLE_APP_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_APP_CERTIFICATE_PASSWORD }} |           APPLE_APP_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_APP_CERTIFICATE_PASSWORD }} | ||||||
| @@ -53,9 +59,11 @@ jobs: | |||||||
|           APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} |           APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} | ||||||
|           APPLE_ID: ${{ secrets.APPLE_ID }} |           APPLE_ID: ${{ secrets.APPLE_ID }} | ||||||
|           APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} |           APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} | ||||||
|  |           WINDOWS_SIGN_EXECUTABLE: ${{ vars.WINDOWS_SIGN_EXECUTABLE }} | ||||||
|  |  | ||||||
|       - name: Publish release |       - name: Publish release | ||||||
|         uses: softprops/action-gh-release@v2 |         uses: softprops/action-gh-release@v2 | ||||||
|  |         if: ${{ github.event_name != 'pull_request' }} | ||||||
|         with: |         with: | ||||||
|           make_latest: false |           make_latest: false | ||||||
|           prerelease: true |           prerelease: true | ||||||
| @@ -65,34 +73,9 @@ jobs: | |||||||
|           tag_name: nightly |           tag_name: nightly | ||||||
|           name: Nightly Build |           name: Nightly Build | ||||||
|  |  | ||||||
|   nightly-server: |       - name: Publish artifacts | ||||||
|     name: Deploy server nightly |         uses: actions/upload-artifact@v4 | ||||||
|     strategy: |         if: ${{ github.event_name == 'pull_request' }} | ||||||
|       fail-fast: false |  | ||||||
|       matrix: |  | ||||||
|         arch: [x64, arm64] |  | ||||||
|         include: |  | ||||||
|           - arch: x64 |  | ||||||
|             runs-on: ubuntu-latest |  | ||||||
|           - arch: arm64 |  | ||||||
|             runs-on: ubuntu-24.04-arm |  | ||||||
|     runs-on: ${{ matrix.runs-on }} |  | ||||||
|     steps: |  | ||||||
|       - uses: actions/checkout@v4 |  | ||||||
|  |  | ||||||
|       - name: Run the build |  | ||||||
|         uses: ./.github/actions/build-server |  | ||||||
|         with: |         with: | ||||||
|           os: linux |           name: TriliumNextNotes ${{ matrix.os.name }} ${{ matrix.arch }} | ||||||
|           arch: ${{ matrix.arch }} |           path: upload | ||||||
|  |  | ||||||
|       - name: Publish release |  | ||||||
|         uses: softprops/action-gh-release@v2 |  | ||||||
|         with: |  | ||||||
|           make_latest: false |  | ||||||
|           prerelease: true |  | ||||||
|           draft: false |  | ||||||
|           fail_on_unmatched_files: true |  | ||||||
|           files: upload/*.* |  | ||||||
|           tag_name: nightly |  | ||||||
|           name: Nightly Build |  | ||||||
|   | |||||||
							
								
								
									
										15
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							| @@ -20,13 +20,16 @@ jobs: | |||||||
|         os: |         os: | ||||||
|           - name: macos |           - name: macos | ||||||
|             image: macos-latest |             image: macos-latest | ||||||
|             extension: [dmg, zip] |             shell: bash | ||||||
|  |             forge_platform: darwin | ||||||
|           - name: linux |           - name: linux | ||||||
|             image: ubuntu-latest |             image: ubuntu-latest | ||||||
|             extension: [deb, rpm, zip, flatpak] |             shell: bash | ||||||
|  |             forge_platform: linux | ||||||
|           - name: windows |           - name: windows | ||||||
|             image: windows-latest |             image: win-signing | ||||||
|             extension: [exe, zip] |             shell: cmd | ||||||
|  |             forge_platform: win32 | ||||||
|     runs-on: ${{ matrix.os.image }} |     runs-on: ${{ matrix.os.image }} | ||||||
|     steps: |     steps: | ||||||
|       - uses: actions/checkout@v4 |       - uses: actions/checkout@v4 | ||||||
| @@ -39,7 +42,8 @@ jobs: | |||||||
|         with: |         with: | ||||||
|           os: ${{ matrix.os.name }} |           os: ${{ matrix.os.name }} | ||||||
|           arch: ${{ matrix.arch }} |           arch: ${{ matrix.arch }} | ||||||
|           extension: ${{ join(matrix.os.extension, ' ') }} |           shell: ${{ matrix.os.shell }} | ||||||
|  |           forge_platform: ${{ matrix.os.forge_platform }} | ||||||
|         env: |         env: | ||||||
|           APPLE_APP_CERTIFICATE_BASE64: ${{ secrets.APPLE_APP_CERTIFICATE_BASE64 }} |           APPLE_APP_CERTIFICATE_BASE64: ${{ secrets.APPLE_APP_CERTIFICATE_BASE64 }} | ||||||
|           APPLE_APP_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_APP_CERTIFICATE_PASSWORD }} |           APPLE_APP_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_APP_CERTIFICATE_PASSWORD }} | ||||||
| @@ -48,6 +52,7 @@ jobs: | |||||||
|           APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} |           APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} | ||||||
|           APPLE_ID: ${{ secrets.APPLE_ID }} |           APPLE_ID: ${{ secrets.APPLE_ID }} | ||||||
|           APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} |           APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} | ||||||
|  |           WINDOWS_SIGN_EXECUTABLE: ${{ vars.WINDOWS_SIGN_EXECUTABLE }} | ||||||
|  |  | ||||||
|       - name: Publish release |       - name: Publish release | ||||||
|         uses: softprops/action-gh-release@v2 |         uses: softprops/action-gh-release@v2 | ||||||
|   | |||||||
| @@ -21,6 +21,7 @@ function copyNodeModuleFileOrFolder(source: string) { | |||||||
| try { | try { | ||||||
|  |  | ||||||
|     const assetsToCopy = new Set([ |     const assetsToCopy = new Set([ | ||||||
|  |         "./node_modules", | ||||||
|         "./images", |         "./images", | ||||||
|         "./libraries", |         "./libraries", | ||||||
|         "./translations", |         "./translations", | ||||||
| @@ -33,6 +34,7 @@ try { | |||||||
|         "./forge.config.cjs", |         "./forge.config.cjs", | ||||||
|         "./bin/tpl/", |         "./bin/tpl/", | ||||||
|         "./bin/electron-forge/desktop.ejs", |         "./bin/electron-forge/desktop.ejs", | ||||||
|  |         "./bin/electron-forge/sign-windows.cjs", | ||||||
|         "./src/views/", |         "./src/views/", | ||||||
|         "./src/etapi/etapi.openapi.yaml", |         "./src/etapi/etapi.openapi.yaml", | ||||||
|         "./src/routes/api/openapi.json", |         "./src/routes/api/openapi.json", | ||||||
|   | |||||||
							
								
								
									
										14
									
								
								bin/electron-forge/sign-windows.cjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								bin/electron-forge/sign-windows.cjs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | const child_process = require("child_process"); | ||||||
|  |  | ||||||
|  | module.exports = function (filePath) { | ||||||
|  |     const { WINDOWS_SIGN_EXECUTABLE } = process.env; | ||||||
|  |  | ||||||
|  |     if (!WINDOWS_SIGN_EXECUTABLE) { | ||||||
|  |         console.warn("[Sign] Skip signing due to missing environment variable."); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     const command = `${WINDOWS_SIGN_EXECUTABLE} --executable "${filePath}"`; | ||||||
|  |     console.log(`[Sign] ${command}`); | ||||||
|  |     child_process.execSync(command); | ||||||
|  | } | ||||||
| @@ -8,9 +8,6 @@ noAuthentication=false | |||||||
| # set to true to disable backups (e.g. because of limited space on server) | # set to true to disable backups (e.g. because of limited space on server) | ||||||
| noBackup=false | noBackup=false | ||||||
|  |  | ||||||
| # Disable automatically generating desktop icon |  | ||||||
| # noDesktopIcon=true |  | ||||||
|  |  | ||||||
| [Network] | [Network] | ||||||
| # host setting is relevant only for web deployments - set the host on which the server will listen | # host setting is relevant only for web deployments - set the host on which the server will listen | ||||||
| # host=0.0.0.0 | # host=0.0.0.0 | ||||||
|   | |||||||
| @@ -43,6 +43,7 @@ It's possible to customize the title of generated date notes by defining a `#dat | |||||||
|  |  | ||||||
| It is also possible to customize the title of generated month notes through the `#monthPattern` attribute, much like `#datePattern`. The options are: | It is also possible to customize the title of generated month notes through the `#monthPattern` attribute, much like `#datePattern`. The options are: | ||||||
|  |  | ||||||
|  | *   `{isoMonth}` results in an ISO 8061 formatted month (e.g. "2025-03" for March 2025) | ||||||
| *   `{monthNumberPadded}` results in a number like `09` for September, and `11` for November | *   `{monthNumberPadded}` results in a number like `09` for September, and `11` for November | ||||||
| *   `{month}` results in the full month name (e.g. `September` or `October`) | *   `{month}` results in the full month name (e.g. `September` or `October`) | ||||||
| *   `{shortMonth3}` is replaced with the first 3 letters of the month, e.g. Jan, Feb, etc. | *   `{shortMonth3}` is replaced with the first 3 letters of the month, e.g. Jan, Feb, etc. | ||||||
|   | |||||||
| @@ -63,7 +63,7 @@ async function testAriaSnapshot({ page, context, noteTitle, snapshot }: AriaTest | |||||||
|     await app.goto(); |     await app.goto(); | ||||||
|     await app.goToNoteInNewTab(noteTitle); |     await app.goToNoteInNewTab(noteTitle); | ||||||
|  |  | ||||||
|     const svgData = app.currentNoteSplit.locator(".mermaid-render svg"); |     const svgData = app.currentNoteSplit.locator(".render-container svg"); | ||||||
|     await expect(svgData).toBeVisible(); |     await expect(svgData).toBeVisible(); | ||||||
|     await expect(svgData).toMatchAriaSnapshot(snapshot); |     await expect(svgData).toMatchAriaSnapshot(snapshot); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -54,6 +54,7 @@ export default class App { | |||||||
|     async goToNoteInNewTab(noteTitle: string) { |     async goToNoteInNewTab(noteTitle: string) { | ||||||
|         const autocomplete = this.currentNoteSplit.locator(".note-autocomplete"); |         const autocomplete = this.currentNoteSplit.locator(".note-autocomplete"); | ||||||
|         await autocomplete.fill(noteTitle); |         await autocomplete.fill(noteTitle); | ||||||
|  |         await expect(this.currentNoteSplit.locator(".note-detail-empty-results")).toContainText(noteTitle); | ||||||
|         await autocomplete.press("ArrowDown"); |         await autocomplete.press("ArrowDown"); | ||||||
|         await autocomplete.press("Enter"); |         await autocomplete.press("Enter"); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -4,9 +4,9 @@ import electron from "electron"; | |||||||
| import electronDebug from "electron-debug"; | import electronDebug from "electron-debug"; | ||||||
| import electronDl from "electron-dl"; | import electronDl from "electron-dl"; | ||||||
| import sqlInit from "./src/services/sql_init.js"; | import sqlInit from "./src/services/sql_init.js"; | ||||||
| import appIconService from "./src/services/app_icon.js"; |  | ||||||
| import windowService from "./src/services/window.js"; | import windowService from "./src/services/window.js"; | ||||||
| import tray from "./src/services/tray.js"; | import tray from "./src/services/tray.js"; | ||||||
|  | import options from "./src/services/options.js"; | ||||||
|  |  | ||||||
| import sourceMapSupport from "source-map-support"; | import sourceMapSupport from "source-map-support"; | ||||||
| sourceMapSupport.install(); | sourceMapSupport.install(); | ||||||
| @@ -19,12 +19,11 @@ if ((await import("electron-squirrel-startup")).default) { | |||||||
| // Adds debug features like hotkeys for triggering dev tools and reload | // Adds debug features like hotkeys for triggering dev tools and reload | ||||||
| electronDebug(); | electronDebug(); | ||||||
|  |  | ||||||
| appIconService.installLocalAppIcon(); |  | ||||||
|  |  | ||||||
| electronDl({ saveAs: true }); | electronDl({ saveAs: true }); | ||||||
|  |  | ||||||
| // needed for excalidraw export https://github.com/zadam/trilium/issues/4271 | // needed for excalidraw export https://github.com/zadam/trilium/issues/4271 | ||||||
| electron.app.commandLine.appendSwitch("enable-experimental-web-platform-features"); | electron.app.commandLine.appendSwitch("enable-experimental-web-platform-features"); | ||||||
|  | electron.app.commandLine.appendSwitch("lang", options.getOption("formattingLocale") ?? "en"); | ||||||
|  |  | ||||||
| electron.app.userAgentFallback = `${electron.app.getName()} ${electron.app.getVersion()}`; | electron.app.userAgentFallback = `${electron.app.getName()} ${electron.app.getVersion()}`; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,13 +2,17 @@ const path = require("path"); | |||||||
| const fs = require("fs-extra"); | const fs = require("fs-extra"); | ||||||
|  |  | ||||||
| const APP_NAME = "TriliumNext Notes"; | const APP_NAME = "TriliumNext Notes"; | ||||||
|  | const BIN_PATH = path.normalize("./bin/electron-forge"); | ||||||
|  |  | ||||||
| const extraResourcesForPlatform = getExtraResourcesForPlatform(); | const extraResourcesForPlatform = getExtraResourcesForPlatform(); | ||||||
| const baseLinuxMakerConfigOptions = { | const baseLinuxMakerConfigOptions = { | ||||||
|   icon: "./images/app-icons/png/128x128.png", |   icon: "./images/app-icons/png/128x128.png", | ||||||
|   desktopTemplate: path.resolve("./bin/electron-forge/desktop.ejs"), |   desktopTemplate: path.resolve(path.join(BIN_PATH, "desktop.ejs")), | ||||||
|   categories: ["Office", "Utility"] |   categories: ["Office", "Utility"] | ||||||
| }; | }; | ||||||
|  | const windowsSignConfiguration = process.env.WINDOWS_SIGN_EXECUTABLE ? { | ||||||
|  |     hookModulePath: path.join(BIN_PATH, "sign-windows.cjs") | ||||||
|  | } : undefined; | ||||||
|  |  | ||||||
| module.exports = { | module.exports = { | ||||||
|     // we run electron-forge inside the ./build folder, |     // we run electron-forge inside the ./build folder, | ||||||
| @@ -26,6 +30,7 @@ module.exports = { | |||||||
|             appleIdPassword: process.env.APPLE_ID_PASSWORD, |             appleIdPassword: process.env.APPLE_ID_PASSWORD, | ||||||
|             teamId: process.env.APPLE_TEAM_ID |             teamId: process.env.APPLE_TEAM_ID | ||||||
|         }, |         }, | ||||||
|  |         windowsSign: windowsSignConfiguration, | ||||||
|         extraResource: [ |         extraResource: [ | ||||||
|             // All resources should stay in Resources directory for macOS |             // All resources should stay in Resources directory for macOS | ||||||
|             ...(process.platform === "darwin" ? [] : extraResourcesForPlatform), |             ...(process.platform === "darwin" ? [] : extraResourcesForPlatform), | ||||||
| @@ -105,7 +110,8 @@ module.exports = { | |||||||
|             config: { |             config: { | ||||||
|                 iconUrl: "https://raw.githubusercontent.com/TriliumNext/Notes/develop/images/app-icons/icon.ico", |                 iconUrl: "https://raw.githubusercontent.com/TriliumNext/Notes/develop/images/app-icons/icon.ico", | ||||||
|                 setupIcon: "./images/app-icons/win/setup.ico", |                 setupIcon: "./images/app-icons/win/setup.ico", | ||||||
|                 loadingGif: "./images/app-icons/win/setup-banner.gif" |                 loadingGif: "./images/app-icons/win/setup-banner.gif", | ||||||
|  |                 windowsSign: windowsSignConfiguration | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
| @@ -129,7 +135,33 @@ module.exports = { | |||||||
|             name: "@electron-forge/plugin-auto-unpack-natives", |             name: "@electron-forge/plugin-auto-unpack-natives", | ||||||
|             config: {} |             config: {} | ||||||
|         } |         } | ||||||
|     ] |     ], | ||||||
|  |     hooks: { | ||||||
|  |         postMake(_, makeResults) { | ||||||
|  |             const outputDir = path.join(__dirname, "..", "upload"); | ||||||
|  |             fs.mkdirp(outputDir); | ||||||
|  |             for (const makeResult of makeResults) { | ||||||
|  |                 for (const artifactPath of makeResult.artifacts) { | ||||||
|  |                     // Ignore certain artifacts. | ||||||
|  |                     let fileName = path.basename(artifactPath); | ||||||
|  |                     const extension = path.extname(fileName); | ||||||
|  |                     if (fileName === "RELEASES" || extension === ".nupkg") { | ||||||
|  |                         continue; | ||||||
|  |                     } | ||||||
|  |  | ||||||
|  |                     // Override the extension for the CI. | ||||||
|  |                     const { TRILIUM_ARTIFACT_NAME_HINT } = process.env; | ||||||
|  |                     if (TRILIUM_ARTIFACT_NAME_HINT) { | ||||||
|  |                         fileName = TRILIUM_ARTIFACT_NAME_HINT + extension; | ||||||
|  |                     } | ||||||
|  |          | ||||||
|  |                     const outputPath = path.join(outputDir, fileName); | ||||||
|  |                     console.log(`[Artifact] ${artifactPath} -> ${outputPath}`); | ||||||
|  |                     fs.copyFile(artifactPath, outputPath); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
| }; | }; | ||||||
|  |  | ||||||
| function getExtraResourcesForPlatform() { | function getExtraResourcesForPlatform() { | ||||||
|   | |||||||
							
								
								
									
										172
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										172
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -39,7 +39,7 @@ | |||||||
|         "electron-squirrel-startup": "1.0.1", |         "electron-squirrel-startup": "1.0.1", | ||||||
|         "electron-window-state": "5.0.3", |         "electron-window-state": "5.0.3", | ||||||
|         "escape-html": "1.0.3", |         "escape-html": "1.0.3", | ||||||
|         "eslint-linter-browserify": "9.22.0", |         "eslint-linter-browserify": "9.23.0", | ||||||
|         "express": "4.21.2", |         "express": "4.21.2", | ||||||
|         "express-openid-connect": "^2.17.1", |         "express-openid-connect": "^2.17.1", | ||||||
|         "express-rate-limit": "7.5.0", |         "express-rate-limit": "7.5.0", | ||||||
| @@ -111,7 +111,7 @@ | |||||||
|         "@electron-forge/maker-zip": "7.7.0", |         "@electron-forge/maker-zip": "7.7.0", | ||||||
|         "@electron-forge/plugin-auto-unpack-natives": "7.7.0", |         "@electron-forge/plugin-auto-unpack-natives": "7.7.0", | ||||||
|         "@electron/rebuild": "3.7.1", |         "@electron/rebuild": "3.7.1", | ||||||
|         "@eslint/js": "9.22.0", |         "@eslint/js": "9.23.0", | ||||||
|         "@fullcalendar/core": "6.1.15", |         "@fullcalendar/core": "6.1.15", | ||||||
|         "@fullcalendar/daygrid": "6.1.15", |         "@fullcalendar/daygrid": "6.1.15", | ||||||
|         "@fullcalendar/interaction": "6.1.15", |         "@fullcalendar/interaction": "6.1.15", | ||||||
| @@ -140,12 +140,12 @@ | |||||||
|         "@types/jquery": "3.5.32", |         "@types/jquery": "3.5.32", | ||||||
|         "@types/js-yaml": "4.0.9", |         "@types/js-yaml": "4.0.9", | ||||||
|         "@types/jsdom": "21.1.7", |         "@types/jsdom": "21.1.7", | ||||||
|         "@types/leaflet": "1.9.16", |         "@types/leaflet": "1.9.17", | ||||||
|         "@types/leaflet-gpx": "1.3.7", |         "@types/leaflet-gpx": "1.3.7", | ||||||
|         "@types/mime-types": "2.1.4", |         "@types/mime-types": "2.1.4", | ||||||
|         "@types/multer": "1.4.12", |         "@types/multer": "1.4.12", | ||||||
|         "@types/node": "22.13.10", |         "@types/node": "22.13.13", | ||||||
|         "@types/react": "18.3.19", |         "@types/react": "18.3.20", | ||||||
|         "@types/react-dom": "18.3.5", |         "@types/react-dom": "18.3.5", | ||||||
|         "@types/safe-compare": "1.1.2", |         "@types/safe-compare": "1.1.2", | ||||||
|         "@types/sanitize-html": "2.13.0", |         "@types/sanitize-html": "2.13.0", | ||||||
| @@ -154,7 +154,7 @@ | |||||||
|         "@types/session-file-store": "1.2.5", |         "@types/session-file-store": "1.2.5", | ||||||
|         "@types/source-map-support": "0.5.10", |         "@types/source-map-support": "0.5.10", | ||||||
|         "@types/stream-throttle": "0.1.4", |         "@types/stream-throttle": "0.1.4", | ||||||
|         "@types/supertest": "6.0.2", |         "@types/supertest": "6.0.3", | ||||||
|         "@types/swagger-ui-express": "4.1.8", |         "@types/swagger-ui-express": "4.1.8", | ||||||
|         "@types/tmp": "0.2.6", |         "@types/tmp": "0.2.6", | ||||||
|         "@types/turndown": "5.0.5", |         "@types/turndown": "5.0.5", | ||||||
| @@ -167,7 +167,7 @@ | |||||||
|         "cross-env": "7.0.3", |         "cross-env": "7.0.3", | ||||||
|         "css-loader": "7.1.2", |         "css-loader": "7.1.2", | ||||||
|         "electron": "35.0.3", |         "electron": "35.0.3", | ||||||
|         "eslint": "9.22.0", |         "eslint": "9.23.0", | ||||||
|         "esm": "3.2.25", |         "esm": "3.2.25", | ||||||
|         "globals": "16.0.0", |         "globals": "16.0.0", | ||||||
|         "happy-dom": "17.4.4", |         "happy-dom": "17.4.4", | ||||||
| @@ -194,7 +194,7 @@ | |||||||
|         "tsx": "4.19.3", |         "tsx": "4.19.3", | ||||||
|         "typedoc": "0.28.1", |         "typedoc": "0.28.1", | ||||||
|         "typescript": "5.8.2", |         "typescript": "5.8.2", | ||||||
|         "typescript-eslint": "8.27.0", |         "typescript-eslint": "8.28.0", | ||||||
|         "vitest": "3.0.9", |         "vitest": "3.0.9", | ||||||
|         "webpack": "5.98.0", |         "webpack": "5.98.0", | ||||||
|         "webpack-cli": "6.0.1", |         "webpack-cli": "6.0.1", | ||||||
| @@ -1818,9 +1818,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/@eslint/config-helpers": { |     "node_modules/@eslint/config-helpers": { | ||||||
|       "version": "0.1.0", |       "version": "0.2.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.1.0.tgz", |       "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.0.tgz", | ||||||
|       "integrity": "sha512-kLrdPDJE1ckPo94kmPPf9Hfd0DU0Jw6oKYrhe+pwSC0iTUInmTa+w6fw8sGgcfkFJGNdWOUeOaDM4quW4a7OkA==", |       "integrity": "sha512-yJLLmLexii32mGrhW29qvU3QBVTu0GUmEf/J4XsBtVhp4JkIUFN/BjWqTF63yRvGApIDpZm5fa97LtYtINmfeQ==", | ||||||
|       "dev": true, |       "dev": true, | ||||||
|       "license": "Apache-2.0", |       "license": "Apache-2.0", | ||||||
|       "engines": { |       "engines": { | ||||||
| @@ -1841,9 +1841,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/@eslint/eslintrc": { |     "node_modules/@eslint/eslintrc": { | ||||||
|       "version": "3.3.0", |       "version": "3.3.1", | ||||||
|       "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.0.tgz", |       "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", | ||||||
|       "integrity": "sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ==", |       "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", | ||||||
|       "dev": true, |       "dev": true, | ||||||
|       "license": "MIT", |       "license": "MIT", | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
| @@ -1902,9 +1902,9 @@ | |||||||
|       "license": "MIT" |       "license": "MIT" | ||||||
|     }, |     }, | ||||||
|     "node_modules/@eslint/js": { |     "node_modules/@eslint/js": { | ||||||
|       "version": "9.22.0", |       "version": "9.23.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.22.0.tgz", |       "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.23.0.tgz", | ||||||
|       "integrity": "sha512-vLFajx9o8d1/oL2ZkpMYbkLv8nDB6yaIwFNt7nI4+I80U/z03SxmfOMsLbvWr3p7C+Wnoh//aOu2pQW8cS0HCQ==", |       "integrity": "sha512-35MJ8vCPU0ZMxo7zfev2pypqTwWTofFZO6m4KAtdoFhRpLJUpHTZZ+KB3C7Hb1d7bULYwO4lJXGCi5Se+8OMbw==", | ||||||
|       "dev": true, |       "dev": true, | ||||||
|       "license": "MIT", |       "license": "MIT", | ||||||
|       "engines": { |       "engines": { | ||||||
| @@ -5007,9 +5007,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/@types/leaflet": { |     "node_modules/@types/leaflet": { | ||||||
|       "version": "1.9.16", |       "version": "1.9.17", | ||||||
|       "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.16.tgz", |       "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.17.tgz", | ||||||
|       "integrity": "sha512-wzZoyySUxkgMZ0ihJ7IaUIblG8Rdc8AbbZKLneyn+QjYsj5q1QU7TEKYqwTr10BGSzY5LI7tJk9Ifo+mEjdFRw==", |       "integrity": "sha512-IJ4K6t7I3Fh5qXbQ1uwL3CFVbCi6haW9+53oLWgdKlLP7EaS21byWFJxxqOx9y8I0AP0actXSJLVMbyvxhkUTA==", | ||||||
|       "dev": true, |       "dev": true, | ||||||
|       "license": "MIT", |       "license": "MIT", | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
| @@ -5112,9 +5112,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/@types/node": { |     "node_modules/@types/node": { | ||||||
|       "version": "22.13.10", |       "version": "22.13.13", | ||||||
|       "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz", |       "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.13.tgz", | ||||||
|       "integrity": "sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==", |       "integrity": "sha512-ClsL5nMwKaBRwPcCvH8E7+nU4GxHVx1axNvMZTFHMEfNI7oahimt26P5zjVCRrjiIWj6YFXfE1v3dEp94wLcGQ==", | ||||||
|       "license": "MIT", |       "license": "MIT", | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "undici-types": "~6.20.0" |         "undici-types": "~6.20.0" | ||||||
| @@ -5142,9 +5142,9 @@ | |||||||
|       "license": "MIT" |       "license": "MIT" | ||||||
|     }, |     }, | ||||||
|     "node_modules/@types/react": { |     "node_modules/@types/react": { | ||||||
|       "version": "18.3.19", |       "version": "18.3.20", | ||||||
|       "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.19.tgz", |       "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.20.tgz", | ||||||
|       "integrity": "sha512-fcdJqaHOMDbiAwJnXv6XCzX0jDW77yI3tJqYh1Byn8EL5/S628WRx9b/y3DnNe55zTukUQKrfYxiZls2dHcUMw==", |       "integrity": "sha512-IPaCZN7PShZK/3t6Q87pfTkRm6oLTd4vztyoj+cbHUF1g3FfVb2tFIL79uCRKEfv16AhqDMBywP2VW3KIZUvcg==", | ||||||
|       "devOptional": true, |       "devOptional": true, | ||||||
|       "license": "MIT", |       "license": "MIT", | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
| @@ -5293,9 +5293,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/@types/supertest": { |     "node_modules/@types/supertest": { | ||||||
|       "version": "6.0.2", |       "version": "6.0.3", | ||||||
|       "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-6.0.2.tgz", |       "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-6.0.3.tgz", | ||||||
|       "integrity": "sha512-137ypx2lk/wTQbW6An6safu9hXmajAifU/s7szAHLN/FeIm5w7yR0Wkl9fdJMRSHwOn4HLAI0DaB2TOORuhPDg==", |       "integrity": "sha512-8WzXq62EXFhJ7QsH3Ocb/iKQ/Ty9ZVWnVzoTKc9tyyFRRF3a74Tk2+TLFgaFFw364Ere+npzHKEJ6ga2LzIL7w==", | ||||||
|       "dev": true, |       "dev": true, | ||||||
|       "license": "MIT", |       "license": "MIT", | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
| @@ -5397,17 +5397,17 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/@typescript-eslint/eslint-plugin": { |     "node_modules/@typescript-eslint/eslint-plugin": { | ||||||
|       "version": "8.27.0", |       "version": "8.28.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.27.0.tgz", |       "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.28.0.tgz", | ||||||
|       "integrity": "sha512-4henw4zkePi5p252c8ncBLzLce52SEUz2Ebj8faDnuUXz2UuHEONYcJ+G0oaCF+bYCWVZtrGzq3FD7YXetmnSA==", |       "integrity": "sha512-lvFK3TCGAHsItNdWZ/1FkvpzCxTHUVuFrdnOGLMa0GGCFIbCgQWVk3CzCGdA7kM3qGVc+dfW9tr0Z/sHnGDFyg==", | ||||||
|       "dev": true, |       "dev": true, | ||||||
|       "license": "MIT", |       "license": "MIT", | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "@eslint-community/regexpp": "^4.10.0", |         "@eslint-community/regexpp": "^4.10.0", | ||||||
|         "@typescript-eslint/scope-manager": "8.27.0", |         "@typescript-eslint/scope-manager": "8.28.0", | ||||||
|         "@typescript-eslint/type-utils": "8.27.0", |         "@typescript-eslint/type-utils": "8.28.0", | ||||||
|         "@typescript-eslint/utils": "8.27.0", |         "@typescript-eslint/utils": "8.28.0", | ||||||
|         "@typescript-eslint/visitor-keys": "8.27.0", |         "@typescript-eslint/visitor-keys": "8.28.0", | ||||||
|         "graphemer": "^1.4.0", |         "graphemer": "^1.4.0", | ||||||
|         "ignore": "^5.3.1", |         "ignore": "^5.3.1", | ||||||
|         "natural-compare": "^1.4.0", |         "natural-compare": "^1.4.0", | ||||||
| @@ -5427,16 +5427,16 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/@typescript-eslint/parser": { |     "node_modules/@typescript-eslint/parser": { | ||||||
|       "version": "8.27.0", |       "version": "8.28.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.27.0.tgz", |       "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.28.0.tgz", | ||||||
|       "integrity": "sha512-XGwIabPallYipmcOk45DpsBSgLC64A0yvdAkrwEzwZ2viqGqRUJ8eEYoPz0CWnutgAFbNMPdsGGvzjSmcWVlEA==", |       "integrity": "sha512-LPcw1yHD3ToaDEoljFEfQ9j2xShY367h7FZ1sq5NJT9I3yj4LHer1Xd1yRSOdYy9BpsrxU7R+eoDokChYM53lQ==", | ||||||
|       "dev": true, |       "dev": true, | ||||||
|       "license": "MIT", |       "license": "MIT", | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "@typescript-eslint/scope-manager": "8.27.0", |         "@typescript-eslint/scope-manager": "8.28.0", | ||||||
|         "@typescript-eslint/types": "8.27.0", |         "@typescript-eslint/types": "8.28.0", | ||||||
|         "@typescript-eslint/typescript-estree": "8.27.0", |         "@typescript-eslint/typescript-estree": "8.28.0", | ||||||
|         "@typescript-eslint/visitor-keys": "8.27.0", |         "@typescript-eslint/visitor-keys": "8.28.0", | ||||||
|         "debug": "^4.3.4" |         "debug": "^4.3.4" | ||||||
|       }, |       }, | ||||||
|       "engines": { |       "engines": { | ||||||
| @@ -5452,14 +5452,14 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/@typescript-eslint/scope-manager": { |     "node_modules/@typescript-eslint/scope-manager": { | ||||||
|       "version": "8.27.0", |       "version": "8.28.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.27.0.tgz", |       "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.28.0.tgz", | ||||||
|       "integrity": "sha512-8oI9GwPMQmBryaaxG1tOZdxXVeMDte6NyJA4i7/TWa4fBwgnAXYlIQP+uYOeqAaLJ2JRxlG9CAyL+C+YE9Xknw==", |       "integrity": "sha512-u2oITX3BJwzWCapoZ/pXw6BCOl8rJP4Ij/3wPoGvY8XwvXflOzd1kLrDUUUAIEdJSFh+ASwdTHqtan9xSg8buw==", | ||||||
|       "dev": true, |       "dev": true, | ||||||
|       "license": "MIT", |       "license": "MIT", | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "@typescript-eslint/types": "8.27.0", |         "@typescript-eslint/types": "8.28.0", | ||||||
|         "@typescript-eslint/visitor-keys": "8.27.0" |         "@typescript-eslint/visitor-keys": "8.28.0" | ||||||
|       }, |       }, | ||||||
|       "engines": { |       "engines": { | ||||||
|         "node": "^18.18.0 || ^20.9.0 || >=21.1.0" |         "node": "^18.18.0 || ^20.9.0 || >=21.1.0" | ||||||
| @@ -5470,14 +5470,14 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/@typescript-eslint/type-utils": { |     "node_modules/@typescript-eslint/type-utils": { | ||||||
|       "version": "8.27.0", |       "version": "8.28.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.27.0.tgz", |       "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.28.0.tgz", | ||||||
|       "integrity": "sha512-wVArTVcz1oJOIEJxui/nRhV0TXzD/zMSOYi/ggCfNq78EIszddXcJb7r4RCp/oBrjt8n9A0BSxRMKxHftpDxDA==", |       "integrity": "sha512-oRoXu2v0Rsy/VoOGhtWrOKDiIehvI+YNrDk5Oqj40Mwm0Yt01FC/Q7nFqg088d3yAsR1ZcZFVfPCTTFCe/KPwg==", | ||||||
|       "dev": true, |       "dev": true, | ||||||
|       "license": "MIT", |       "license": "MIT", | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "@typescript-eslint/typescript-estree": "8.27.0", |         "@typescript-eslint/typescript-estree": "8.28.0", | ||||||
|         "@typescript-eslint/utils": "8.27.0", |         "@typescript-eslint/utils": "8.28.0", | ||||||
|         "debug": "^4.3.4", |         "debug": "^4.3.4", | ||||||
|         "ts-api-utils": "^2.0.1" |         "ts-api-utils": "^2.0.1" | ||||||
|       }, |       }, | ||||||
| @@ -5494,9 +5494,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/@typescript-eslint/types": { |     "node_modules/@typescript-eslint/types": { | ||||||
|       "version": "8.27.0", |       "version": "8.28.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.27.0.tgz", |       "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.28.0.tgz", | ||||||
|       "integrity": "sha512-/6cp9yL72yUHAYq9g6DsAU+vVfvQmd1a8KyA81uvfDE21O2DwQ/qxlM4AR8TSdAu+kJLBDrEHKC5/W2/nxsY0A==", |       "integrity": "sha512-bn4WS1bkKEjx7HqiwG2JNB3YJdC1q6Ue7GyGlwPHyt0TnVq6TtD/hiOdTZt71sq0s7UzqBFXD8t8o2e63tXgwA==", | ||||||
|       "dev": true, |       "dev": true, | ||||||
|       "license": "MIT", |       "license": "MIT", | ||||||
|       "engines": { |       "engines": { | ||||||
| @@ -5508,14 +5508,14 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/@typescript-eslint/typescript-estree": { |     "node_modules/@typescript-eslint/typescript-estree": { | ||||||
|       "version": "8.27.0", |       "version": "8.28.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.27.0.tgz", |       "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.28.0.tgz", | ||||||
|       "integrity": "sha512-BnKq8cqPVoMw71O38a1tEb6iebEgGA80icSxW7g+kndx0o6ot6696HjG7NdgfuAVmVEtwXUr3L8R9ZuVjoQL6A==", |       "integrity": "sha512-H74nHEeBGeklctAVUvmDkxB1mk+PAZ9FiOMPFncdqeRBXxk1lWSYraHw8V12b7aa6Sg9HOBNbGdSHobBPuQSuA==", | ||||||
|       "dev": true, |       "dev": true, | ||||||
|       "license": "MIT", |       "license": "MIT", | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "@typescript-eslint/types": "8.27.0", |         "@typescript-eslint/types": "8.28.0", | ||||||
|         "@typescript-eslint/visitor-keys": "8.27.0", |         "@typescript-eslint/visitor-keys": "8.28.0", | ||||||
|         "debug": "^4.3.4", |         "debug": "^4.3.4", | ||||||
|         "fast-glob": "^3.3.2", |         "fast-glob": "^3.3.2", | ||||||
|         "is-glob": "^4.0.3", |         "is-glob": "^4.0.3", | ||||||
| @@ -5561,16 +5561,16 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/@typescript-eslint/utils": { |     "node_modules/@typescript-eslint/utils": { | ||||||
|       "version": "8.27.0", |       "version": "8.28.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.27.0.tgz", |       "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.28.0.tgz", | ||||||
|       "integrity": "sha512-njkodcwH1yvmo31YWgRHNb/x1Xhhq4/m81PhtvmRngD8iHPehxffz1SNCO+kwaePhATC+kOa/ggmvPoPza5i0Q==", |       "integrity": "sha512-OELa9hbTYciYITqgurT1u/SzpQVtDLmQMFzy/N8pQE+tefOyCWT79jHsav294aTqV1q1u+VzqDGbuujvRYaeSQ==", | ||||||
|       "dev": true, |       "dev": true, | ||||||
|       "license": "MIT", |       "license": "MIT", | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "@eslint-community/eslint-utils": "^4.4.0", |         "@eslint-community/eslint-utils": "^4.4.0", | ||||||
|         "@typescript-eslint/scope-manager": "8.27.0", |         "@typescript-eslint/scope-manager": "8.28.0", | ||||||
|         "@typescript-eslint/types": "8.27.0", |         "@typescript-eslint/types": "8.28.0", | ||||||
|         "@typescript-eslint/typescript-estree": "8.27.0" |         "@typescript-eslint/typescript-estree": "8.28.0" | ||||||
|       }, |       }, | ||||||
|       "engines": { |       "engines": { | ||||||
|         "node": "^18.18.0 || ^20.9.0 || >=21.1.0" |         "node": "^18.18.0 || ^20.9.0 || >=21.1.0" | ||||||
| @@ -5585,13 +5585,13 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/@typescript-eslint/visitor-keys": { |     "node_modules/@typescript-eslint/visitor-keys": { | ||||||
|       "version": "8.27.0", |       "version": "8.28.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.27.0.tgz", |       "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.28.0.tgz", | ||||||
|       "integrity": "sha512-WsXQwMkILJvffP6z4U3FYJPlbf/j07HIxmDjZpbNvBJkMfvwXj5ACRkkHwBDvLBbDbtX5TdU64/rcvKJ/vuInQ==", |       "integrity": "sha512-hbn8SZ8w4u2pRwgQ1GlUrPKE+t2XvcCW5tTRF7j6SMYIuYG37XuzIW44JCZPa36evi0Oy2SnM664BlIaAuQcvg==", | ||||||
|       "dev": true, |       "dev": true, | ||||||
|       "license": "MIT", |       "license": "MIT", | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "@typescript-eslint/types": "8.27.0", |         "@typescript-eslint/types": "8.28.0", | ||||||
|         "eslint-visitor-keys": "^4.2.0" |         "eslint-visitor-keys": "^4.2.0" | ||||||
|       }, |       }, | ||||||
|       "engines": { |       "engines": { | ||||||
| @@ -10270,19 +10270,19 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/eslint": { |     "node_modules/eslint": { | ||||||
|       "version": "9.22.0", |       "version": "9.23.0", | ||||||
|       "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.22.0.tgz", |       "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.23.0.tgz", | ||||||
|       "integrity": "sha512-9V/QURhsRN40xuHXWjV64yvrzMjcz7ZyNoF2jJFmy9j/SLk0u1OLSZgXi28MrXjymnjEGSR80WCdab3RGMDveQ==", |       "integrity": "sha512-jV7AbNoFPAY1EkFYpLq5bslU9NLNO8xnEeQXwErNibVryjk67wHVmddTBilc5srIttJDBrB0eMHKZBFbSIABCw==", | ||||||
|       "dev": true, |       "dev": true, | ||||||
|       "license": "MIT", |       "license": "MIT", | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "@eslint-community/eslint-utils": "^4.2.0", |         "@eslint-community/eslint-utils": "^4.2.0", | ||||||
|         "@eslint-community/regexpp": "^4.12.1", |         "@eslint-community/regexpp": "^4.12.1", | ||||||
|         "@eslint/config-array": "^0.19.2", |         "@eslint/config-array": "^0.19.2", | ||||||
|         "@eslint/config-helpers": "^0.1.0", |         "@eslint/config-helpers": "^0.2.0", | ||||||
|         "@eslint/core": "^0.12.0", |         "@eslint/core": "^0.12.0", | ||||||
|         "@eslint/eslintrc": "^3.3.0", |         "@eslint/eslintrc": "^3.3.1", | ||||||
|         "@eslint/js": "9.22.0", |         "@eslint/js": "9.23.0", | ||||||
|         "@eslint/plugin-kit": "^0.2.7", |         "@eslint/plugin-kit": "^0.2.7", | ||||||
|         "@humanfs/node": "^0.16.6", |         "@humanfs/node": "^0.16.6", | ||||||
|         "@humanwhocodes/module-importer": "^1.0.1", |         "@humanwhocodes/module-importer": "^1.0.1", | ||||||
| @@ -10331,9 +10331,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/eslint-linter-browserify": { |     "node_modules/eslint-linter-browserify": { | ||||||
|       "version": "9.22.0", |       "version": "9.23.0", | ||||||
|       "resolved": "https://registry.npmjs.org/eslint-linter-browserify/-/eslint-linter-browserify-9.22.0.tgz", |       "resolved": "https://registry.npmjs.org/eslint-linter-browserify/-/eslint-linter-browserify-9.23.0.tgz", | ||||||
|       "integrity": "sha512-b70x+ilh1XkugEZZvGJ6LNPE1+jxjsn4KIdj1OBMBGbzYj7l2lr3N/Y4NHKhFxq2a4v/J8WqojIOvy0AFDmrXw==", |       "integrity": "sha512-5dpvA43y3psh58cl5HILg0Fk82KUP30YqCMQw17mt5H3kG16G3YfQgSE+sKV/6U3fT/SBitFrQA9PX0BZ7xUBQ==", | ||||||
|       "license": "MIT" |       "license": "MIT" | ||||||
|     }, |     }, | ||||||
|     "node_modules/eslint-scope": { |     "node_modules/eslint-scope": { | ||||||
| @@ -19643,15 +19643,15 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/typescript-eslint": { |     "node_modules/typescript-eslint": { | ||||||
|       "version": "8.27.0", |       "version": "8.28.0", | ||||||
|       "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.27.0.tgz", |       "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.28.0.tgz", | ||||||
|       "integrity": "sha512-ZZ/8+Y0rRUMuW1gJaPtLWe4ryHbsPLzzibk5Sq+IFa2aOH1Vo0gPr1fbA6pOnzBke7zC2Da4w8AyCgxKXo3lqA==", |       "integrity": "sha512-jfZtxJoHm59bvoCMYCe2BM0/baMswRhMmYhy+w6VfcyHrjxZ0OJe0tGasydCpIpA+A/WIJhTyZfb3EtwNC/kHQ==", | ||||||
|       "dev": true, |       "dev": true, | ||||||
|       "license": "MIT", |       "license": "MIT", | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "@typescript-eslint/eslint-plugin": "8.27.0", |         "@typescript-eslint/eslint-plugin": "8.28.0", | ||||||
|         "@typescript-eslint/parser": "8.27.0", |         "@typescript-eslint/parser": "8.28.0", | ||||||
|         "@typescript-eslint/utils": "8.27.0" |         "@typescript-eslint/utils": "8.28.0" | ||||||
|       }, |       }, | ||||||
|       "engines": { |       "engines": { | ||||||
|         "node": "^18.18.0 || ^20.9.0 || >=21.1.0" |         "node": "^18.18.0 || ^20.9.0 || >=21.1.0" | ||||||
|   | |||||||
							
								
								
									
										20
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								package.json
									
									
									
									
									
								
							| @@ -38,9 +38,9 @@ | |||||||
|     "electron:switch": "electron-rebuild", |     "electron:switch": "electron-rebuild", | ||||||
|     "docs:edit": "cross-env NODE_OPTIONS=\"--import tsx\" TRILIUM_DATA_DIR=./data-docs TRILIUM_ENV=dev TRILIUM_PORT=37741 electron ./electron-docs-main.ts .", |     "docs:edit": "cross-env NODE_OPTIONS=\"--import tsx\" TRILIUM_DATA_DIR=./data-docs TRILIUM_ENV=dev TRILIUM_PORT=37741 electron ./electron-docs-main.ts .", | ||||||
|     "docs:edit-nix": "electron-rebuild --version 33.3.1 && cross-env NODE_OPTIONS=\"--import tsx\" TRILIUM_DATA_DIR=./data-docs TRILIUM_PORT=37741 TRILIUM_ENV=dev nix-shell -p electron_33 --run \"electron ./electron-docs-main.ts .\"", |     "docs:edit-nix": "electron-rebuild --version 33.3.1 && cross-env NODE_OPTIONS=\"--import tsx\" TRILIUM_DATA_DIR=./data-docs TRILIUM_PORT=37741 TRILIUM_ENV=dev nix-shell -p electron_33 --run \"electron ./electron-docs-main.ts .\"", | ||||||
|     "electron-forge:prepare": "npm run build:prepare-dist && cp -r node_modules ./build", |     "electron-forge:prepare": "npm run build:prepare-dist", | ||||||
|     "electron-forge:start": "npm run electron-forge:prepare && cd ./build && electron-forge start", |     "electron-forge:start": "npm run electron-forge:prepare && cd ./build && electron-forge start", | ||||||
|     "electron-forge:make": "npm run electron-forge:prepare && cd ./build && electron-forge make", |     "electron-forge:make": "npm run electron-forge:prepare && cross-env DEBUG=electron-windows-installer:* electron-forge make ./build", | ||||||
|     "electron-forge:package": "npm run electron-forge:prepare && cd ./build && electron-forge package", |     "electron-forge:package": "npm run electron-forge:prepare && cd ./build && electron-forge package", | ||||||
|     "docs:build-backend": "rimraf ./docs/backend_api && typedoc ./docs/backend_api src/becca/entities/*.ts src/services/backend_script_api.ts src/services/sql.ts", |     "docs:build-backend": "rimraf ./docs/backend_api && typedoc ./docs/backend_api src/becca/entities/*.ts src/services/backend_script_api.ts src/services/sql.ts", | ||||||
|     "docs:build-frontend": "rimraf ./docs/frontend_api && jsdoc -c jsdoc-conf.json -d ./docs/frontend_api src/public/app/entities/*.js src/public/app/services/frontend_script_api.js src/public/app/widgets/basic_widget.js src/public/app/widgets/note_context_aware_widget.js src/public/app/widgets/right_panel_widget.js", |     "docs:build-frontend": "rimraf ./docs/frontend_api && jsdoc -c jsdoc-conf.json -d ./docs/frontend_api src/public/app/entities/*.js src/public/app/services/frontend_script_api.js src/public/app/widgets/basic_widget.js src/public/app/widgets/note_context_aware_widget.js src/public/app/widgets/right_panel_widget.js", | ||||||
| @@ -99,7 +99,7 @@ | |||||||
|     "electron-squirrel-startup": "1.0.1", |     "electron-squirrel-startup": "1.0.1", | ||||||
|     "electron-window-state": "5.0.3", |     "electron-window-state": "5.0.3", | ||||||
|     "escape-html": "1.0.3", |     "escape-html": "1.0.3", | ||||||
|     "eslint-linter-browserify": "9.22.0", |     "eslint-linter-browserify": "9.23.0", | ||||||
|     "express": "4.21.2", |     "express": "4.21.2", | ||||||
|     "express-openid-connect": "^2.17.1", |     "express-openid-connect": "^2.17.1", | ||||||
|     "express-rate-limit": "7.5.0", |     "express-rate-limit": "7.5.0", | ||||||
| @@ -168,7 +168,7 @@ | |||||||
|     "@electron-forge/maker-zip": "7.7.0", |     "@electron-forge/maker-zip": "7.7.0", | ||||||
|     "@electron-forge/plugin-auto-unpack-natives": "7.7.0", |     "@electron-forge/plugin-auto-unpack-natives": "7.7.0", | ||||||
|     "@electron/rebuild": "3.7.1", |     "@electron/rebuild": "3.7.1", | ||||||
|     "@eslint/js": "9.22.0", |     "@eslint/js": "9.23.0", | ||||||
|     "@fullcalendar/core": "6.1.15", |     "@fullcalendar/core": "6.1.15", | ||||||
|     "@fullcalendar/daygrid": "6.1.15", |     "@fullcalendar/daygrid": "6.1.15", | ||||||
|     "@fullcalendar/interaction": "6.1.15", |     "@fullcalendar/interaction": "6.1.15", | ||||||
| @@ -197,12 +197,12 @@ | |||||||
|     "@types/jquery": "3.5.32", |     "@types/jquery": "3.5.32", | ||||||
|     "@types/js-yaml": "4.0.9", |     "@types/js-yaml": "4.0.9", | ||||||
|     "@types/jsdom": "21.1.7", |     "@types/jsdom": "21.1.7", | ||||||
|     "@types/leaflet": "1.9.16", |     "@types/leaflet": "1.9.17", | ||||||
|     "@types/leaflet-gpx": "1.3.7", |     "@types/leaflet-gpx": "1.3.7", | ||||||
|     "@types/mime-types": "2.1.4", |     "@types/mime-types": "2.1.4", | ||||||
|     "@types/multer": "1.4.12", |     "@types/multer": "1.4.12", | ||||||
|     "@types/node": "22.13.10", |     "@types/node": "22.13.13", | ||||||
|     "@types/react": "18.3.19", |     "@types/react": "18.3.20", | ||||||
|     "@types/react-dom": "18.3.5", |     "@types/react-dom": "18.3.5", | ||||||
|     "@types/safe-compare": "1.1.2", |     "@types/safe-compare": "1.1.2", | ||||||
|     "@types/sanitize-html": "2.13.0", |     "@types/sanitize-html": "2.13.0", | ||||||
| @@ -211,7 +211,7 @@ | |||||||
|     "@types/session-file-store": "1.2.5", |     "@types/session-file-store": "1.2.5", | ||||||
|     "@types/source-map-support": "0.5.10", |     "@types/source-map-support": "0.5.10", | ||||||
|     "@types/stream-throttle": "0.1.4", |     "@types/stream-throttle": "0.1.4", | ||||||
|     "@types/supertest": "6.0.2", |     "@types/supertest": "6.0.3", | ||||||
|     "@types/swagger-ui-express": "4.1.8", |     "@types/swagger-ui-express": "4.1.8", | ||||||
|     "@types/tmp": "0.2.6", |     "@types/tmp": "0.2.6", | ||||||
|     "@types/turndown": "5.0.5", |     "@types/turndown": "5.0.5", | ||||||
| @@ -224,7 +224,7 @@ | |||||||
|     "cross-env": "7.0.3", |     "cross-env": "7.0.3", | ||||||
|     "css-loader": "7.1.2", |     "css-loader": "7.1.2", | ||||||
|     "electron": "35.0.3", |     "electron": "35.0.3", | ||||||
|     "eslint": "9.22.0", |     "eslint": "9.23.0", | ||||||
|     "esm": "3.2.25", |     "esm": "3.2.25", | ||||||
|     "globals": "16.0.0", |     "globals": "16.0.0", | ||||||
|     "happy-dom": "17.4.4", |     "happy-dom": "17.4.4", | ||||||
| @@ -251,7 +251,7 @@ | |||||||
|     "tsx": "4.19.3", |     "tsx": "4.19.3", | ||||||
|     "typedoc": "0.28.1", |     "typedoc": "0.28.1", | ||||||
|     "typescript": "5.8.2", |     "typescript": "5.8.2", | ||||||
|     "typescript-eslint": "8.27.0", |     "typescript-eslint": "8.28.0", | ||||||
|     "vitest": "3.0.9", |     "vitest": "3.0.9", | ||||||
|     "webpack": "5.98.0", |     "webpack": "5.98.0", | ||||||
|     "webpack-cli": "6.0.1", |     "webpack-cli": "6.0.1", | ||||||
|   | |||||||
							
								
								
									
										173
									
								
								packages/turndown-plugin-gfm/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										173
									
								
								packages/turndown-plugin-gfm/package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -163,9 +163,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/@rollup/rollup-android-arm-eabi": { |     "node_modules/@rollup/rollup-android-arm-eabi": { | ||||||
|       "version": "4.36.0", |       "version": "4.37.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.36.0.tgz", |       "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.37.0.tgz", | ||||||
|       "integrity": "sha512-jgrXjjcEwN6XpZXL0HUeOVGfjXhPyxAbbhD0BlXUB+abTOpbPiN5Wb3kOT7yb+uEtATNYF5x5gIfwutmuBA26w==", |       "integrity": "sha512-l7StVw6WAa8l3vA1ov80jyetOAEo1FtHvZDbzXDO/02Sq/QVvqlHkYoFwDJPIMj0GKiistsBudfx5tGFnwYWDQ==", | ||||||
|       "cpu": [ |       "cpu": [ | ||||||
|         "arm" |         "arm" | ||||||
|       ], |       ], | ||||||
| @@ -177,9 +177,9 @@ | |||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "node_modules/@rollup/rollup-android-arm64": { |     "node_modules/@rollup/rollup-android-arm64": { | ||||||
|       "version": "4.36.0", |       "version": "4.37.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.36.0.tgz", |       "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.37.0.tgz", | ||||||
|       "integrity": "sha512-NyfuLvdPdNUfUNeYKUwPwKsE5SXa2J6bCt2LdB/N+AxShnkpiczi3tcLJrm5mA+eqpy0HmaIY9F6XCa32N5yzg==", |       "integrity": "sha512-6U3SlVyMxezt8Y+/iEBcbp945uZjJwjZimu76xoG7tO1av9VO691z8PkhzQ85ith2I8R2RddEPeSfcbyPfD4hA==", | ||||||
|       "cpu": [ |       "cpu": [ | ||||||
|         "arm64" |         "arm64" | ||||||
|       ], |       ], | ||||||
| @@ -191,9 +191,9 @@ | |||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "node_modules/@rollup/rollup-darwin-arm64": { |     "node_modules/@rollup/rollup-darwin-arm64": { | ||||||
|       "version": "4.36.0", |       "version": "4.37.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.36.0.tgz", |       "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.37.0.tgz", | ||||||
|       "integrity": "sha512-JQ1Jk5G4bGrD4pWJQzWsD8I1n1mgPXq33+/vP4sk8j/z/C2siRuxZtaUA7yMTf71TCZTZl/4e1bfzwUmFb3+rw==", |       "integrity": "sha512-+iTQ5YHuGmPt10NTzEyMPbayiNTcOZDWsbxZYR1ZnmLnZxG17ivrPSWFO9j6GalY0+gV3Jtwrrs12DBscxnlYA==", | ||||||
|       "cpu": [ |       "cpu": [ | ||||||
|         "arm64" |         "arm64" | ||||||
|       ], |       ], | ||||||
| @@ -205,9 +205,9 @@ | |||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "node_modules/@rollup/rollup-darwin-x64": { |     "node_modules/@rollup/rollup-darwin-x64": { | ||||||
|       "version": "4.36.0", |       "version": "4.37.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.36.0.tgz", |       "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.37.0.tgz", | ||||||
|       "integrity": "sha512-6c6wMZa1lrtiRsbDziCmjE53YbTkxMYhhnWnSW8R/yqsM7a6mSJ3uAVT0t8Y/DGt7gxUWYuFM4bwWk9XCJrFKA==", |       "integrity": "sha512-m8W2UbxLDcmRKVjgl5J/k4B8d7qX2EcJve3Sut7YGrQoPtCIQGPH5AMzuFvYRWZi0FVS0zEY4c8uttPfX6bwYQ==", | ||||||
|       "cpu": [ |       "cpu": [ | ||||||
|         "x64" |         "x64" | ||||||
|       ], |       ], | ||||||
| @@ -219,9 +219,9 @@ | |||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "node_modules/@rollup/rollup-freebsd-arm64": { |     "node_modules/@rollup/rollup-freebsd-arm64": { | ||||||
|       "version": "4.36.0", |       "version": "4.37.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.36.0.tgz", |       "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.37.0.tgz", | ||||||
|       "integrity": "sha512-KXVsijKeJXOl8QzXTsA+sHVDsFOmMCdBRgFmBb+mfEb/7geR7+C8ypAml4fquUt14ZyVXaw2o1FWhqAfOvA4sg==", |       "integrity": "sha512-FOMXGmH15OmtQWEt174v9P1JqqhlgYge/bUjIbiVD1nI1NeJ30HYT9SJlZMqdo1uQFyt9cz748F1BHghWaDnVA==", | ||||||
|       "cpu": [ |       "cpu": [ | ||||||
|         "arm64" |         "arm64" | ||||||
|       ], |       ], | ||||||
| @@ -233,9 +233,9 @@ | |||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "node_modules/@rollup/rollup-freebsd-x64": { |     "node_modules/@rollup/rollup-freebsd-x64": { | ||||||
|       "version": "4.36.0", |       "version": "4.37.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.36.0.tgz", |       "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.37.0.tgz", | ||||||
|       "integrity": "sha512-dVeWq1ebbvByI+ndz4IJcD4a09RJgRYmLccwlQ8bPd4olz3Y213uf1iwvc7ZaxNn2ab7bjc08PrtBgMu6nb4pQ==", |       "integrity": "sha512-SZMxNttjPKvV14Hjck5t70xS3l63sbVwl98g3FlVVx2YIDmfUIy29jQrsw06ewEYQ8lQSuY9mpAPlmgRD2iSsA==", | ||||||
|       "cpu": [ |       "cpu": [ | ||||||
|         "x64" |         "x64" | ||||||
|       ], |       ], | ||||||
| @@ -247,9 +247,9 @@ | |||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "node_modules/@rollup/rollup-linux-arm-gnueabihf": { |     "node_modules/@rollup/rollup-linux-arm-gnueabihf": { | ||||||
|       "version": "4.36.0", |       "version": "4.37.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.36.0.tgz", |       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.37.0.tgz", | ||||||
|       "integrity": "sha512-bvXVU42mOVcF4le6XSjscdXjqx8okv4n5vmwgzcmtvFdifQ5U4dXFYaCB87namDRKlUL9ybVtLQ9ztnawaSzvg==", |       "integrity": "sha512-hhAALKJPidCwZcj+g+iN+38SIOkhK2a9bqtJR+EtyxrKKSt1ynCBeqrQy31z0oWU6thRZzdx53hVgEbRkuI19w==", | ||||||
|       "cpu": [ |       "cpu": [ | ||||||
|         "arm" |         "arm" | ||||||
|       ], |       ], | ||||||
| @@ -261,9 +261,9 @@ | |||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "node_modules/@rollup/rollup-linux-arm-musleabihf": { |     "node_modules/@rollup/rollup-linux-arm-musleabihf": { | ||||||
|       "version": "4.36.0", |       "version": "4.37.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.36.0.tgz", |       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.37.0.tgz", | ||||||
|       "integrity": "sha512-JFIQrDJYrxOnyDQGYkqnNBtjDwTgbasdbUiQvcU8JmGDfValfH1lNpng+4FWlhaVIR4KPkeddYjsVVbmJYvDcg==", |       "integrity": "sha512-jUb/kmn/Gd8epbHKEqkRAxq5c2EwRt0DqhSGWjPFxLeFvldFdHQs/n8lQ9x85oAeVb6bHcS8irhTJX2FCOd8Ag==", | ||||||
|       "cpu": [ |       "cpu": [ | ||||||
|         "arm" |         "arm" | ||||||
|       ], |       ], | ||||||
| @@ -275,9 +275,9 @@ | |||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "node_modules/@rollup/rollup-linux-arm64-gnu": { |     "node_modules/@rollup/rollup-linux-arm64-gnu": { | ||||||
|       "version": "4.36.0", |       "version": "4.37.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.36.0.tgz", |       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.37.0.tgz", | ||||||
|       "integrity": "sha512-KqjYVh3oM1bj//5X7k79PSCZ6CvaVzb7Qs7VMWS+SlWB5M8p3FqufLP9VNp4CazJ0CsPDLwVD9r3vX7Ci4J56A==", |       "integrity": "sha512-oNrJxcQT9IcbcmKlkF+Yz2tmOxZgG9D9GRq+1OE6XCQwCVwxixYAa38Z8qqPzQvzt1FCfmrHX03E0pWoXm1DqA==", | ||||||
|       "cpu": [ |       "cpu": [ | ||||||
|         "arm64" |         "arm64" | ||||||
|       ], |       ], | ||||||
| @@ -289,9 +289,9 @@ | |||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "node_modules/@rollup/rollup-linux-arm64-musl": { |     "node_modules/@rollup/rollup-linux-arm64-musl": { | ||||||
|       "version": "4.36.0", |       "version": "4.37.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.36.0.tgz", |       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.37.0.tgz", | ||||||
|       "integrity": "sha512-QiGnhScND+mAAtfHqeT+cB1S9yFnNQ/EwCg5yE3MzoaZZnIV0RV9O5alJAoJKX/sBONVKeZdMfO8QSaWEygMhw==", |       "integrity": "sha512-pfxLBMls+28Ey2enpX3JvjEjaJMBX5XlPCZNGxj4kdJyHduPBXtxYeb8alo0a7bqOoWZW2uKynhHxF/MWoHaGQ==", | ||||||
|       "cpu": [ |       "cpu": [ | ||||||
|         "arm64" |         "arm64" | ||||||
|       ], |       ], | ||||||
| @@ -303,9 +303,9 @@ | |||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "node_modules/@rollup/rollup-linux-loongarch64-gnu": { |     "node_modules/@rollup/rollup-linux-loongarch64-gnu": { | ||||||
|       "version": "4.36.0", |       "version": "4.37.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.36.0.tgz", |       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.37.0.tgz", | ||||||
|       "integrity": "sha512-1ZPyEDWF8phd4FQtTzMh8FQwqzvIjLsl6/84gzUxnMNFBtExBtpL51H67mV9xipuxl1AEAerRBgBwFNpkw8+Lg==", |       "integrity": "sha512-yCE0NnutTC/7IGUq/PUHmoeZbIwq3KRh02e9SfFh7Vmc1Z7atuJRYWhRME5fKgT8aS20mwi1RyChA23qSyRGpA==", | ||||||
|       "cpu": [ |       "cpu": [ | ||||||
|         "loong64" |         "loong64" | ||||||
|       ], |       ], | ||||||
| @@ -317,9 +317,9 @@ | |||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { |     "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { | ||||||
|       "version": "4.36.0", |       "version": "4.37.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.36.0.tgz", |       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.37.0.tgz", | ||||||
|       "integrity": "sha512-VMPMEIUpPFKpPI9GZMhJrtu8rxnp6mJR3ZzQPykq4xc2GmdHj3Q4cA+7avMyegXy4n1v+Qynr9fR88BmyO74tg==", |       "integrity": "sha512-NxcICptHk06E2Lh3a4Pu+2PEdZ6ahNHuK7o6Np9zcWkrBMuv21j10SQDJW3C9Yf/A/P7cutWoC/DptNLVsZ0VQ==", | ||||||
|       "cpu": [ |       "cpu": [ | ||||||
|         "ppc64" |         "ppc64" | ||||||
|       ], |       ], | ||||||
| @@ -331,9 +331,23 @@ | |||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "node_modules/@rollup/rollup-linux-riscv64-gnu": { |     "node_modules/@rollup/rollup-linux-riscv64-gnu": { | ||||||
|       "version": "4.36.0", |       "version": "4.37.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.36.0.tgz", |       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.37.0.tgz", | ||||||
|       "integrity": "sha512-ttE6ayb/kHwNRJGYLpuAvB7SMtOeQnVXEIpMtAvx3kepFQeowVED0n1K9nAdraHUPJ5hydEMxBpIR7o4nrm8uA==", |       "integrity": "sha512-PpWwHMPCVpFZLTfLq7EWJWvrmEuLdGn1GMYcm5MV7PaRgwCEYJAwiN94uBuZev0/J/hFIIJCsYw4nLmXA9J7Pw==", | ||||||
|  |       "cpu": [ | ||||||
|  |         "riscv64" | ||||||
|  |       ], | ||||||
|  |       "dev": true, | ||||||
|  |       "license": "MIT", | ||||||
|  |       "optional": true, | ||||||
|  |       "os": [ | ||||||
|  |         "linux" | ||||||
|  |       ] | ||||||
|  |     }, | ||||||
|  |     "node_modules/@rollup/rollup-linux-riscv64-musl": { | ||||||
|  |       "version": "4.37.0", | ||||||
|  |       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.37.0.tgz", | ||||||
|  |       "integrity": "sha512-DTNwl6a3CfhGTAOYZ4KtYbdS8b+275LSLqJVJIrPa5/JuIufWWZ/QFvkxp52gpmguN95eujrM68ZG+zVxa8zHA==", | ||||||
|       "cpu": [ |       "cpu": [ | ||||||
|         "riscv64" |         "riscv64" | ||||||
|       ], |       ], | ||||||
| @@ -345,9 +359,9 @@ | |||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "node_modules/@rollup/rollup-linux-s390x-gnu": { |     "node_modules/@rollup/rollup-linux-s390x-gnu": { | ||||||
|       "version": "4.36.0", |       "version": "4.37.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.36.0.tgz", |       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.37.0.tgz", | ||||||
|       "integrity": "sha512-4a5gf2jpS0AIe7uBjxDeUMNcFmaRTbNv7NxI5xOCs4lhzsVyGR/0qBXduPnoWf6dGC365saTiwag8hP1imTgag==", |       "integrity": "sha512-hZDDU5fgWvDdHFuExN1gBOhCuzo/8TMpidfOR+1cPZJflcEzXdCy1LjnklQdW8/Et9sryOPJAKAQRw8Jq7Tg+A==", | ||||||
|       "cpu": [ |       "cpu": [ | ||||||
|         "s390x" |         "s390x" | ||||||
|       ], |       ], | ||||||
| @@ -359,9 +373,9 @@ | |||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "node_modules/@rollup/rollup-linux-x64-gnu": { |     "node_modules/@rollup/rollup-linux-x64-gnu": { | ||||||
|       "version": "4.36.0", |       "version": "4.37.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.36.0.tgz", |       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.37.0.tgz", | ||||||
|       "integrity": "sha512-5KtoW8UWmwFKQ96aQL3LlRXX16IMwyzMq/jSSVIIyAANiE1doaQsx/KRyhAvpHlPjPiSU/AYX/8m+lQ9VToxFQ==", |       "integrity": "sha512-pKivGpgJM5g8dwj0ywBwe/HeVAUSuVVJhUTa/URXjxvoyTT/AxsLTAbkHkDHG7qQxLoW2s3apEIl26uUe08LVQ==", | ||||||
|       "cpu": [ |       "cpu": [ | ||||||
|         "x64" |         "x64" | ||||||
|       ], |       ], | ||||||
| @@ -373,9 +387,9 @@ | |||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "node_modules/@rollup/rollup-linux-x64-musl": { |     "node_modules/@rollup/rollup-linux-x64-musl": { | ||||||
|       "version": "4.36.0", |       "version": "4.37.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.36.0.tgz", |       "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.37.0.tgz", | ||||||
|       "integrity": "sha512-sycrYZPrv2ag4OCvaN5js+f01eoZ2U+RmT5as8vhxiFz+kxwlHrsxOwKPSA8WyS+Wc6Epid9QeI/IkQ9NkgYyQ==", |       "integrity": "sha512-E2lPrLKE8sQbY/2bEkVTGDEk4/49UYRVWgj90MY8yPjpnGBQ+Xi1Qnr7b7UIWw1NOggdFQFOLZ8+5CzCiz143w==", | ||||||
|       "cpu": [ |       "cpu": [ | ||||||
|         "x64" |         "x64" | ||||||
|       ], |       ], | ||||||
| @@ -387,9 +401,9 @@ | |||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "node_modules/@rollup/rollup-win32-arm64-msvc": { |     "node_modules/@rollup/rollup-win32-arm64-msvc": { | ||||||
|       "version": "4.36.0", |       "version": "4.37.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.36.0.tgz", |       "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.37.0.tgz", | ||||||
|       "integrity": "sha512-qbqt4N7tokFwwSVlWDsjfoHgviS3n/vZ8LK0h1uLG9TYIRuUTJC88E1xb3LM2iqZ/WTqNQjYrtmtGmrmmawB6A==", |       "integrity": "sha512-Jm7biMazjNzTU4PrQtr7VS8ibeys9Pn29/1bm4ph7CP2kf21950LgN+BaE2mJ1QujnvOc6p54eWWiVvn05SOBg==", | ||||||
|       "cpu": [ |       "cpu": [ | ||||||
|         "arm64" |         "arm64" | ||||||
|       ], |       ], | ||||||
| @@ -401,9 +415,9 @@ | |||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "node_modules/@rollup/rollup-win32-ia32-msvc": { |     "node_modules/@rollup/rollup-win32-ia32-msvc": { | ||||||
|       "version": "4.36.0", |       "version": "4.37.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.36.0.tgz", |       "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.37.0.tgz", | ||||||
|       "integrity": "sha512-t+RY0JuRamIocMuQcfwYSOkmdX9dtkr1PbhKW42AMvaDQa+jOdpUYysroTF/nuPpAaQMWp7ye+ndlmmthieJrQ==", |       "integrity": "sha512-e3/1SFm1OjefWICB2Ucstg2dxYDkDTZGDYgwufcbsxTHyqQps1UQf33dFEChBNmeSsTOyrjw2JJq0zbG5GF6RA==", | ||||||
|       "cpu": [ |       "cpu": [ | ||||||
|         "ia32" |         "ia32" | ||||||
|       ], |       ], | ||||||
| @@ -415,9 +429,9 @@ | |||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     "node_modules/@rollup/rollup-win32-x64-msvc": { |     "node_modules/@rollup/rollup-win32-x64-msvc": { | ||||||
|       "version": "4.36.0", |       "version": "4.37.0", | ||||||
|       "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.36.0.tgz", |       "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.37.0.tgz", | ||||||
|       "integrity": "sha512-aRXd7tRZkWLqGbChgcMMDEHjOKudo1kChb1Jt1IfR8cY/KIpgNviLeJy5FUb9IpSuQj8dU2fAYNMPW/hLKOSTw==", |       "integrity": "sha512-LWbXUBwn/bcLx2sSsqy7pK5o+Nr+VCoRoAohfJ5C/aBio9nfJmGQqHAhU6pwxV/RmyTk5AqdySma7uwWGlmeuA==", | ||||||
|       "cpu": [ |       "cpu": [ | ||||||
|         "x64" |         "x64" | ||||||
|       ], |       ], | ||||||
| @@ -4944,9 +4958,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/rollup": { |     "node_modules/rollup": { | ||||||
|       "version": "4.36.0", |       "version": "4.37.0", | ||||||
|       "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.36.0.tgz", |       "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.37.0.tgz", | ||||||
|       "integrity": "sha512-zwATAXNQxUcd40zgtQG0ZafcRK4g004WtEl7kbuhTWPvf07PsfohXl39jVUvPF7jvNAIkKPQ2XrsDlWuxBd++Q==", |       "integrity": "sha512-iAtQy/L4QFU+rTJ1YUjXqJOJzuwEghqWzCEYD2FEghT7Gsy1VdABntrO4CLopA5IkflTyqNiLNwPcOJ3S7UKLg==", | ||||||
|       "dev": true, |       "dev": true, | ||||||
|       "license": "MIT", |       "license": "MIT", | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
| @@ -4960,25 +4974,26 @@ | |||||||
|         "npm": ">=8.0.0" |         "npm": ">=8.0.0" | ||||||
|       }, |       }, | ||||||
|       "optionalDependencies": { |       "optionalDependencies": { | ||||||
|         "@rollup/rollup-android-arm-eabi": "4.36.0", |         "@rollup/rollup-android-arm-eabi": "4.37.0", | ||||||
|         "@rollup/rollup-android-arm64": "4.36.0", |         "@rollup/rollup-android-arm64": "4.37.0", | ||||||
|         "@rollup/rollup-darwin-arm64": "4.36.0", |         "@rollup/rollup-darwin-arm64": "4.37.0", | ||||||
|         "@rollup/rollup-darwin-x64": "4.36.0", |         "@rollup/rollup-darwin-x64": "4.37.0", | ||||||
|         "@rollup/rollup-freebsd-arm64": "4.36.0", |         "@rollup/rollup-freebsd-arm64": "4.37.0", | ||||||
|         "@rollup/rollup-freebsd-x64": "4.36.0", |         "@rollup/rollup-freebsd-x64": "4.37.0", | ||||||
|         "@rollup/rollup-linux-arm-gnueabihf": "4.36.0", |         "@rollup/rollup-linux-arm-gnueabihf": "4.37.0", | ||||||
|         "@rollup/rollup-linux-arm-musleabihf": "4.36.0", |         "@rollup/rollup-linux-arm-musleabihf": "4.37.0", | ||||||
|         "@rollup/rollup-linux-arm64-gnu": "4.36.0", |         "@rollup/rollup-linux-arm64-gnu": "4.37.0", | ||||||
|         "@rollup/rollup-linux-arm64-musl": "4.36.0", |         "@rollup/rollup-linux-arm64-musl": "4.37.0", | ||||||
|         "@rollup/rollup-linux-loongarch64-gnu": "4.36.0", |         "@rollup/rollup-linux-loongarch64-gnu": "4.37.0", | ||||||
|         "@rollup/rollup-linux-powerpc64le-gnu": "4.36.0", |         "@rollup/rollup-linux-powerpc64le-gnu": "4.37.0", | ||||||
|         "@rollup/rollup-linux-riscv64-gnu": "4.36.0", |         "@rollup/rollup-linux-riscv64-gnu": "4.37.0", | ||||||
|         "@rollup/rollup-linux-s390x-gnu": "4.36.0", |         "@rollup/rollup-linux-riscv64-musl": "4.37.0", | ||||||
|         "@rollup/rollup-linux-x64-gnu": "4.36.0", |         "@rollup/rollup-linux-s390x-gnu": "4.37.0", | ||||||
|         "@rollup/rollup-linux-x64-musl": "4.36.0", |         "@rollup/rollup-linux-x64-gnu": "4.37.0", | ||||||
|         "@rollup/rollup-win32-arm64-msvc": "4.36.0", |         "@rollup/rollup-linux-x64-musl": "4.37.0", | ||||||
|         "@rollup/rollup-win32-ia32-msvc": "4.36.0", |         "@rollup/rollup-win32-arm64-msvc": "4.37.0", | ||||||
|         "@rollup/rollup-win32-x64-msvc": "4.36.0", |         "@rollup/rollup-win32-ia32-msvc": "4.37.0", | ||||||
|  |         "@rollup/rollup-win32-x64-msvc": "4.37.0", | ||||||
|         "fsevents": "~2.3.2" |         "fsevents": "~2.3.2" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|   | |||||||
| @@ -76,6 +76,8 @@ | |||||||
|           the <code>#monthPattern</code> attribute, much like <code>#datePattern</code>. |           the <code>#monthPattern</code> attribute, much like <code>#datePattern</code>. | ||||||
|           The options are:</p> |           The options are:</p> | ||||||
|         <ul> |         <ul> | ||||||
|  |           <li><code>{isoMonth}</code> results in an ISO 8061 formatted month (e.g. | ||||||
|  |             "2025-03" for March 2025)</li> | ||||||
|           <li><code>{monthNumberPadded}</code> results in a number like <code>09</code> for |           <li><code>{monthNumberPadded}</code> results in a number like <code>09</code> for | ||||||
|             September, and <code>11</code> for November</li> |             September, and <code>11</code> for November</li> | ||||||
|           <li><code>{month}</code> results in the full month name (e.g. <code>September</code> or <code>October</code>)</li> |           <li><code>{month}</code> results in the full month name (e.g. <code>September</code> or <code>October</code>)</li> | ||||||
|   | |||||||
| @@ -130,7 +130,7 @@ export default class MobileLayout { | |||||||
|                     .id("mobile-rest-container") |                     .id("mobile-rest-container") | ||||||
|                     .child( |                     .child( | ||||||
|                         new SidebarContainer("tree", "column") |                         new SidebarContainer("tree", "column") | ||||||
|                             .class("d-sm-flex d-md-flex d-lg-flex d-xl-flex col-12 col-sm-5 col-md-4 col-lg-3 col-xl-3") |                             .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") |                             .id("mobile-sidebar-wrapper") | ||||||
|                             .css("max-height", "100%") |                             .css("max-height", "100%") | ||||||
|                             .css("padding-left", "0") |                             .css("padding-left", "0") | ||||||
| @@ -142,10 +142,6 @@ export default class MobileLayout { | |||||||
|                         new ScreenContainer("detail", "column") |                         new ScreenContainer("detail", "column") | ||||||
|                             .id("detail-container") |                             .id("detail-container") | ||||||
|                             .class("d-sm-flex d-md-flex d-lg-flex d-xl-flex col-12 col-sm-7 col-md-8 col-lg-9") |                             .class("d-sm-flex d-md-flex d-lg-flex d-xl-flex col-12 col-sm-7 col-md-8 col-lg-9") | ||||||
|                             .css("padding-left", "0") |  | ||||||
|                             .css("padding-right", "0") |  | ||||||
|                             .css("max-height", "100%") |  | ||||||
|                             .css("position", "relative") |  | ||||||
|                             .child( |                             .child( | ||||||
|                                 new FlexContainer("row") |                                 new FlexContainer("row") | ||||||
|                                     .contentSized() |                                     .contentSized() | ||||||
|   | |||||||
| @@ -55,4 +55,8 @@ describe("Linter", () => { | |||||||
|         expect(await lint(`module.exports("Hi");`, "application/javascript;env=backend")).toStrictEqual([]); |         expect(await lint(`module.exports("Hi");`, "application/javascript;env=backend")).toStrictEqual([]); | ||||||
|         expect(await lint(`module.exports("Hi");`, "application/javascript;env=frontend")).toStrictEqual([]); |         expect(await lint(`module.exports("Hi");`, "application/javascript;env=frontend")).toStrictEqual([]); | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|  |     it("ignores TypeScript file", async () => { | ||||||
|  |         expect(await lint("export async function lint(code: string, mimeType: string) {}", "text/typescript-jsx")).toStrictEqual([]); | ||||||
|  |     }); | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -10,6 +10,12 @@ export async function lint(code: string, mimeType: string) { | |||||||
|         module: "readonly" |         module: "readonly" | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|  |     // Unsupported languages | ||||||
|  |     if (mimeType.startsWith("text/typescript")) { | ||||||
|  |         return []; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     // Custom globals | ||||||
|     if (mimeType === "application/javascript;env=frontend") { |     if (mimeType === "application/javascript;env=frontend") { | ||||||
|         globals = { ...globals, ...globalDefinitions.jquery }; |         globals = { ...globals, ...globalDefinitions.jquery }; | ||||||
|     } else if (mimeType === "application/javascript;env=backend") { |     } else if (mimeType === "application/javascript;env=backend") { | ||||||
|   | |||||||
| @@ -10,6 +10,17 @@ function reloadFrontendApp(reason?: string) { | |||||||
|     window.location.reload(); |     window.location.reload(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | function restartDesktopApp() { | ||||||
|  |     if (!isElectron()) { | ||||||
|  |         reloadFrontendApp(); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     const app = dynamicRequire("@electron/remote").app; | ||||||
|  |     app.relaunch(); | ||||||
|  |     app.exit(); | ||||||
|  | } | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Triggers the system tray to update its menu items, i.e. after a change in dynamic content such as bookmarks or recent notes. |  * Triggers the system tray to update its menu items, i.e. after a change in dynamic content such as bookmarks or recent notes. | ||||||
|  * |  * | ||||||
| @@ -739,6 +750,7 @@ function isLaunchBarConfig(noteId: string) { | |||||||
|  |  | ||||||
| export default { | export default { | ||||||
|     reloadFrontendApp, |     reloadFrontendApp, | ||||||
|  |     restartDesktopApp, | ||||||
|     reloadTray, |     reloadTray, | ||||||
|     parseDate, |     parseDate, | ||||||
|     getMonthsInDateRange, |     getMonthsInDateRange, | ||||||
|   | |||||||
| @@ -206,7 +206,8 @@ export class TypedBasicWidget<T extends TypedComponent<any>> extends TypedCompon | |||||||
|     doRender() {} |     doRender() {} | ||||||
|  |  | ||||||
|     toggleInt(show: boolean | null | undefined) { |     toggleInt(show: boolean | null | undefined) { | ||||||
|         this.$widget.toggleClass("hidden-int", !show); |         this.$widget.toggleClass("hidden-int", !show) | ||||||
|  |                     .toggleClass("visible", !!show); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     isHiddenInt() { |     isHiddenInt() { | ||||||
| @@ -214,7 +215,8 @@ export class TypedBasicWidget<T extends TypedComponent<any>> extends TypedCompon | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     toggleExt(show: boolean) { |     toggleExt(show: boolean) { | ||||||
|         this.$widget.toggleClass("hidden-ext", !show); |         this.$widget.toggleClass("hidden-ext", !show) | ||||||
|  |                     .toggleClass("visible", !!show); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     isHiddenExt() { |     isHiddenExt() { | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ export default class ShowTocWidgetButton extends OnClickButtonWidget { | |||||||
|     constructor() { |     constructor() { | ||||||
|         super(); |         super(); | ||||||
|  |  | ||||||
|         this.icon("bx-spreadsheet bx-rotate-180") |         this.icon("bx-tn-toc") | ||||||
|             .title(t("show_toc_widget_button.show_toc")) |             .title(t("show_toc_widget_button.show_toc")) | ||||||
|             .titlePlacement("bottom") |             .titlePlacement("bottom") | ||||||
|             .onClick(() => { |             .onClick(() => { | ||||||
|   | |||||||
| @@ -3,6 +3,14 @@ import { t } from "../../services/i18n.js"; | |||||||
| import type FNote from "../../entities/fnote.js"; | import type FNote from "../../entities/fnote.js"; | ||||||
| import type BasicWidget from "../basic_widget.js"; | import type BasicWidget from "../basic_widget.js"; | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Note: | ||||||
|  |  * | ||||||
|  |  * For floating button widgets that require content to overflow, the has-overflow CSS class should | ||||||
|  |  * be applied to the root element of the widget. Additionally, this root element may need to | ||||||
|  |  * properly handle rounded corners, as defined by the --border-radius CSS variable. | ||||||
|  |  */ | ||||||
|  |  | ||||||
| const TPL = ` | const TPL = ` | ||||||
| <div class="floating-buttons no-print"> | <div class="floating-buttons no-print"> | ||||||
|     <style> |     <style> | ||||||
| @@ -39,10 +47,18 @@ const TPL = ` | |||||||
|             top: 70px; |             top: 70px; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         .type-canvas .floating-buttons-children > * { | ||||||
|  |             --border-radius: 0; /* Overridden by themes */ | ||||||
|  |         } | ||||||
|  |  | ||||||
|         .floating-buttons-children > *:not(.hidden-int):not(.no-content-hidden) { |         .floating-buttons-children > *:not(.hidden-int):not(.no-content-hidden) { | ||||||
|             margin: 2px; |             margin: 2px; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         .floating-buttons-children > *:not(.has-overflow) { | ||||||
|  |             overflow: hidden; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         .floating-buttons-children > button, .floating-buttons-children .floating-button { |         .floating-buttons-children > button, .floating-buttons-children .floating-button { | ||||||
|             font-size: 150%; |             font-size: 150%; | ||||||
|             padding: 5px 10px 4px 10px; |             padding: 5px 10px 4px 10px; | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ const TPL = ` | |||||||
|  |  | ||||||
| export default class PngExportButton extends NoteContextAwareWidget { | export default class PngExportButton extends NoteContextAwareWidget { | ||||||
|     isEnabled() { |     isEnabled() { | ||||||
|         return super.isEnabled() && ["mermaid"].includes(this.note?.type ?? "") && this.note?.isContentAvailable() && this.noteContext?.viewScope?.viewMode === "default"; |         return super.isEnabled() && ["mermaid", "mindMap"].includes(this.note?.type ?? "") && this.note?.isContentAvailable() && this.noteContext?.viewScope?.viewMode === "default"; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     doRender() { |     doRender() { | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ const TPL = ` | |||||||
| <button type="button" | <button type="button" | ||||||
|         class="export-svg-button" |         class="export-svg-button" | ||||||
|         title="${t("svg_export_button.button_title")}"> |         title="${t("svg_export_button.button_title")}"> | ||||||
|         <span class="bx bx-export"></span> |         <span class="bx bxs-file-image"></span> | ||||||
| </button> | </button> | ||||||
| `; | `; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ import froca from "../../services/froca.js"; | |||||||
| import type FNote from "../../entities/fnote.js"; | import type FNote from "../../entities/fnote.js"; | ||||||
|  |  | ||||||
| const TPL = ` | const TPL = ` | ||||||
| <div class="backlinks-widget"> | <div class="backlinks-widget has-overflow"> | ||||||
|     <style> |     <style> | ||||||
|         .backlinks-widget { |         .backlinks-widget { | ||||||
|             position: relative; |             position: relative; | ||||||
| @@ -61,7 +61,7 @@ const TPL = ` | |||||||
|         <span class="backlinks-count"></span> |         <span class="backlinks-count"></span> | ||||||
|     </div> |     </div> | ||||||
|  |  | ||||||
|     <div class="backlinks-items" style="display: none;"></div> |     <div class="backlinks-items dropdown-menu" style="display: none;"></div> | ||||||
| </div> | </div> | ||||||
| `; | `; | ||||||
|  |  | ||||||
| @@ -121,7 +121,8 @@ export default class BacklinksWidget extends NoteContextAwareWidget { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     toggle(show: boolean) { |     toggle(show: boolean) { | ||||||
|         this.$widget.toggleClass("hidden-no-content", !show); |         this.$widget.toggleClass("hidden-no-content", !show) | ||||||
|  |                     .toggleClass("visible", !!show); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     clearItems() { |     clearItems() { | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ import server from "../services/server.js"; | |||||||
| import type FNote from "../entities/fnote.js"; | import type FNote from "../entities/fnote.js"; | ||||||
| import type { EventData } from "../components/app_context.js"; | import type { EventData } from "../components/app_context.js"; | ||||||
| import type { Icon } from "./icon_list.js"; | import type { Icon } from "./icon_list.js"; | ||||||
|  | import { Dropdown } from "bootstrap"; | ||||||
|  |  | ||||||
| const TPL = ` | const TPL = ` | ||||||
| <div class="note-icon-widget dropdown"> | <div class="note-icon-widget dropdown"> | ||||||
| @@ -88,6 +89,7 @@ interface IconToCountCache { | |||||||
|  |  | ||||||
| export default class NoteIconWidget extends NoteContextAwareWidget { | export default class NoteIconWidget extends NoteContextAwareWidget { | ||||||
|  |  | ||||||
|  |     private dropdown!: bootstrap.Dropdown; | ||||||
|     private $icon!: JQuery<HTMLElement>; |     private $icon!: JQuery<HTMLElement>; | ||||||
|     private $iconList!: JQuery<HTMLElement>; |     private $iconList!: JQuery<HTMLElement>; | ||||||
|     private $iconCategory!: JQuery<HTMLElement>; |     private $iconCategory!: JQuery<HTMLElement>; | ||||||
| @@ -96,6 +98,8 @@ export default class NoteIconWidget extends NoteContextAwareWidget { | |||||||
|  |  | ||||||
|     doRender() { |     doRender() { | ||||||
|         this.$widget = $(TPL); |         this.$widget = $(TPL); | ||||||
|  |         this.dropdown = Dropdown.getOrCreateInstance(this.$widget.find("[data-bs-toggle='dropdown']")[0]); | ||||||
|  |  | ||||||
|         this.$icon = this.$widget.find("button.note-icon"); |         this.$icon = this.$widget.find("button.note-icon"); | ||||||
|         this.$iconList = this.$widget.find(".icon-list"); |         this.$iconList = this.$widget.find(".icon-list"); | ||||||
|         this.$iconList.on("click", "span", async (e) => { |         this.$iconList.on("click", "span", async (e) => { | ||||||
| @@ -130,6 +134,8 @@ export default class NoteIconWidget extends NoteContextAwareWidget { | |||||||
|  |  | ||||||
|     async refreshWithNote(note: FNote) { |     async refreshWithNote(note: FNote) { | ||||||
|         this.$icon.removeClass().addClass(`${note.getIcon()} note-icon`); |         this.$icon.removeClass().addClass(`${note.getIcon()} note-icon`); | ||||||
|  |         this.$icon.prop("disabled", !!(this.noteContext?.viewScope?.viewMode !== "default")); | ||||||
|  |         this.dropdown.hide(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) { |     async entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) { | ||||||
|   | |||||||
| @@ -165,8 +165,7 @@ export default abstract class AbstractSplitTypeWidget extends TypeWidget { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     cleanup(): void { |     cleanup(): void { | ||||||
|         this.splitInstance?.destroy(); |         this.#destroyResizer(); | ||||||
|         this.splitInstance = undefined; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async doRefresh(note: FNote | null | undefined) { |     async doRefresh(note: FNote | null | undefined) { | ||||||
| @@ -189,18 +188,20 @@ export default abstract class AbstractSplitTypeWidget extends TypeWidget { | |||||||
|  |  | ||||||
|         // Vertical vs horizontal layout |         // Vertical vs horizontal layout | ||||||
|         const layoutOrientation = (!utils.isMobile() ? options.get("splitEditorOrientation") ?? "horizontal" : "vertical"); |         const layoutOrientation = (!utils.isMobile() ? options.get("splitEditorOrientation") ?? "horizontal" : "vertical"); | ||||||
|         if (this.layoutOrientation === layoutOrientation && this.isReadOnly === isReadOnly) { |         if (this.layoutOrientation !== layoutOrientation || this.isReadOnly !== isReadOnly) { | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|             this.$widget |             this.$widget | ||||||
|                 .toggleClass("split-horizontal", !isReadOnly && layoutOrientation === "horizontal") |                 .toggleClass("split-horizontal", !isReadOnly && layoutOrientation === "horizontal") | ||||||
|                 .toggleClass("split-vertical", !isReadOnly && layoutOrientation === "vertical") |                 .toggleClass("split-vertical", !isReadOnly && layoutOrientation === "vertical") | ||||||
|                 .toggleClass("split-read-only", isReadOnly); |                 .toggleClass("split-read-only", isReadOnly); | ||||||
|             this.layoutOrientation = layoutOrientation as ("horizontal" | "vertical"); |             this.layoutOrientation = layoutOrientation as ("horizontal" | "vertical"); | ||||||
|             this.isReadOnly = isReadOnly; |             this.isReadOnly = isReadOnly; | ||||||
|  |             this.#destroyResizer(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (!this.splitInstance) { | ||||||
|             this.#setupResizer(); |             this.#setupResizer(); | ||||||
|         } |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     #setupResizer() { |     #setupResizer() { | ||||||
|         if (!utils.isDesktop()) { |         if (!utils.isDesktop()) { | ||||||
| @@ -226,6 +227,11 @@ export default abstract class AbstractSplitTypeWidget extends TypeWidget { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     #destroyResizer() { | ||||||
|  |         this.splitInstance?.destroy(); | ||||||
|  |         this.splitInstance = undefined; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Called upon when the split between the preview and content pane is initialized. Can be used to add additional listeners if needed. |      * Called upon when the split between the preview and content pane is initialized. Can be used to add additional listeners if needed. | ||||||
|      */ |      */ | ||||||
|   | |||||||
| @@ -276,4 +276,14 @@ export default class MindMapWidget extends TypeWidget { | |||||||
|         const svg = await this.renderSvg(); |         const svg = await this.renderSvg(); | ||||||
|         utils.downloadSvg(this.note.title, svg); |         utils.downloadSvg(this.note.title, svg); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     async exportPngEvent({ ntxId }: EventData<"exportPng">) { | ||||||
|  |         if (!this.isNoteContext(ntxId) || this.note?.type !== "mindMap") { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         const svg = await this.renderSvg(); | ||||||
|  |         utils.downloadSvgAsPng(this.note.title, svg); | ||||||
|  |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -61,11 +61,7 @@ export default class ElectronIntegrationOptions extends OptionsWidget { | |||||||
|         this.$backgroundEffects.on("change", () => this.updateCheckboxOption("backgroundEffects", this.$backgroundEffects)); |         this.$backgroundEffects.on("change", () => this.updateCheckboxOption("backgroundEffects", this.$backgroundEffects)); | ||||||
|  |  | ||||||
|         const restartAppButton = this.$widget.find(".restart-app-button"); |         const restartAppButton = this.$widget.find(".restart-app-button"); | ||||||
|         restartAppButton.on("click", () => { |         restartAppButton.on("click", utils.restartDesktopApp); | ||||||
|             const app = utils.dynamicRequire("@electron/remote").app; |  | ||||||
|             app.relaunch(); |  | ||||||
|             app.exit(); |  | ||||||
|         }); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     isEnabled() { |     isEnabled() { | ||||||
|   | |||||||
| @@ -3,20 +3,26 @@ import server from "../../../../services/server.js"; | |||||||
| import utils from "../../../../services/utils.js"; | import utils from "../../../../services/utils.js"; | ||||||
| import { getAvailableLocales, t } from "../../../../services/i18n.js"; | import { getAvailableLocales, t } from "../../../../services/i18n.js"; | ||||||
| import type { OptionMap } from "../../../../../../services/options_interface.js"; | import type { OptionMap } from "../../../../../../services/options_interface.js"; | ||||||
|  | import type { Locale } from "../../../../../../services/i18n.js"; | ||||||
|  |  | ||||||
| const TPL = ` | const TPL = ` | ||||||
| <div class="options-section"> | <div class="options-section"> | ||||||
|     <h4>${t("i18n.title")}</h4> |     <h4>${t("i18n.title")}</h4> | ||||||
|  |  | ||||||
|     <div class="form-group row"> |     <div class="locale-options-container"> | ||||||
|         <div class="col-6"> |         <div class="option-row"> | ||||||
|             <label for="locale-select">${t("i18n.language")}</label> |             <label for="locale-select">${t("i18n.language")}</label> | ||||||
|             <select id="locale-select" class="locale-select form-select"></select> |             <select id="locale-select" class="locale-select form-select"></select> | ||||||
|         </div> |         </div> | ||||||
|  |  | ||||||
|         <div class="col-6"> |         <div class="option-row electron-only"> | ||||||
|  |             <label for="formatting-locale-select">${t("i18n.formatting-locale")}</label> | ||||||
|  |             <select id="formatting-locale-select" class="formatting-locale-select form-select"></select> | ||||||
|  |         </div> | ||||||
|  |  | ||||||
|  |         <div class="option-row"> | ||||||
|             <label id="first-day-of-week-label">${t("i18n.first-day-of-the-week")}</label> |             <label id="first-day-of-week-label">${t("i18n.first-day-of-the-week")}</label> | ||||||
|             <div role="group" aria-labelledby="first-day-of-week-label" style="margin-top: .33em;"> |             <div role="group" aria-labelledby="first-day-of-week-label"> | ||||||
|                 <label class="tn-radio"> |                 <label class="tn-radio"> | ||||||
|                     <input name="first-day-of-week" type="radio" value="0" /> |                     <input name="first-day-of-week" type="radio" value="0" /> | ||||||
|                     ${t("i18n.sunday")} |                     ${t("i18n.sunday")} | ||||||
| @@ -28,13 +34,44 @@ const TPL = ` | |||||||
|                 </label> |                 </label> | ||||||
|             </div> |             </div> | ||||||
|         </div> |         </div> | ||||||
|  |  | ||||||
|  |         <div class="option-row centered"> | ||||||
|  |             <button class="btn btn-secondary btn-micro restart-app-button">${t("electron_integration.restart-app-button")}</button> | ||||||
|         </div> |         </div> | ||||||
|  |     </div> | ||||||
|  |  | ||||||
|  |     <style> | ||||||
|  |         .locale-options-container .option-row { | ||||||
|  |             border-bottom: 1px solid var(--main-border-color); | ||||||
|  |             display: flex; | ||||||
|  |             align-items: center; | ||||||
|  |             padding: 0.5em 0; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         .locale-options-container .option-row > label { | ||||||
|  |             width: 40%; | ||||||
|  |             margin-bottom: 0 !important; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         .locale-options-container .option-row > select { | ||||||
|  |             width: 60%; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         .locale-options-container .option-row:last-of-type { | ||||||
|  |             border-bottom: unset; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         .locale-options-container .option-row.centered { | ||||||
|  |             justify-content: center; | ||||||
|  |         } | ||||||
|  |     </style> | ||||||
| </div> | </div> | ||||||
| `; | `; | ||||||
|  |  | ||||||
| export default class LocalizationOptions extends OptionsWidget { | export default class LocalizationOptions extends OptionsWidget { | ||||||
|  |  | ||||||
|     private $localeSelect!: JQuery<HTMLElement>; |     private $localeSelect!: JQuery<HTMLElement>; | ||||||
|  |     private $formattingLocaleSelect!: JQuery<HTMLElement>; | ||||||
|  |  | ||||||
|     doRender() { |     doRender() { | ||||||
|         this.$widget = $(TPL); |         this.$widget = $(TPL); | ||||||
| @@ -43,24 +80,44 @@ export default class LocalizationOptions extends OptionsWidget { | |||||||
|         this.$localeSelect.on("change", async () => { |         this.$localeSelect.on("change", async () => { | ||||||
|             const newLocale = this.$localeSelect.val(); |             const newLocale = this.$localeSelect.val(); | ||||||
|             await server.put(`options/locale/${newLocale}`); |             await server.put(`options/locale/${newLocale}`); | ||||||
|             utils.reloadFrontendApp("locale change"); |         }); | ||||||
|  |  | ||||||
|  |         this.$formattingLocaleSelect = this.$widget.find(".formatting-locale-select"); | ||||||
|  |         this.$formattingLocaleSelect.on("change", async () => { | ||||||
|  |             const newLocale = this.$formattingLocaleSelect.val(); | ||||||
|  |             await server.put(`options/formattingLocale/${newLocale}`); | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|         this.$widget.find(`input[name="first-day-of-week"]`).on("change", () => { |         this.$widget.find(`input[name="first-day-of-week"]`).on("change", () => { | ||||||
|             const firstDayOfWeek = String(this.$widget.find(`input[name="first-day-of-week"]:checked`).val()); |             const firstDayOfWeek = String(this.$widget.find(`input[name="first-day-of-week"]:checked`).val()); | ||||||
|             this.updateOption("firstDayOfWeek", firstDayOfWeek); |             this.updateOption("firstDayOfWeek", firstDayOfWeek); | ||||||
|         }); |         }); | ||||||
|  |         this.$widget.find(".restart-app-button").on("click", utils.restartDesktopApp); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async optionsLoaded(options: OptionMap) { |     async optionsLoaded(options: OptionMap) { | ||||||
|         const availableLocales = getAvailableLocales().filter(l => !l.contentOnly); |         const allLocales = getAvailableLocales(); | ||||||
|         this.$localeSelect.empty(); |  | ||||||
|  |  | ||||||
|         for (const locale of availableLocales) { |         function buildLocaleItem(locale: Locale, value: string) { | ||||||
|             this.$localeSelect.append($("<option>").attr("value", locale.id).text(locale.name)); |             return $("<option>") | ||||||
|  |                 .attr("value", value) | ||||||
|  |                 .text(locale.name) | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         // Build list of UI locales. | ||||||
|  |         this.$localeSelect.empty(); | ||||||
|  |         for (const locale of allLocales.filter(l => !l.contentOnly)) { | ||||||
|  |             this.$localeSelect.append(buildLocaleItem(locale, locale.id)); | ||||||
|  |         } | ||||||
|         this.$localeSelect.val(options.locale); |         this.$localeSelect.val(options.locale); | ||||||
|  |  | ||||||
|  |         // Build list of Electron locales. | ||||||
|  |         this.$formattingLocaleSelect.empty(); | ||||||
|  |         for (const locale of allLocales.filter(l => l.electronLocale)) { | ||||||
|  |             this.$formattingLocaleSelect.append(buildLocaleItem(locale, locale.electronLocale as string)); | ||||||
|  |         } | ||||||
|  |         this.$formattingLocaleSelect.val(options.formattingLocale); | ||||||
|  |  | ||||||
|         this.$widget.find(`input[name="first-day-of-week"][value="${options.firstDayOfWeek}"]`) |         this.$widget.find(`input[name="first-day-of-week"][value="${options.firstDayOfWeek}"]`) | ||||||
|                     .prop("checked", "true"); |                     .prop("checked", "true"); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -49,7 +49,8 @@ body { | |||||||
|     --tab-bar-height: 40px; |     --tab-bar-height: 40px; | ||||||
| } | } | ||||||
|  |  | ||||||
| body.mobile .desktop-only { | body.mobile .desktop-only, | ||||||
|  | body:not(.electron) .electron-only { | ||||||
|     display: none !important; |     display: none !important; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -579,11 +580,7 @@ table.promoted-attributes-in-tooltip th { | |||||||
|  |  | ||||||
| .tooltip { | .tooltip { | ||||||
|     font-size: var(--main-font-size) !important; |     font-size: var(--main-font-size) !important; | ||||||
|     /* |  | ||||||
|         TODO: Investigate the purpose of this |  | ||||||
|     z-index: calc(var(--ck-z-panel) - 1) !important; |     z-index: calc(var(--ck-z-panel) - 1) !important; | ||||||
|     */ |  | ||||||
|     z-index: 3000; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| .tooltip-trigger { | .tooltip-trigger { | ||||||
| @@ -1315,6 +1312,12 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu { | |||||||
| } | } | ||||||
|  |  | ||||||
| /* Mobile, phone mode */ | /* Mobile, phone mode */ | ||||||
|  |  | ||||||
|  | #detail-container { | ||||||
|  |     max-height: 100%; | ||||||
|  |     position: relative; | ||||||
|  | } | ||||||
|  |  | ||||||
| @media (max-width: 991px) { | @media (max-width: 991px) { | ||||||
|     body.mobile #launcher-pane .dropdown.global-menu > .dropdown-menu.show, |     body.mobile #launcher-pane .dropdown.global-menu > .dropdown-menu.show, | ||||||
|     body.mobile #launcher-container .dropdown > .dropdown-menu.show { |     body.mobile #launcher-container .dropdown > .dropdown-menu.show { | ||||||
| @@ -1354,6 +1357,10 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu { | |||||||
|         z-index: 2000; |         z-index: 2000; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     #detail-container { | ||||||
|  |         width: 100%; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     #mobile-sidebar-container.show #mobile-sidebar-wrapper { |     #mobile-sidebar-container.show #mobile-sidebar-wrapper { | ||||||
|         transform: translateX(0); |         transform: translateX(0); | ||||||
|     } |     } | ||||||
| @@ -1787,3 +1794,10 @@ footer.file-footer button { | |||||||
|     font-size: 130%; |     font-size: 130%; | ||||||
|     padding: 1px 10px 1px 10px; |     padding: 1px 10px 1px 10px; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* Customized icons */ | ||||||
|  |  | ||||||
|  | .bx-tn-toc::before { | ||||||
|  |     content: "\ec24"; | ||||||
|  |     transform: rotate(180deg); | ||||||
|  | } | ||||||
| @@ -1305,7 +1305,7 @@ div.promoted-attribute-cell .multiplicity:has(span) { | |||||||
|  /* Floating buttons container */ |  /* Floating buttons container */ | ||||||
| div#center-pane .floating-buttons-children { | div#center-pane .floating-buttons-children { | ||||||
|     opacity: 1; |     opacity: 1; | ||||||
|     overflow: hidden; |     min-height: var(--floating-button-height); | ||||||
|     transform-origin: right; |     transform-origin: right; | ||||||
|     box-shadow: 1px 1px 1px var(--floating-button-shadow-color); |     box-shadow: 1px 1px 1px var(--floating-button-shadow-color); | ||||||
|     background: var(--floating-button-background-color); |     background: var(--floating-button-background-color); | ||||||
| @@ -1325,6 +1325,10 @@ div#center-pane .floating-buttons-children { | |||||||
|  |  | ||||||
| /* Floating buttons */ | /* Floating buttons */ | ||||||
|  |  | ||||||
|  | .floating-buttons-children { | ||||||
|  |     --border-radius-size: 6px; | ||||||
|  | } | ||||||
|  |  | ||||||
| .floating-buttons-children > * { | .floating-buttons-children > * { | ||||||
|     margin: 0 !important; |     margin: 0 !important; | ||||||
| } | } | ||||||
| @@ -1352,6 +1356,12 @@ div.floating-buttons-children .floating-button:active { | |||||||
|     font-size: calc(var(--floating-button-icon-size) * 0.85); |     font-size: calc(var(--floating-button-icon-size) * 0.85); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* The first visible floating button */ | ||||||
|  | div.floating-buttons-children > *:nth-child(1 of .visible) { | ||||||
|  |     --border-radius: var(--border-radius-size) 0 0 var(--border-radius-size); | ||||||
|  |     border-radius: var(--border-radius); | ||||||
|  | } | ||||||
|  |  | ||||||
|  /* "Show / hide floating buttons" buttons */ |  /* "Show / hide floating buttons" buttons */ | ||||||
|  |  | ||||||
|  @keyframes floating-buttons-show-hide-button-animation { |  @keyframes floating-buttons-show-hide-button-animation { | ||||||
| @@ -1409,8 +1419,9 @@ div.floating-buttons-children:not(.temporarily-hidden) .close-floating-buttons-b | |||||||
|     animation: floating-buttons-show-hide-button-animation 400ms ease-out; |     animation: floating-buttons-show-hide-button-animation 400ms ease-out; | ||||||
| } | } | ||||||
|  |  | ||||||
| div.floating-buttons-children .close-floating-buttons-button { | div.floating-buttons-children .close-floating-buttons { | ||||||
|     border-radius: 0; |     border-radius: 0 var(--border-radius-size) var(--border-radius-size) 0; | ||||||
|  |     overflow: hidden; | ||||||
| } | } | ||||||
|  |  | ||||||
| div.floating-buttons-children .close-floating-buttons { | div.floating-buttons-children .close-floating-buttons { | ||||||
| @@ -1426,18 +1437,27 @@ div.floating-buttons-children .close-floating-buttons:has(.close-floating-button | |||||||
|  |  | ||||||
| /* Backlink count */ | /* Backlink count */ | ||||||
|  |  | ||||||
| .floating-buttons .backlinks-ticker { | .backlinks-widget .backlinks-ticker { | ||||||
|     height: 100%; |     height: 100%; | ||||||
|     padding: 0 10px; |     padding: 0 10px; | ||||||
|     border-radius: 0; |     border-radius: var(--border-radius); | ||||||
|     background: transparent; |     background: transparent; | ||||||
|     user-select: none; |     user-select: none; | ||||||
| } | } | ||||||
|  |  | ||||||
| .floating-buttons .backlinks-ticker:has(.backlinks-count:hover) { | .backlinks-widget .backlinks-ticker:hover { | ||||||
|     background: var(--floating-button-hover-background); |     background: var(--floating-button-hover-background); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | .backlinks-widget .backlinks-items { | ||||||
|  |     --menu-padding-size: 20px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* TODO: Restyle the path */ | ||||||
|  | .backlinks-widget .backlinks-items .note-path { | ||||||
|  |     padding-inline-start: 8px; | ||||||
|  | } | ||||||
|  |  | ||||||
| /* Copy image reference */ | /* Copy image reference */ | ||||||
|  |  | ||||||
| .floating-buttons .copy-image-reference-button .hidden-image-copy { | .floating-buttons .copy-image-reference-button .hidden-image-copy { | ||||||
| @@ -1452,14 +1472,6 @@ div.floating-buttons-children .close-floating-buttons:has(.close-floating-button | |||||||
|     gap: 0; |     gap: 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Individual icon position / size corrections */ |  | ||||||
|  |  | ||||||
| /* Table of contents */ |  | ||||||
| .floating-buttons .bx-spreadsheet::before { |  | ||||||
|     /* Note: since the icon is rotated, a positive top margin will actually shift the icon upwards */ |  | ||||||
|     margin-top: .1em; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* The highlight animation */ | /* The highlight animation */ | ||||||
|  |  | ||||||
| @keyframes floating-button-highlight { | @keyframes floating-button-highlight { | ||||||
|   | |||||||
| @@ -1242,7 +1242,8 @@ | |||||||
|     "language": "Language", |     "language": "Language", | ||||||
|     "first-day-of-the-week": "First day of the week", |     "first-day-of-the-week": "First day of the week", | ||||||
|     "sunday": "Sunday", |     "sunday": "Sunday", | ||||||
|     "monday": "Monday" |     "monday": "Monday", | ||||||
|  |     "formatting-locale": "Date & number format" | ||||||
|   }, |   }, | ||||||
|   "backup": { |   "backup": { | ||||||
|     "automatic_backup": "Automatic backup", |     "automatic_backup": "Automatic backup", | ||||||
|   | |||||||
| @@ -744,7 +744,8 @@ | |||||||
|   "basic_properties": { |   "basic_properties": { | ||||||
|     "note_type": "Tipo de nota", |     "note_type": "Tipo de nota", | ||||||
|     "editable": "Editable", |     "editable": "Editable", | ||||||
|     "basic_properties": "Propiedades básicas" |     "basic_properties": "Propiedades básicas", | ||||||
|  |     "language": "Idioma" | ||||||
|   }, |   }, | ||||||
|   "book_properties": { |   "book_properties": { | ||||||
|     "view_type": "Tipo de vista", |     "view_type": "Tipo de vista", | ||||||
| @@ -1090,6 +1091,7 @@ | |||||||
|     "title": "Ancho del contenido", |     "title": "Ancho del contenido", | ||||||
|     "default_description": "Trilium limita de forma predeterminada el ancho máximo del contenido para mejorar la legibilidad de ventanas maximizadas en pantallas anchas.", |     "default_description": "Trilium limita de forma predeterminada el ancho máximo del contenido para mejorar la legibilidad de ventanas maximizadas en pantallas anchas.", | ||||||
|     "max_width_label": "Ancho máximo del contenido en píxeles", |     "max_width_label": "Ancho máximo del contenido en píxeles", | ||||||
|  |     "max_width_unit": "píxeles", | ||||||
|     "apply_changes_description": "Para aplicar cambios en el ancho del contenido, haga clic en", |     "apply_changes_description": "Para aplicar cambios en el ancho del contenido, haga clic en", | ||||||
|     "reload_button": "recargar la interfaz", |     "reload_button": "recargar la interfaz", | ||||||
|     "reload_description": "cambios desde las opciones de apariencia" |     "reload_description": "cambios desde las opciones de apariencia" | ||||||
| @@ -1127,7 +1129,11 @@ | |||||||
|   "code_auto_read_only_size": { |   "code_auto_read_only_size": { | ||||||
|     "title": "Tamaño automático de solo lectura", |     "title": "Tamaño automático de solo lectura", | ||||||
|     "description": "El tamaño de nota de solo lectura automático es el tamaño después del cual las notas se mostrarán en modo de solo lectura (por razones de rendimiento).", |     "description": "El tamaño de nota de solo lectura automático es el tamaño después del cual las notas se mostrarán en modo de solo lectura (por razones de rendimiento).", | ||||||
|     "label": "Tamaño automático de solo lectura (notas de código)" |     "label": "Tamaño automático de solo lectura (notas de código)", | ||||||
|  |     "unit": "caracteres" | ||||||
|  |   }, | ||||||
|  |   "code-editor-options": { | ||||||
|  |     "title": "Editor" | ||||||
|   }, |   }, | ||||||
|   "code_mime_types": { |   "code_mime_types": { | ||||||
|     "title": "Tipos MIME disponibles en el menú desplegable" |     "title": "Tipos MIME disponibles en el menú desplegable" | ||||||
| @@ -1146,6 +1152,7 @@ | |||||||
|     "download_images_description": "El HTML pegado puede contener referencias a imágenes en línea; Trilium encontrará esas referencias y descargará las imágenes para que estén disponibles sin conexión.", |     "download_images_description": "El HTML pegado puede contener referencias a imágenes en línea; Trilium encontrará esas referencias y descargará las imágenes para que estén disponibles sin conexión.", | ||||||
|     "enable_image_compression": "Habilitar la compresión de imágenes", |     "enable_image_compression": "Habilitar la compresión de imágenes", | ||||||
|     "max_image_dimensions": "Ancho/alto máximo de una imagen en píxeles (la imagen cambiará de tamaño si excede esta configuración).", |     "max_image_dimensions": "Ancho/alto máximo de una imagen en píxeles (la imagen cambiará de tamaño si excede esta configuración).", | ||||||
|  |     "max_image_dimensions_unit": "píxeles", | ||||||
|     "jpeg_quality_description": "Calidad JPEG (10 - peor calidad, 100 - mejor calidad, se recomienda 50 - 85)" |     "jpeg_quality_description": "Calidad JPEG (10 - peor calidad, 100 - mejor calidad, se recomienda 50 - 85)" | ||||||
|   }, |   }, | ||||||
|   "attachment_erasure_timeout": { |   "attachment_erasure_timeout": { | ||||||
| @@ -1177,6 +1184,7 @@ | |||||||
|     "note_revisions_snapshot_limit_title": "Límite de respaldos de revisiones de nota", |     "note_revisions_snapshot_limit_title": "Límite de respaldos de revisiones de nota", | ||||||
|     "note_revisions_snapshot_limit_description": "El límite de número de respaldos de revisiones de notas se refiere al número máximo de revisiones que pueden guardarse para cada nota. Donde -1 significa sin límite, 0 significa borrar todas las revisiones. Puede establecer el máximo de revisiones para una sola nota a través de la etiqueta #versioningLimit.", |     "note_revisions_snapshot_limit_description": "El límite de número de respaldos de revisiones de notas se refiere al número máximo de revisiones que pueden guardarse para cada nota. Donde -1 significa sin límite, 0 significa borrar todas las revisiones. Puede establecer el máximo de revisiones para una sola nota a través de la etiqueta #versioningLimit.", | ||||||
|     "snapshot_number_limit_label": "Número límite de respaldos de revisiones de nota:", |     "snapshot_number_limit_label": "Número límite de respaldos de revisiones de nota:", | ||||||
|  |     "snapshot_number_limit_unit": "respaldos", | ||||||
|     "erase_excess_revision_snapshots": "Eliminar el exceso de respaldos de revisiones ahora", |     "erase_excess_revision_snapshots": "Eliminar el exceso de respaldos de revisiones ahora", | ||||||
|     "erase_excess_revision_snapshots_prompt": "El exceso de respaldos de revisiones han sido eliminadas." |     "erase_excess_revision_snapshots_prompt": "El exceso de respaldos de revisiones han sido eliminadas." | ||||||
|   }, |   }, | ||||||
| @@ -1219,13 +1227,15 @@ | |||||||
|   "table_of_contents": { |   "table_of_contents": { | ||||||
|     "title": "Tabla de contenido", |     "title": "Tabla de contenido", | ||||||
|     "description": "La tabla de contenido aparecerá en las notas de texto cuando la nota tenga más de un número definido de títulos. Puede personalizar este número:", |     "description": "La tabla de contenido aparecerá en las notas de texto cuando la nota tenga más de un número definido de títulos. Puede personalizar este número:", | ||||||
|  |     "unit": "títulos", | ||||||
|     "disable_info": "También puede utilizar esta opción para desactivar la TDC (TOC) de forma efectiva estableciendo un número muy alto.", |     "disable_info": "También puede utilizar esta opción para desactivar la TDC (TOC) de forma efectiva estableciendo un número muy alto.", | ||||||
|     "shortcut_info": "Puede configurar un atajo de teclado para alternar rápidamente el panel derecho (incluido el TDC) en Opciones -> Atajos (nombre 'toggleRightPane')." |     "shortcut_info": "Puede configurar un atajo de teclado para alternar rápidamente el panel derecho (incluido el TDC) en Opciones -> Atajos (nombre 'toggleRightPane')." | ||||||
|   }, |   }, | ||||||
|   "text_auto_read_only_size": { |   "text_auto_read_only_size": { | ||||||
|     "title": "Tamaño para modo de solo lectura automático", |     "title": "Tamaño para modo de solo lectura automático", | ||||||
|     "description": "El tamaño de nota de solo lectura automático es el tamaño después del cual las notas se mostrarán en modo de solo lectura (por razones de rendimiento).", |     "description": "El tamaño de nota de solo lectura automático es el tamaño después del cual las notas se mostrarán en modo de solo lectura (por razones de rendimiento).", | ||||||
|     "label": "Tamaño para modo de solo lectura automático (notas de texto)" |     "label": "Tamaño para modo de solo lectura automático (notas de texto)", | ||||||
|  |     "unit": "caracteres" | ||||||
|   }, |   }, | ||||||
|   "i18n": { |   "i18n": { | ||||||
|     "title": "Localización", |     "title": "Localización", | ||||||
| @@ -1302,7 +1312,7 @@ | |||||||
|   "shortcuts": { |   "shortcuts": { | ||||||
|     "keyboard_shortcuts": "Atajos de teclado", |     "keyboard_shortcuts": "Atajos de teclado", | ||||||
|     "multiple_shortcuts": "Varios atajos para la misma acción se pueden separar mediante comas.", |     "multiple_shortcuts": "Varios atajos para la misma acción se pueden separar mediante comas.", | ||||||
|     "electron_documentation": "Véa <a href=\"https://www.electronjs.org/docs/latest/api/accelerator\">documentation de Electron </a> para los modificadores y códigos de tecla disponibles.", |     "electron_documentation": "Véa la <a href=\"https://www.electronjs.org/docs/latest/api/accelerator\">documentación de Electron </a> para los modificadores y códigos de tecla disponibles.", | ||||||
|     "type_text_to_filter": "Escriba texto para filtrar los accesos directos...", |     "type_text_to_filter": "Escriba texto para filtrar los accesos directos...", | ||||||
|     "action_name": "Nombre de la acción", |     "action_name": "Nombre de la acción", | ||||||
|     "shortcuts": "Atajos", |     "shortcuts": "Atajos", | ||||||
| @@ -1326,6 +1336,7 @@ | |||||||
|     "config_title": "Configuración de sincronización", |     "config_title": "Configuración de sincronización", | ||||||
|     "server_address": "Dirección de la instancia del servidor", |     "server_address": "Dirección de la instancia del servidor", | ||||||
|     "timeout": "Tiempo de espera de sincronización (milisegundos)", |     "timeout": "Tiempo de espera de sincronización (milisegundos)", | ||||||
|  |     "timeout_unit": "milisegundos", | ||||||
|     "proxy_label": "Sincronizar servidor proxy (opcional)", |     "proxy_label": "Sincronizar servidor proxy (opcional)", | ||||||
|     "note": "Nota", |     "note": "Nota", | ||||||
|     "note_description": "Si deja la configuración del proxy en blanco, se utilizará el proxy del sistema (se aplica únicamente a la compilación de escritorio/electron).", |     "note_description": "Si deja la configuración del proxy en blanco, se utilizará el proxy del sistema (se aplica únicamente a la compilación de escritorio/electron).", | ||||||
| @@ -1421,8 +1432,7 @@ | |||||||
|     "widget": "Widget", |     "widget": "Widget", | ||||||
|     "confirm-change": "No es recomendado cambiar el tipo de nota cuando el contenido de la nota no está vacío. ¿Desea continuar de cualquier manera?", |     "confirm-change": "No es recomendado cambiar el tipo de nota cuando el contenido de la nota no está vacío. ¿Desea continuar de cualquier manera?", | ||||||
|     "geo-map": "Mapa Geo", |     "geo-map": "Mapa Geo", | ||||||
|     "beta-feature": "Beta", |     "beta-feature": "Beta" | ||||||
|     "task-list": "Lista de tareas" |  | ||||||
|   }, |   }, | ||||||
|   "protect_note": { |   "protect_note": { | ||||||
|     "toggle-on": "Proteger la nota", |     "toggle-on": "Proteger la nota", | ||||||
| @@ -1679,5 +1689,27 @@ | |||||||
|       "tomorrow": "Mañana", |       "tomorrow": "Mañana", | ||||||
|       "yesterday": "Ayer" |       "yesterday": "Ayer" | ||||||
|     } |     } | ||||||
|  |   }, | ||||||
|  |   "content_widget": { | ||||||
|  |     "unknown_widget": "Widget desconocido para \"{{id}}\"." | ||||||
|  |   }, | ||||||
|  |   "note_language": { | ||||||
|  |     "not_set": "No establecido", | ||||||
|  |     "configure-languages": "Configurar idiomas..." | ||||||
|  |   }, | ||||||
|  |   "content_language": { | ||||||
|  |     "title": "Contenido de idiomas", | ||||||
|  |     "description": "Seleccione uno o más idiomas que deben aparecer en la selección del idioma en la sección Propiedades Básicas de una nota de texto de solo lectura o editable. Esto permitirá características tales como corrección de ortografía o soporte de derecha a izquierda." | ||||||
|  |   }, | ||||||
|  |   "switch_layout_button": { | ||||||
|  |     "title_vertical": "Mover el panel de edición hacia abajo", | ||||||
|  |     "title_horizontal": "Mover el panel de edición a la izquierda" | ||||||
|  |   }, | ||||||
|  |   "toggle_read_only_button": { | ||||||
|  |     "unlock-editing": "Desbloquear la edición", | ||||||
|  |     "lock-editing": "Bloquear la edición" | ||||||
|  |   }, | ||||||
|  |   "png_export_button": { | ||||||
|  |     "button_title": "Exportar diagrama como PNG" | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -267,7 +267,8 @@ | |||||||
|   "basic_properties": { |   "basic_properties": { | ||||||
|     "basic_properties": "Proprietăți de bază", |     "basic_properties": "Proprietăți de bază", | ||||||
|     "editable": "Editabil", |     "editable": "Editabil", | ||||||
|     "note_type": "Tipul notiței" |     "note_type": "Tipul notiței", | ||||||
|  |     "language": "Limbă" | ||||||
|   }, |   }, | ||||||
|   "book": { |   "book": { | ||||||
|     "no_children_help": "Această notiță de tip Carte nu are nicio subnotiță așadar nu este nimic de afișat. Vedeți <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">wiki</a> pentru detalii." |     "no_children_help": "Această notiță de tip Carte nu are nicio subnotiță așadar nu este nimic de afișat. Vedeți <a href=\"https://triliumnext.github.io/Docs/Wiki/book-note.html\">wiki</a> pentru detalii." | ||||||
| @@ -678,7 +679,8 @@ | |||||||
|     "language": "Limbă", |     "language": "Limbă", | ||||||
|     "monday": "Luni", |     "monday": "Luni", | ||||||
|     "sunday": "Duminică", |     "sunday": "Duminică", | ||||||
|     "title": "Localizare" |     "title": "Localizare", | ||||||
|  |     "formatting-locale": "Format dată și numere" | ||||||
|   }, |   }, | ||||||
|   "image_properties": { |   "image_properties": { | ||||||
|     "copy_reference_to_clipboard": "Copiază referință în clipboard", |     "copy_reference_to_clipboard": "Copiază referință în clipboard", | ||||||
| @@ -1692,5 +1694,30 @@ | |||||||
|   }, |   }, | ||||||
|   "content_widget": { |   "content_widget": { | ||||||
|     "unknown_widget": "Nu s-a putut găsi widget-ul corespunzător pentru „{{id}}”." |     "unknown_widget": "Nu s-a putut găsi widget-ul corespunzător pentru „{{id}}”." | ||||||
|  |   }, | ||||||
|  |   "code-editor-options": { | ||||||
|  |     "title": "Editor" | ||||||
|  |   }, | ||||||
|  |   "content_language": { | ||||||
|  |     "description": "Selectați una sau mai multe limbi ce vor apărea în selecția limbii din cadrul secțiunii „Proprietăți de bază” pentru notițele de tip text (editabile sau doar în citire).", | ||||||
|  |     "title": "Limbi pentru conținutul notițelor" | ||||||
|  |   }, | ||||||
|  |   "hidden-subtree": { | ||||||
|  |     "localization": "Limbă și regiune" | ||||||
|  |   }, | ||||||
|  |   "note_language": { | ||||||
|  |     "configure-languages": "Configurează limbile...", | ||||||
|  |     "not_set": "Nedefinită" | ||||||
|  |   }, | ||||||
|  |   "png_export_button": { | ||||||
|  |     "button_title": "Exportă diagrama ca PNG" | ||||||
|  |   }, | ||||||
|  |   "switch_layout_button": { | ||||||
|  |     "title_horizontal": "Mută panoul de editare la stânga", | ||||||
|  |     "title_vertical": "Mută panoul de editare în jos" | ||||||
|  |   }, | ||||||
|  |   "toggle_read_only_button": { | ||||||
|  |     "lock-editing": "Blochează editarea", | ||||||
|  |     "unlock-editing": "Deblochează editarea" | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -70,6 +70,7 @@ const ALLOWED_OPTIONS = new Set<OptionNames>([ | |||||||
|     "promotedAttributesOpenInRibbon", |     "promotedAttributesOpenInRibbon", | ||||||
|     "editedNotesOpenInRibbon", |     "editedNotesOpenInRibbon", | ||||||
|     "locale", |     "locale", | ||||||
|  |     "formattingLocale", | ||||||
|     "firstDayOfWeek", |     "firstDayOfWeek", | ||||||
|     "languages", |     "languages", | ||||||
|     "textNoteEditorType", |     "textNoteEditorType", | ||||||
|   | |||||||
| @@ -1,70 +0,0 @@ | |||||||
| "use strict"; |  | ||||||
|  |  | ||||||
| import path from "path"; |  | ||||||
| import resourceDir from "./resource_dir.js"; |  | ||||||
| import log from "./log.js"; |  | ||||||
| import os from "os"; |  | ||||||
| import fs from "fs"; |  | ||||||
| import config from "./config.js"; |  | ||||||
| import { isElectron } from "./utils.js"; |  | ||||||
|  |  | ||||||
| const template = `[Desktop Entry] |  | ||||||
| Type=Application |  | ||||||
| Name=TriliumNext Notes |  | ||||||
| StartupWMClass=TriliumNext Notes |  | ||||||
| Icon=#APP_ROOT_DIR#/icon.png |  | ||||||
| Exec=#EXE_PATH# |  | ||||||
| Categories=Office |  | ||||||
| Terminal=false |  | ||||||
| `; |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Installs .desktop icon into standard ~/.local/share/applications directory. |  | ||||||
|  * We overwrite this file during every run as it might have been updated. |  | ||||||
|  */ |  | ||||||
| function installLocalAppIcon() { |  | ||||||
|     if (!isElectron || ["win32", "darwin"].includes(os.platform()) || (config.General && config.General.noDesktopIcon)) { |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (!fs.existsSync(path.resolve(resourceDir.ELECTRON_APP_ROOT_DIR, "trilium-portable.sh"))) { |  | ||||||
|         // simple heuristic to detect ".tar.xz" linux build (i.e., not flatpak, not debian) |  | ||||||
|         // only in such case it's necessary to create an icon |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     const desktopDir = path.resolve(os.homedir(), ".local/share/applications"); |  | ||||||
|  |  | ||||||
|     fs.stat(desktopDir, function (err, stats) { |  | ||||||
|         if (err) { |  | ||||||
|             // Directory doesn't exist, so we won't attempt to create the .desktop file |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if (stats.isDirectory()) { |  | ||||||
|             const desktopFilePath = path.resolve(desktopDir, "trilium-notes.desktop"); |  | ||||||
|  |  | ||||||
|             fs.writeFile(desktopFilePath, getDesktopFileContent(), function (err) { |  | ||||||
|                 if (err) { |  | ||||||
|                     log.error("Desktop icon installation to ~/.local/share/applications failed."); |  | ||||||
|                 } |  | ||||||
|             }); |  | ||||||
|         } |  | ||||||
|     }); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function getDesktopFileContent() { |  | ||||||
|     return template.replace("#APP_ROOT_DIR#", escapePath(resourceDir.ELECTRON_APP_ROOT_DIR)).replace("#EXE_PATH#", escapePath(getExePath())); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function escapePath(path: string) { |  | ||||||
|     return path.replace(/ /g, "\\ "); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function getExePath() { |  | ||||||
|     return path.resolve(resourceDir.ELECTRON_APP_ROOT_DIR, "trilium"); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export default { |  | ||||||
|     installLocalAppIcon |  | ||||||
| }; |  | ||||||
| @@ -76,6 +76,10 @@ async function backupNow(name: string) { | |||||||
|     return await syncMutexService.doExclusively(async () => { |     return await syncMutexService.doExclusively(async () => { | ||||||
|         const backupFile = `${dataDir.BACKUP_DIR}/backup-${name}.db`; |         const backupFile = `${dataDir.BACKUP_DIR}/backup-${name}.db`; | ||||||
|  |  | ||||||
|  |         if (!fs.existsSync(dataDir.BACKUP_DIR)) { | ||||||
|  |             fs.mkdirSync(dataDir.BACKUP_DIR, 0o700); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         await sql.copyDatabase(backupFile); |         await sql.copyDatabase(backupFile); | ||||||
|  |  | ||||||
|         log.info(`Created backup at ${backupFile}`); |         log.info(`Created backup at ${backupFile}`); | ||||||
| @@ -83,11 +87,6 @@ async function backupNow(name: string) { | |||||||
|         return backupFile; |         return backupFile; | ||||||
|     }); |     }); | ||||||
| } | } | ||||||
|  |  | ||||||
| if (!fs.existsSync(dataDir.BACKUP_DIR)) { |  | ||||||
|     fs.mkdirSync(dataDir.BACKUP_DIR, 0o700); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export default { | export default { | ||||||
|     getExistingBackups, |     getExistingBackups, | ||||||
|     backupNow, |     backupNow, | ||||||
|   | |||||||
| @@ -111,6 +111,7 @@ function getMonthNoteTitle(rootNote: BNote, monthNumber: string, dateObj: Date) | |||||||
|     return pattern |     return pattern | ||||||
|         .replace(/{shortMonth3}/g, monthName.slice(0, 3)) |         .replace(/{shortMonth3}/g, monthName.slice(0, 3)) | ||||||
|         .replace(/{shortMonth4}/g, monthName.slice(0, 4)) |         .replace(/{shortMonth4}/g, monthName.slice(0, 4)) | ||||||
|  |         .replace(/{isoMonth}/g, dateUtils.utcDateStr(dateObj).slice(0, 7)) | ||||||
|         .replace(/{monthNumberPadded}/g, monthNumber) |         .replace(/{monthNumberPadded}/g, monthNumber) | ||||||
|         .replace(/{month}/g, monthName); |         .replace(/{month}/g, monthName); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -13,36 +13,45 @@ export interface Locale { | |||||||
|     rtl?: boolean; |     rtl?: boolean; | ||||||
|     /** `true` if the language is not supported by the application as a display language, but it is selectable by the user for the content. */ |     /** `true` if the language is not supported by the application as a display language, but it is selectable by the user for the content. */ | ||||||
|     contentOnly?: boolean; |     contentOnly?: boolean; | ||||||
|  |     /** The value to pass to `--lang` for the Electron instance in order to set it as a locale. Not setting it will hide it from the list of supported locales. */ | ||||||
|  |     electronLocale?: string; | ||||||
| } | } | ||||||
|  |  | ||||||
| const LOCALES: Locale[] = [ | const LOCALES: Locale[] = [ | ||||||
|     { |     { | ||||||
|         id: "en", |         id: "en", | ||||||
|         name: "English" |         name: "English", | ||||||
|  |         electronLocale: "en" | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|         id: "de", |         id: "de", | ||||||
|         name: "Deutsch" |         name: "Deutsch", | ||||||
|  |         electronLocale: "de" | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|         id: "es", |         id: "es", | ||||||
|         name: "Español" |         name: "Español", | ||||||
|  |         electronLocale: "es" | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|         id: "fr", |         id: "fr", | ||||||
|         name: "Français" |         name: "Français", | ||||||
|  |         electronLocale: "fr" | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|         id: "cn", |         id: "cn", | ||||||
|         name: "简体中文" |         name: "简体中文", | ||||||
|  |         electronLocale: "zh_CN" | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|         id: "tw", |         id: "tw", | ||||||
|         name: "繁體中文" |         name: "繁體中文", | ||||||
|  |         electronLocale: "zh_TW" | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|         id: "ro", |         id: "ro", | ||||||
|         name: "Română" |         name: "Română", | ||||||
|  |         electronLocale: "ro" | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|     /* |     /* | ||||||
|   | |||||||
| @@ -141,6 +141,7 @@ const defaultOptions: DefaultOption[] = [ | |||||||
|  |  | ||||||
|     // Internationalization |     // Internationalization | ||||||
|     { name: "locale", value: "en", isSynced: true }, |     { name: "locale", value: "en", isSynced: true }, | ||||||
|  |     { name: "formattingLocale", value: "en", isSynced: true }, | ||||||
|     { name: "firstDayOfWeek", value: "1", isSynced: true }, |     { name: "firstDayOfWeek", value: "1", isSynced: true }, | ||||||
|     { name: "languages", value: "[]", isSynced: true }, |     { name: "languages", value: "[]", isSynced: true }, | ||||||
|  |  | ||||||
|   | |||||||
| @@ -35,6 +35,7 @@ export interface OptionDefinitions extends KeyboardShortcutsOptions<KeyboardActi | |||||||
|     customSearchEngineName: string; |     customSearchEngineName: string; | ||||||
|     customSearchEngineUrl: string; |     customSearchEngineUrl: string; | ||||||
|     locale: string; |     locale: string; | ||||||
|  |     formattingLocale: string; | ||||||
|     codeBlockTheme: string; |     codeBlockTheme: string; | ||||||
|     textNoteEditorType: string; |     textNoteEditorType: string; | ||||||
|     layoutOrientation: string; |     layoutOrientation: string; | ||||||
|   | |||||||
| @@ -365,7 +365,7 @@ export function processStringOrBuffer(data: string | Buffer | null) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| export function safeExtractMessageAndStackFromError(err: unknown) { | export function safeExtractMessageAndStackFromError(err: unknown): [errMessage: string, errStack: string | undefined] { | ||||||
|     return (err instanceof Error) ? [err.message, err.stack] as const : ["Unknown Error", undefined] as const; |     return (err instanceof Error) ? [err.message, err.stack] as const : ["Unknown Error", undefined] as const; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ import { beforeAll, beforeEach, describe, expect, it } from "vitest"; | |||||||
| import supertest from "supertest"; | import supertest from "supertest"; | ||||||
| import { initializeTranslations } from "../services/i18n.js"; | import { initializeTranslations } from "../services/i18n.js"; | ||||||
| import type { Application, Request, Response, NextFunction } from "express"; | import type { Application, Request, Response, NextFunction } from "express"; | ||||||
|  | import { safeExtractMessageAndStackFromError } from "../services/utils.js"; | ||||||
|  |  | ||||||
| let app: Application; | let app: Application; | ||||||
|  |  | ||||||
| @@ -11,8 +12,9 @@ describe("Share API test", () => { | |||||||
|     beforeAll(async () => { |     beforeAll(async () => { | ||||||
|         initializeTranslations(); |         initializeTranslations(); | ||||||
|         app = (await import("../app.js")).default; |         app = (await import("../app.js")).default; | ||||||
|         app.use((err: any, req: Request, res: Response, next: NextFunction) => { |         app.use((err: unknown, req: Request, res: Response, next: NextFunction) => { | ||||||
|             if (err.message.includes("Cannot set headers after they are sent to the client")) { |             const [errMessage] = safeExtractMessageAndStackFromError(err) | ||||||
|  |             if (errMessage.includes("Cannot set headers after they are sent to the client")) { | ||||||
|                 cannotSetHeadersCount++; |                 cannotSetHeadersCount++; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ import log from "../services/log.js"; | |||||||
| import type SNote from "./shaca/entities/snote.js"; | import type SNote from "./shaca/entities/snote.js"; | ||||||
| import type SBranch from "./shaca/entities/sbranch.js"; | import type SBranch from "./shaca/entities/sbranch.js"; | ||||||
| import type SAttachment from "./shaca/entities/sattachment.js"; | import type SAttachment from "./shaca/entities/sattachment.js"; | ||||||
| import utils from "../services/utils.js"; | import utils, { safeExtractMessageAndStackFromError } from "../services/utils.js"; | ||||||
| import options from "../services/options.js"; | import options from "../services/options.js"; | ||||||
|  |  | ||||||
| function getSharedSubTreeRoot(note: SNote): { note?: SNote; branch?: SBranch } { | function getSharedSubTreeRoot(note: SNote): { note?: SNote; branch?: SBranch } { | ||||||
| @@ -115,7 +115,14 @@ function renderImageAttachment(image: SNote, res: Response, attachmentName: stri | |||||||
|         svgString = content; |         svgString = content; | ||||||
|     } else { |     } else { | ||||||
|         // backwards compatibility, before attachments, the SVG was stored in the main note content as a separate key |         // backwards compatibility, before attachments, the SVG was stored in the main note content as a separate key | ||||||
|         const contentSvg = image.getJsonContentSafely()?.svg; |         const possibleSvgContent = image.getJsonContentSafely(); | ||||||
|  |  | ||||||
|  |         const contentSvg = (typeof possibleSvgContent === "object" | ||||||
|  |             && possibleSvgContent !== null | ||||||
|  |             && "svg" in possibleSvgContent | ||||||
|  |             && typeof possibleSvgContent.svg === "string") | ||||||
|  |                 ? possibleSvgContent.svg | ||||||
|  |                 : null; | ||||||
|  |  | ||||||
|         if (contentSvg) { |         if (contentSvg) { | ||||||
|             svgString = contentSvg; |             svgString = contentSvg; | ||||||
| @@ -184,8 +191,9 @@ function register(router: Router) { | |||||||
|                         res.send(ejsResult); |                         res.send(ejsResult); | ||||||
|                         useDefaultView = false; // Rendering went okay, don't use default view |                         useDefaultView = false; // Rendering went okay, don't use default view | ||||||
|                     } |                     } | ||||||
|                 } catch (e: any) { |                 } catch (e: unknown) { | ||||||
|                     log.error(`Rendering user provided share template (${templateId}) threw exception ${e.message} with stacktrace: ${e.stack}`); |                     const [errMessage, errStack] = safeExtractMessageAndStackFromError(e); | ||||||
|  |                     log.error(`Rendering user provided share template (${templateId}) threw exception ${errMessage} with stacktrace: ${errStack}`); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @@ -195,7 +203,7 @@ function register(router: Router) { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     router.get("/share/", (req, res, next) => { |     router.get("/share/", (req, res) => { | ||||||
|         if (req.path.substr(-1) !== "/") { |         if (req.path.substr(-1) !== "/") { | ||||||
|             res.redirect("../share/"); |             res.redirect("../share/"); | ||||||
|             return; |             return; | ||||||
| @@ -211,7 +219,7 @@ function register(router: Router) { | |||||||
|         renderNote(shaca.shareRootNote, req, res); |         renderNote(shaca.shareRootNote, req, res); | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     router.get("/share/:shareId", (req, res, next) => { |     router.get("/share/:shareId", (req, res) => { | ||||||
|         shacaLoader.ensureLoad(); |         shacaLoader.ensureLoad(); | ||||||
|  |  | ||||||
|         const { shareId } = req.params; |         const { shareId } = req.params; | ||||||
| @@ -221,7 +229,7 @@ function register(router: Router) { | |||||||
|         renderNote(note, req, res); |         renderNote(note, req, res); | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     router.get("/share/api/notes/:noteId", (req, res, next) => { |     router.get("/share/api/notes/:noteId", (req, res) => { | ||||||
|         shacaLoader.ensureLoad(); |         shacaLoader.ensureLoad(); | ||||||
|         let note: SNote | boolean; |         let note: SNote | boolean; | ||||||
|  |  | ||||||
| @@ -234,7 +242,7 @@ function register(router: Router) { | |||||||
|         res.json(note.getPojo()); |         res.json(note.getPojo()); | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     router.get("/share/api/notes/:noteId/download", (req, res, next) => { |     router.get("/share/api/notes/:noteId/download", (req, res) => { | ||||||
|         shacaLoader.ensureLoad(); |         shacaLoader.ensureLoad(); | ||||||
|  |  | ||||||
|         let note: SNote | boolean; |         let note: SNote | boolean; | ||||||
| @@ -256,7 +264,7 @@ function register(router: Router) { | |||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     // :filename is not used by trilium, but instead used for "save as" to assign a human-readable filename |     // :filename is not used by trilium, but instead used for "save as" to assign a human-readable filename | ||||||
|     router.get("/share/api/images/:noteId/:filename", (req, res, next) => { |     router.get("/share/api/images/:noteId/:filename", (req, res) => { | ||||||
|         shacaLoader.ensureLoad(); |         shacaLoader.ensureLoad(); | ||||||
|  |  | ||||||
|         let image: SNote | boolean; |         let image: SNote | boolean; | ||||||
| @@ -282,7 +290,7 @@ function register(router: Router) { | |||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     // :filename is not used by trilium, but instead used for "save as" to assign a human-readable filename |     // :filename is not used by trilium, but instead used for "save as" to assign a human-readable filename | ||||||
|     router.get("/share/api/attachments/:attachmentId/image/:filename", (req, res, next) => { |     router.get("/share/api/attachments/:attachmentId/image/:filename", (req, res) => { | ||||||
|         shacaLoader.ensureLoad(); |         shacaLoader.ensureLoad(); | ||||||
|  |  | ||||||
|         let attachment: SAttachment | boolean; |         let attachment: SAttachment | boolean; | ||||||
| @@ -300,7 +308,7 @@ function register(router: Router) { | |||||||
|         } |         } | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     router.get("/share/api/attachments/:attachmentId/download", (req, res, next) => { |     router.get("/share/api/attachments/:attachmentId/download", (req, res) => { | ||||||
|         shacaLoader.ensureLoad(); |         shacaLoader.ensureLoad(); | ||||||
|  |  | ||||||
|         let attachment: SAttachment | boolean; |         let attachment: SAttachment | boolean; | ||||||
| @@ -322,7 +330,7 @@ function register(router: Router) { | |||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     // used for PDF viewing |     // used for PDF viewing | ||||||
|     router.get("/share/api/notes/:noteId/view", (req, res, next) => { |     router.get("/share/api/notes/:noteId/view", (req, res) => { | ||||||
|         shacaLoader.ensureLoad(); |         shacaLoader.ensureLoad(); | ||||||
|  |  | ||||||
|         let note: SNote | boolean; |         let note: SNote | boolean; | ||||||
| @@ -340,11 +348,10 @@ function register(router: Router) { | |||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     // Used for searching, require noteId so we know the subTreeRoot |     // Used for searching, require noteId so we know the subTreeRoot | ||||||
|     router.get("/share/api/notes", (req, res, next) => { |     router.get("/share/api/notes", (req, res) => { | ||||||
|         shacaLoader.ensureLoad(); |         shacaLoader.ensureLoad(); | ||||||
|  |  | ||||||
|         const ancestorNoteId = req.query.ancestorNoteId ?? "_share"; |         const ancestorNoteId = req.query.ancestorNoteId ?? "_share"; | ||||||
|         let note; |  | ||||||
|  |  | ||||||
|         if (typeof ancestorNoteId !== "string") { |         if (typeof ancestorNoteId !== "string") { | ||||||
|             res.status(400).json({ message: "'ancestorNoteId' parameter is mandatory." }); |             res.status(400).json({ message: "'ancestorNoteId' parameter is mandatory." }); | ||||||
| @@ -352,7 +359,7 @@ function register(router: Router) { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         // This will automatically return if no ancestorNoteId is provided and there is no shareIndex |         // This will automatically return if no ancestorNoteId is provided and there is no shareIndex | ||||||
|         if (!(note = checkNoteAccess(ancestorNoteId, req, res))) { |         if (!checkNoteAccess(ancestorNoteId, req, res)) { | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -47,7 +47,7 @@ class SAttachment extends AbstractShacaEntity { | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         let content = row.content; |         const content = row.content; | ||||||
|  |  | ||||||
|         if (this.hasStringContent()) { |         if (this.hasStringContent()) { | ||||||
|             return content === null ? "" : content.toString("utf-8"); |             return content === null ? "" : content.toString("utf-8"); | ||||||
|   | |||||||
| @@ -105,7 +105,7 @@ class SNote extends AbstractShacaEntity { | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         let content = row.content; |         const content = row.content; | ||||||
|  |  | ||||||
|         if (this.hasStringContent()) { |         if (this.hasStringContent()) { | ||||||
|             return content === null ? "" : content.toString("utf-8"); |             return content === null ? "" : content.toString("utf-8"); | ||||||
| @@ -212,7 +212,7 @@ class SNote extends AbstractShacaEntity { | |||||||
|     /** |     /** | ||||||
|      * @throws Error in case of invalid JSON |      * @throws Error in case of invalid JSON | ||||||
|      */ |      */ | ||||||
|     getJsonContent(): any | null { |     getJsonContent(): unknown | null { | ||||||
|         const content = this.getContent(); |         const content = this.getContent(); | ||||||
|  |  | ||||||
|         if (typeof content !== "string" || !content || !content.trim()) { |         if (typeof content !== "string" || !content || !content.trim()) { | ||||||
|   | |||||||
| @@ -93,7 +93,7 @@ function ensureLoad() { | |||||||
|  |  | ||||||
| eventService.subscribe( | eventService.subscribe( | ||||||
|     [eventService.ENTITY_CREATED, eventService.ENTITY_CHANGED, eventService.ENTITY_DELETED, eventService.ENTITY_CHANGE_SYNCED, eventService.ENTITY_DELETE_SYNCED], |     [eventService.ENTITY_CREATED, eventService.ENTITY_CHANGED, eventService.ENTITY_DELETED, eventService.ENTITY_CHANGE_SYNCED, eventService.ENTITY_DELETE_SYNCED], | ||||||
|     ({ entityName, entity }) => { |     () => { | ||||||
|         shaca.reset(); |         shaca.reset(); | ||||||
|     } |     } | ||||||
| ); | ); | ||||||
|   | |||||||
| @@ -244,7 +244,8 @@ | |||||||
|     "other": "Otros", |     "other": "Otros", | ||||||
|     "advanced-title": "Avanzado", |     "advanced-title": "Avanzado", | ||||||
|     "visible-launchers-title": "Lanzadores visibles", |     "visible-launchers-title": "Lanzadores visibles", | ||||||
|     "user-guide": "Guía de Usuario" |     "user-guide": "Guía de Usuario", | ||||||
|  |     "localization": "Idioma y Región" | ||||||
|   }, |   }, | ||||||
|   "notes": { |   "notes": { | ||||||
|     "new-note": "Nueva nota", |     "new-note": "Nueva nota", | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user