diff --git a/.dockerignore b/.dockerignore
index 64bcb6983..1ca391a43 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -1,10 +1,44 @@
-.git
-.idea
+# ignored Files
+.dockerignore
+.editorconfig
+.git*
+.prettier*
+electron*
+entitlements.plist
+nodemon.json
+renovate.json
+trilium.iml
+Dockerfile
+Dockerfile.*
+npm-debug.log
+/src/**/*.spec.ts
+
+# ignored folders
+/.cache
+/.git
+/.github
+/.idea
+/.vscode
/bin
+/build
/dist
/docs
-/npm-debug.log
-node_modules
+/dump-db
+/e2e
+/integration-tests
+/spec
+/test
+/test-etapi
+/node_modules
-src/**/*.ts
-!src/services/asset_path.ts
\ No newline at end of file
+
+# exceptions
+!/bin/copy-dist.ts
+!/bin/cleanupNodeModules.ts
+
+# temporary exception to make copy-dist inside Docker build not fail
+# TriliumNextTODO: make copy-dist *not* requiring to copy these file for builds other than electron-forge
+!forge.config.cjs
+!/bin/tpl
+!/bin/electron-forge/desktop.ejs
+!/bin/electron-forge/sign-windows.cjs
\ No newline at end of file
diff --git a/.gitattributes b/.gitattributes
index 9f1ce2646..c2de311c3 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,3 +1,13 @@
package-lock.json linguist-generated=true
**/package-lock.json linguist-generated=true
+src/public/app/doc_notes/en/User[[:space:]]Guide/** linguist-generated=true
+src/public/app/doc_notes/en/User[[:space:]]Guide/**/*.md eol=lf
+
+demo/**/*.html eol=lf
+demo/**/*.json eol=lf
+demo/**/*.svg eol=lf
+demo/**/*.txt eol=lf
+demo/**/*.js eol=lf
+demo/**/*.css eol=lf
+
libraries/** linguist-vendored
\ No newline at end of file
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index 6203d87bc..75c9d0dca 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -1,4 +1,4 @@
# These are supported funding model platforms
-github: [zadam]
-custom: ["https://paypal.me/za4am"]
+github: [eliandoran]
+custom: ["https://paypal.me/eliandoran"]
diff --git a/.github/actions/build-electron/action.yml b/.github/actions/build-electron/action.yml
index dca9bc3b8..d5003ecdd 100644
--- a/.github/actions/build-electron/action.yml
+++ b/.github/actions/build-electron/action.yml
@@ -8,206 +8,153 @@ inputs:
arch:
description: "The architecture to build for: x64, arm64"
required: true
- extension:
- description: "Platform specific extensions to copy in the output: dmg, deb, rpm, exe, zip"
+ shell:
+ description: "Which shell to use"
+ required: true
+ forge_platform:
+ description: "The --platform to pass to Electron Forge"
required: true
runs:
using: composite
steps:
- # Certificate setup
- - name: Import Apple certificates
- if: inputs.os == 'macos'
- uses: apple-actions/import-codesign-certs@v2
- with:
- p12-file-base64: ${{ env.APPLE_APP_CERTIFICATE_BASE64 }}
- p12-password: ${{ env.APPLE_APP_CERTIFICATE_PASSWORD }}
- keychain: build
- keychain-password: ${{ github.run_id }}
+ # Certificate setup
+ - name: Import Apple certificates
+ if: inputs.os == 'macos'
+ uses: apple-actions/import-codesign-certs@v3
+ with:
+ p12-file-base64: ${{ env.APPLE_APP_CERTIFICATE_BASE64 }}
+ p12-password: ${{ env.APPLE_APP_CERTIFICATE_PASSWORD }}
+ keychain: build
+ keychain-password: ${{ github.run_id }}
- - name: Install Installer certificate
- if: inputs.os == 'macos'
- uses: apple-actions/import-codesign-certs@v2
- with:
- p12-file-base64: ${{ env.APPLE_INSTALLER_CERTIFICATE_BASE64 }}
- p12-password: ${{ env.APPLE_INSTALLER_CERTIFICATE_PASSWORD }}
- keychain: build
- keychain-password: ${{ github.run_id }}
- # We don't need to create a keychain here because we're using the build keychain that was created in the previous step
- create-keychain: false
+ - name: Install Installer certificate
+ if: inputs.os == 'macos'
+ uses: apple-actions/import-codesign-certs@v3
+ with:
+ p12-file-base64: ${{ env.APPLE_INSTALLER_CERTIFICATE_BASE64 }}
+ p12-password: ${{ env.APPLE_INSTALLER_CERTIFICATE_PASSWORD }}
+ keychain: build
+ keychain-password: ${{ github.run_id }}
+ # We don't need to create a keychain here because we're using the build keychain that was created in the previous step
+ create-keychain: false
- - name: Verify certificates
- if: inputs.os == 'macos'
- shell: bash
- run: |
- echo "Available signing identities:"
- security find-identity -v -p codesigning build.keychain
+ - name: Verify certificates
+ if: inputs.os == 'macos'
+ shell: ${{ inputs.shell }}
+ run: |
+ echo "Available signing identities:"
+ security find-identity -v -p codesigning build.keychain
- - name: Set up Python and other macOS dependencies
- if: ${{ inputs.os == 'macos' }}
- shell: bash
- run: |
- brew install python-setuptools
- brew install create-dmg
+ - name: Set up Python and other macOS dependencies
+ if: ${{ inputs.os == 'macos' }}
+ shell: ${{ inputs.shell }}
+ run: |
+ brew install python-setuptools
+ brew install create-dmg
- - name: Install dependencies for RPM and Flatpak package building
- if: ${{ inputs.os == 'linux' }}
- shell: bash
- run: |
- 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_ARCH=$(if [[ ${{ inputs.arch }} = 'arm64' ]]; then echo 'aarch64'; else echo 'x86_64'; fi)
- FLATPAK_VERSION='24.08'
- flatpak install --user --no-deps --arch $FLATPAK_ARCH --assumeyes runtime/org.freedesktop.Platform/$FLATPAK_ARCH/$FLATPAK_VERSION runtime/org.freedesktop.Sdk/$FLATPAK_ARCH/$FLATPAK_VERSION org.electronjs.Electron2.BaseApp/$FLATPAK_ARCH/$FLATPAK_VERSION
+ - name: Install dependencies for RPM and Flatpak package building
+ if: ${{ inputs.os == 'linux' }}
+ shell: ${{ inputs.shell }}
+ run: |
+ 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_ARCH=$(if [[ ${{ inputs.arch }} = 'arm64' ]]; then echo 'aarch64'; else echo 'x86_64'; fi)
+ FLATPAK_VERSION='24.08'
+ flatpak install --user --no-deps --arch $FLATPAK_ARCH --assumeyes runtime/org.freedesktop.Platform/$FLATPAK_ARCH/$FLATPAK_VERSION runtime/org.freedesktop.Sdk/$FLATPAK_ARCH/$FLATPAK_VERSION org.electronjs.Electron2.BaseApp/$FLATPAK_ARCH/$FLATPAK_VERSION
- # Build setup
- - name: Install dependencies
- shell: bash
- run: npm ci
+ # Build setup
+ - name: Install dependencies
+ shell: ${{ inputs.shell }}
+ run: npm ci
- - name: Update build info
- shell: bash
- run: npm run chore:update-build-info
+ - name: Update build info
+ shell: ${{ inputs.shell }}
+ run: npm run chore:update-build-info
- # Critical debugging configuration
- - name: Run electron-forge build with enhanced logging
- shell: bash
- env:
- # Pass through required environment variables for signing and notarization
- APPLE_TEAM_ID: ${{ env.APPLE_TEAM_ID }}
- APPLE_ID: ${{ env.APPLE_ID }}
- APPLE_ID_PASSWORD: ${{ env.APPLE_ID_PASSWORD }}
- 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 }}"
+ # Critical debugging configuration
+ - name: Run electron-forge build with enhanced logging
+ shell: ${{ inputs.shell }}
+ env:
+ # Pass through required environment variables for signing and notarization
+ APPLE_TEAM_ID: ${{ env.APPLE_TEAM_ID }}
+ APPLE_ID: ${{ env.APPLE_ID }}
+ APPLE_ID_PASSWORD: ${{ env.APPLE_ID_PASSWORD }}
+ WINDOWS_SIGN_EXECUTABLE: ${{ env.WINDOWS_SIGN_EXECUTABLE }}
+ TRILIUM_ARTIFACT_NAME_HINT: TriliumNextNotes-${{ github.ref_name }}-${{ inputs.os }}-${{ inputs.arch }}
+ run: npm run electron-forge:make -- --arch=${{ inputs.arch }} --platform=${{ inputs.forge_platform }}
+
+ # Add DMG signing step
+ - name: Sign DMG
+ if: inputs.os == 'macos'
+ shell: ${{ inputs.shell }}
+ run: |
+ echo "Signing DMG file..."
+ dmg_file=$(find ./dist -name "*.dmg" -print -quit)
+ if [ -n "$dmg_file" ]; then
+ echo "Found DMG: $dmg_file"
+ # Get the first valid signing identity from the keychain
+ SIGNING_IDENTITY=$(security find-identity -v -p codesigning build.keychain | grep "Developer ID Application" | head -1 | sed -E 's/.*"([^"]+)".*/\1/')
+ if [ -z "$SIGNING_IDENTITY" ]; then
+ echo "Error: No valid Developer ID Application certificate found in keychain"
+ exit 1
fi
+ echo "Using signing identity: $SIGNING_IDENTITY"
+ # Sign the DMG
+ codesign --force --sign "$SIGNING_IDENTITY" --options runtime --timestamp "$dmg_file"
+ # Notarize the DMG
+ xcrun notarytool submit "$dmg_file" --apple-id "$APPLE_ID" --password "$APPLE_ID_PASSWORD" --team-id "$APPLE_TEAM_ID" --wait
+ # Staple the notarization ticket
+ xcrun stapler staple "$dmg_file"
+ else
+ echo "No DMG found to sign"
+ fi
- npm run electron-forge:make -- \
- --arch=${{ inputs.arch }} \
- --platform=$PLATFORM
+ - name: Verify code signing
+ if: inputs.os == 'macos'
+ shell: ${{ inputs.shell }}
+ run: |
+ echo "Verifying code signing for all artifacts..."
- # Add DMG signing step
- - name: Sign DMG
- if: inputs.os == 'macos'
- shell: bash
- run: |
- echo "Signing DMG file..."
- dmg_file=$(find out -name "*.dmg" -print -quit)
- if [ -n "$dmg_file" ]; then
- echo "Found DMG: $dmg_file"
- # Get the first valid signing identity from the keychain
- SIGNING_IDENTITY=$(security find-identity -v -p codesigning build.keychain | grep "Developer ID Application" | head -1 | sed -E 's/.*"([^"]+)".*/\1/')
- if [ -z "$SIGNING_IDENTITY" ]; then
- echo "Error: No valid Developer ID Application certificate found in keychain"
- exit 1
- fi
- echo "Using signing identity: $SIGNING_IDENTITY"
- # Sign the DMG
- codesign --force --sign "$SIGNING_IDENTITY" --options runtime --timestamp "$dmg_file"
- # Notarize the DMG
- xcrun notarytool submit "$dmg_file" --apple-id "$APPLE_ID" --password "$APPLE_ID_PASSWORD" --team-id "$APPLE_TEAM_ID" --wait
- # Staple the notarization ticket
- xcrun stapler staple "$dmg_file"
- else
- echo "No DMG found to sign"
- fi
+ # First check the .app bundle
+ echo "Looking for .app bundle..."
+ app_bundle=$(find ./dist -name "*.app" -print -quit)
+ if [ -n "$app_bundle" ]; then
+ echo "Found app bundle: $app_bundle"
+ echo "Verifying app bundle signing..."
+ codesign --verify --deep --strict --verbose=2 "$app_bundle"
+ echo "Displaying app bundle signing info..."
+ codesign --display --verbose=2 "$app_bundle"
- - name: Verify code signing
- if: inputs.os == 'macos'
- shell: bash
- run: |
- echo "Verifying code signing for all artifacts..."
+ echo "Checking entitlements..."
+ codesign --display --entitlements :- "$app_bundle"
- # First check the .app bundle
- echo "Looking for .app bundle..."
- app_bundle=$(find out -name "*.app" -print -quit)
- if [ -n "$app_bundle" ]; then
- echo "Found app bundle: $app_bundle"
- echo "Verifying app bundle signing..."
- codesign --verify --deep --strict --verbose=2 "$app_bundle"
- echo "Displaying app bundle signing info..."
- codesign --display --verbose=2 "$app_bundle"
+ echo "Checking notarization status..."
+ xcrun stapler validate "$app_bundle" || echo "Warning: App bundle not notarized yet"
+ else
+ echo "No .app bundle found to verify"
+ fi
- echo "Checking entitlements..."
- codesign --display --entitlements :- "$app_bundle"
+ # Then check DMG if it exists
+ echo "Looking for DMG..."
+ dmg_file=$(find ./dist -name "*.dmg" -print -quit)
+ if [ -n "$dmg_file" ]; then
+ echo "Found DMG: $dmg_file"
+ echo "Verifying DMG signing..."
+ codesign --verify --deep --strict --verbose=2 "$dmg_file"
+ echo "Displaying DMG signing info..."
+ codesign --display --verbose=2 "$dmg_file"
- echo "Checking notarization status..."
- xcrun stapler validate "$app_bundle" || echo "Warning: App bundle not notarized yet"
- else
- echo "No .app bundle found to verify"
- fi
+ echo "Checking DMG notarization..."
+ xcrun stapler validate "$dmg_file" || echo "Warning: DMG not notarized yet"
+ else
+ echo "No DMG found to verify"
+ fi
- # Then check DMG if it exists
- echo "Looking for DMG..."
- dmg_file=$(find out -name "*.dmg" -print -quit)
- if [ -n "$dmg_file" ]; then
- echo "Found DMG: $dmg_file"
- echo "Verifying DMG signing..."
- codesign --verify --deep --strict --verbose=2 "$dmg_file"
- echo "Displaying DMG signing info..."
- codesign --display --verbose=2 "$dmg_file"
-
- echo "Checking DMG notarization..."
- xcrun stapler validate "$dmg_file" || echo "Warning: DMG not notarized yet"
- else
- echo "No DMG found to verify"
- fi
-
- # Finally check ZIP if it exists
- echo "Looking for ZIP..."
- zip_file=$(find out -name "*.zip" -print -quit)
- if [ -n "$zip_file" ]; then
- echo "Found ZIP: $zip_file"
- echo "Note: ZIP files are not code signed, but their contents should be"
- 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 out -name "*.dmg" -print -quit)
- if [ -n "$dmg_file" ]; then
- echo "Found DMG: $dmg_file"
- cp "$dmg_file" "upload/TriliumNextNotes-${{ github.ref_name }}-darwin-${{ inputs.arch }}.dmg"
- else
- echo "Warning: No DMG file found"
- fi
-
- # Look for ZIP files recursively
- echo "Looking for ZIP files..."
- zip_file=$(find out -name "*.zip" -print -quit)
- if [ -n "$zip_file" ]; then
- echo "Found ZIP: $zip_file"
- cp "$zip_file" "upload/TriliumNextNotes-${{ github.ref_name }}-darwin-${{ 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 out -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/
+ # Finally check ZIP if it exists
+ echo "Looking for ZIP..."
+ zip_file=$(find ./dist -name "*.zip" -print -quit)
+ if [ -n "$zip_file" ]; then
+ echo "Found ZIP: $zip_file"
+ echo "Note: ZIP files are not code signed, but their contents should be"
+ fi
diff --git a/.github/actions/build-server/action.yml b/.github/actions/build-server/action.yml
index 7423b8c4a..13984e2ce 100644
--- a/.github/actions/build-server/action.yml
+++ b/.github/actions/build-server/action.yml
@@ -11,7 +11,7 @@ runs:
- name: Set up node & dependencies
uses: actions/setup-node@v4
with:
- node-version: 20
+ node-version: 22
cache: "npm"
- name: Install dependencies
shell: bash
@@ -28,4 +28,5 @@ runs:
run: |
mkdir -p upload
file=$(find dist -name '*.tar.xz' -print -quit)
- cp "$file" "upload/TriliumNextNotes-Server-${{ github.ref_name }}-${{ inputs.os }}-${{ inputs.arch }}.tar.xz"
+ name=${{ github.ref_name }}
+ cp "$file" "upload/TriliumNextNotes-Server-${name//\//-}-${{ inputs.os }}-${{ inputs.arch }}.tar.xz"
diff --git a/.github/actions/report-size/action.yml b/.github/actions/report-size/action.yml
new file mode 100644
index 000000000..e6bc477ca
--- /dev/null
+++ b/.github/actions/report-size/action.yml
@@ -0,0 +1,79 @@
+name: 'Bundle size reporter'
+description: 'Post bundle size difference compared to another branch'
+inputs:
+ branch:
+ description: 'Branch to compare to'
+ required: true
+ default: 'main'
+ paths:
+ description:
+ 'Paths to json file bundle size report or folder containing bundles'
+ required: true
+ default: '/'
+ onlyDiff:
+ description: 'Report only different sizes'
+ required: false
+ default: 'false'
+ filter:
+ description: 'Regex filter based on file path'
+ required: false
+ unit:
+ description: 'Size unit'
+ required: false
+ default: 'KB'
+
+ # Comment inputs
+ comment:
+ description: 'Post comment'
+ required: false
+ default: 'true'
+ header:
+ description: 'Comment header'
+ required: false
+ default: 'Bundle size report'
+ append:
+ description: 'Append comment'
+ required: false
+ default: 'false'
+ ghToken:
+ description: 'Github token'
+ required: false
+
+runs:
+ using: 'composite'
+ steps:
+ # Checkout branch to compare to [required]
+ - name: Checkout base branch
+ uses: actions/checkout@v4
+ with:
+ ref: ${{ inputs.branch }}
+ path: br-base
+ token: ${{ inputs.ghToken }}
+
+ # Generate the bundle size difference report [required]
+ - name: Generate report
+ id: bundleSize
+ uses: nejcm/bundle-size-reporter-action@v1.4.1
+ with:
+ paths: ${{ inputs.paths }}
+ onlyDiff: ${{ inputs.onlyDiff }}
+ filter: ${{ inputs.filter }}
+ unit: ${{ inputs.unit }}
+
+ # Post github action summary
+ - name: Post summary
+ if: ${{ steps.bundleSize.outputs.hasDifferences == 'true' }} # post only in case of changes
+ run: |
+ echo '${{ steps.bundleSize.outputs.summary }}' >> $GITHUB_STEP_SUMMARY
+ shell: bash
+
+ # Post github action comment
+ - name: Post comment
+ uses: marocchino/sticky-pull-request-comment@v2
+ if: ${{ steps.bundleSize.outputs.hasDifferences == 'true' }} # post only in case of changes
+ with:
+ number: ${{ github.event.pull_request.number }}
+ header: ${{ inputs.header }}
+ append: ${{ inputs.append }}
+ message: '${{ steps.bundleSize.outputs.summary }}'
+ GITHUB_TOKEN: ${{ inputs.ghToken }}
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
new file mode 100644
index 000000000..25cd18724
--- /dev/null
+++ b/.github/workflows/codeql.yml
@@ -0,0 +1,100 @@
+# For most projects, this workflow file will not need changing; you simply need
+# to commit it to your repository.
+#
+# You may wish to alter this file to override the set of languages analyzed,
+# or to provide custom queries or build logic.
+#
+# ******** NOTE ********
+# We have attempted to detect the languages in your repository. Please check
+# the `language` matrix defined below to confirm you have the correct set of
+# supported CodeQL languages.
+#
+name: "CodeQL Advanced"
+
+on:
+ push:
+ branches: [ "develop" ]
+ pull_request:
+ branches: [ "develop" ]
+ schedule:
+ - cron: '20 7 * * 0'
+
+jobs:
+ analyze:
+ name: Analyze (${{ matrix.language }})
+ # Runner size impacts CodeQL analysis time. To learn more, please see:
+ # - https://gh.io/recommended-hardware-resources-for-running-codeql
+ # - https://gh.io/supported-runners-and-hardware-resources
+ # - https://gh.io/using-larger-runners (GitHub.com only)
+ # Consider using larger runners or machines with greater resources for possible analysis time improvements.
+ runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
+ permissions:
+ # required for all workflows
+ security-events: write
+
+ # required to fetch internal or private CodeQL packs
+ packages: read
+
+ # only required for workflows in private repositories
+ actions: read
+ contents: read
+
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - language: actions
+ build-mode: none
+ - language: javascript-typescript
+ build-mode: none
+ # CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'
+ # Use `c-cpp` to analyze code written in C, C++ or both
+ # Use 'java-kotlin' to analyze code written in Java, Kotlin or both
+ # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
+ # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
+ # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
+ # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
+ # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ # Add any setup steps before running the `github/codeql-action/init` action.
+ # This includes steps like installing compilers or runtimes (`actions/setup-node`
+ # or others). This is typically only required for manual builds.
+ # - name: Setup runtime (example)
+ # uses: actions/setup-example@v1
+
+ # Initializes the CodeQL tools for scanning.
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v3
+ with:
+ languages: ${{ matrix.language }}
+ build-mode: ${{ matrix.build-mode }}
+ # If you wish to specify custom queries, you can do so here or in a config file.
+ # By default, queries listed here will override any specified in a config file.
+ # Prefix the list here with "+" to use these queries and those in the config file.
+
+ # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
+ # queries: security-extended,security-and-quality
+
+ # If the analyze step fails for one of the languages you are analyzing with
+ # "We were unable to automatically build your code", modify the matrix above
+ # to set the build mode to "manual" for that language. Then modify this step
+ # to build your code.
+ # ℹ️ Command-line programs to run using the OS shell.
+ # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
+ - if: matrix.build-mode == 'manual'
+ shell: bash
+ run: |
+ echo 'If you are using a "manual" build mode for one or more of the' \
+ 'languages you are analyzing, replace this with the commands to build' \
+ 'your code, for example:'
+ echo ' make bootstrap'
+ echo ' make release'
+ exit 1
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v3
+ with:
+ category: "/language:${{matrix.language}}"
diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml
index 3afb9811c..c12db78c9 100644
--- a/.github/workflows/dev.yml
+++ b/.github/workflows/dev.yml
@@ -1,9 +1,9 @@
name: Dev
on:
push:
- branches-ignore:
- - 'develop'
- - 'feature/update**'
+ branches: [ develop ]
+ pull_request:
+ branches: [ develop ]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
@@ -15,7 +15,73 @@ env:
IMAGE_NAME: ${{ github.repository_owner }}/notes
TEST_TAG: ${{ github.repository_owner }}/notes:test
+permissions:
+ pull-requests: write # for PR comments
+
jobs:
+ report-electron-size:
+ name: Report Electron size
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout the repository
+ uses: actions/checkout@v4
+
+ - name: Set up node & dependencies
+ uses: actions/setup-node@v4
+ with:
+ node-version: 22
+ cache: "npm"
+
+ - run: npm ci
+
+ - name: Run the build
+ uses: ./.github/actions/build-electron
+ with:
+ os: linux
+ arch: x64
+ shell: bash
+ forge_platform: linux
+
+ - name: Run the Electron size report
+ uses: ./.github/actions/report-size
+ with:
+ paths: 'upload/**/*'
+ onlyDiff: 'true'
+ branch: 'develop'
+ header: 'Electron size report'
+ unit: "MB"
+ ghToken: ${{ secrets.GITHUB_TOKEN }}
+ report-server-size:
+ name: Report server size
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout the repository
+ uses: actions/checkout@v4
+
+ - name: Set up node & dependencies
+ uses: actions/setup-node@v4
+ with:
+ node-version: 22
+ cache: "npm"
+
+ - run: npm ci
+
+ - name: Run the build
+ uses: ./.github/actions/build-server
+ with:
+ os: linux
+ arch: x64
+
+ - name: Run the server size report
+ uses: ./.github/actions/report-size
+ with:
+ paths: 'upload/**/*'
+ onlyDiff: 'true'
+ branch: 'develop'
+ header: 'Server size report'
+ unit: "MB"
+ ghToken: ${{ secrets.GITHUB_TOKEN }}
+
test_dev:
name: Test development
runs-on: ubuntu-latest
@@ -26,13 +92,17 @@ jobs:
- name: Set up node & dependencies
uses: actions/setup-node@v4
with:
- node-version: 20
+ node-version: 22
cache: "npm"
- run: npm ci
- name: Run the TypeScript build
run: npx tsc
+
+ - name: Run the unit tests
+ run: npm run test
+
build_docker:
name: Build Docker image
runs-on: ubuntu-latest
@@ -40,22 +110,16 @@ jobs:
- test_dev
steps:
- uses: actions/checkout@v4
- - name: Set up node & dependencies
- uses: actions/setup-node@v4
- with:
- node-version: 20
- cache: "npm"
- - run: npm ci
- - name: Run the TypeScript build
- run: npx tsc
- - name: Create server-package.json
- run: cat package.json | grep -v electron > server-package.json
+ - name: Install dependencies
+ run: npm ci
+ - name: Update build info
+ run: npm run chore:update-build-info
- uses: docker/setup-buildx-action@v3
- uses: docker/build-push-action@v6
with:
context: .
cache-from: type=gha
- cache-to: type=gha,mode=max
+ cache-to: type=gha,mode=max
test_docker:
name: Check Docker build
runs-on: ubuntu-latest
@@ -69,7 +133,13 @@ jobs:
steps:
- name: Checkout the repository
uses: actions/checkout@v4
-
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Update build info
+ run: npm run chore:update-build-info
+
- name: Set IMAGE_NAME to lowercase
run: echo "IMAGE_NAME=${IMAGE_NAME,,}" >> $GITHUB_ENV
- name: Set TEST_TAG to lowercase
@@ -78,20 +148,6 @@ jobs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- - name: Set up node & dependencies
- uses: actions/setup-node@v4
- with:
- node-version: 20
- cache: "npm"
-
- - run: npm ci
-
- - name: Run the TypeScript build
- run: npx tsc
-
- - name: Create server-package.json
- run: cat package.json | grep -v electron > server-package.json
-
- name: Build and export to Docker
uses: docker/build-push-action@v6
with:
@@ -101,12 +157,12 @@ jobs:
tags: ${{ env.TEST_TAG }}
cache-from: type=gha
cache-to: type=gha,mode=max
-
+
- name: Validate container run output
run: |
CONTAINER_ID=$(docker run -d --log-driver=journald --rm --name trilium_local ${{ env.TEST_TAG }})
echo "Container ID: $CONTAINER_ID"
-
+
- name: Wait for the healthchecks to pass
uses: stringbean/docker-healthcheck-action@v3
with:
diff --git a/.github/workflows/main-docker.yml b/.github/workflows/main-docker.yml
index 0c1be531a..755956fb1 100644
--- a/.github/workflows/main-docker.yml
+++ b/.github/workflows/main-docker.yml
@@ -45,7 +45,7 @@ jobs:
- name: Set up node & dependencies
uses: actions/setup-node@v4
with:
- node-version: 20
+ node-version: 22
cache: "npm"
- name: Install npm dependencies
@@ -57,9 +57,6 @@ jobs:
- name: Run the TypeScript build
run: npx tsc
- - name: Create server-package.json
- run: cat package.json | grep -v electron > server-package.json
-
- name: Build and export to Docker
uses: docker/build-push-action@v6
with:
@@ -134,6 +131,13 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v4
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Update build info
+ run: npm run chore:update-build-info
+
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
@@ -154,18 +158,6 @@ jobs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
-
- - name: Set up node & dependencies
- uses: actions/setup-node@v4
- with:
- node-version: 20
- cache: "npm"
- - run: npm ci
- - name: Run the TypeScript build
- run: npx tsc
- - name: Create server-package.json
- run: cat package.json | grep -v electron > server-package.json
-
- name: Login to GHCR
uses: docker/login-action@v3
with:
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
deleted file mode 100644
index b469ac79b..000000000
--- a/.github/workflows/main.yml
+++ /dev/null
@@ -1,119 +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
-
- # Set up certificates and keychain for macOS
- - name: Install Apple Certificates
- if: matrix.os.name == 'macos'
- env:
- APP_CERTIFICATE_BASE64: ${{ secrets.APPLE_APP_CERTIFICATE_BASE64 }}
- APP_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_APP_CERTIFICATE_PASSWORD }}
- INSTALLER_CERTIFICATE_BASE64: ${{ secrets.APPLE_INSTALLER_CERTIFICATE_BASE64 }}
- INSTALLER_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_INSTALLER_CERTIFICATE_PASSWORD }}
- KEYCHAIN_PASSWORD: ${{ github.run_id }}
- run: |
- # Create keychain
- security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
- security default-keychain -s build.keychain
- security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
- security set-keychain-settings -t 3600 -u build.keychain
-
- # Import application certificate
- echo "$APP_CERTIFICATE_BASE64" | base64 --decode > application.p12
- security import application.p12 -k build.keychain -P "$APP_CERTIFICATE_PASSWORD" -T /usr/bin/codesign
- rm application.p12
-
- # Import installer certificate
- echo "$INSTALLER_CERTIFICATE_BASE64" | base64 --decode > installer.p12
- security import installer.p12 -k build.keychain -P "$INSTALLER_CERTIFICATE_PASSWORD" -T /usr/bin/codesign
- rm installer.p12
-
- # Update keychain settings
- security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" build.keychain
-
- - 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_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
diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml
index c339fd37d..83b9c436c 100644
--- a/.github/workflows/nightly.yml
+++ b/.github/workflows/nightly.yml
@@ -2,9 +2,16 @@ name: Nightly Release
on:
# This can be used to automatically publish nightlies at UTC nighttime
schedule:
- - 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
workflow_dispatch:
+ push:
+ branches:
+ - renovate/electron-forge*
+ pull_request:
+ paths:
+ - .github/actions/build-electron/*
+ - forge.config.cjs
env:
GITHUB_UPLOAD_URL: https://uploads.github.com/repos/TriliumNext/Notes/releases/179589950/assets{?name,label}
GITHUB_RELEASE_ID: 179589950
@@ -20,22 +27,24 @@ jobs:
os:
- name: macos
image: macos-latest
- extension: [dmg, zip]
+ shell: bash
+ forge_platform: darwin
- name: linux
image: ubuntu-latest
- extension: [deb, rpm, zip, flatpak]
+ shell: bash
+ forge_platform: linux
- name: windows
- image: windows-latest
- extension: [exe, zip]
+ image: win-signing
+ shell: cmd
+ forge_platform: win32
runs-on: ${{ matrix.os.image }}
steps:
- uses: actions/checkout@v4
- name: Set up node & dependencies
uses: actions/setup-node@v4
with:
- node-version: 20
+ node-version: 22
- name: Install dependencies
- shell: bash
run: npm ci
- name: Update nightly version
run: npm run chore:ci-update-nightly-version
@@ -44,10 +53,21 @@ jobs:
with:
os: ${{ matrix.os.name }}
arch: ${{ matrix.arch }}
- extension: ${{ join(matrix.os.extension, ' ') }}
+ shell: ${{ matrix.os.shell }}
+ forge_platform: ${{ matrix.os.forge_platform }}
+ 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 }}
+ WINDOWS_SIGN_EXECUTABLE: ${{ vars.WINDOWS_SIGN_EXECUTABLE }}
- name: Publish release
uses: softprops/action-gh-release@v2
+ if: ${{ github.event_name != 'pull_request' }}
with:
make_latest: false
prerelease: true
@@ -57,6 +77,13 @@ jobs:
tag_name: nightly
name: Nightly Build
+ - name: Publish artifacts
+ uses: actions/upload-artifact@v4
+ if: ${{ github.event_name == 'pull_request' }}
+ with:
+ name: TriliumNextNotes ${{ matrix.os.name }} ${{ matrix.arch }}
+ path: upload
+
nightly-server:
name: Deploy server nightly
strategy:
@@ -80,6 +107,7 @@ jobs:
- name: Publish release
uses: softprops/action-gh-release@v2
+ if: ${{ github.event_name != 'pull_request' }}
with:
make_latest: false
prerelease: true
diff --git a/.github/workflows/release-winget.yml b/.github/workflows/release-winget.yml
new file mode 100644
index 000000000..27b57e19d
--- /dev/null
+++ b/.github/workflows/release-winget.yml
@@ -0,0 +1,20 @@
+name: Release to winget
+on:
+ release:
+ types: [ published ]
+ workflow_dispatch:
+ inputs:
+ release_tag:
+ description: 'Git tag to release from'
+ type: string
+ required: true
+jobs:
+ release-winget:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Publish to WinGet
+ uses: vedantmgoyal9/winget-releaser@main
+ with:
+ identifier: TriliumNext.Notes
+ token: ${{ secrets.token }}
+ release-tag: ${{ github.event.inputs.release_tag || github.event.release.tag_name }}
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index dc523893b..458861c9d 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -3,7 +3,6 @@ on:
push:
tags:
- "v*"
- workflow_dispatch:
permissions:
contents: write
concurrency:
@@ -20,26 +19,30 @@ jobs:
os:
- name: macos
image: macos-latest
- extension: [dmg, zip]
+ shell: bash
+ forge_platform: darwin
- name: linux
image: ubuntu-latest
- extension: [deb, rpm, zip, flatpak]
+ shell: bash
+ forge_platform: linux
- name: windows
- image: windows-latest
- extension: [exe, zip]
+ image: win-signing
+ shell: cmd
+ forge_platform: win32
runs-on: ${{ matrix.os.image }}
steps:
- uses: actions/checkout@v4
- name: Set up node & dependencies
uses: actions/setup-node@v4
with:
- node-version: 20
+ node-version: 22
- name: Run the build
uses: ./.github/actions/build-electron
with:
os: ${{ matrix.os.name }}
arch: ${{ matrix.arch }}
- extension: ${{ join(matrix.os.extension, ' ') }}
+ shell: ${{ matrix.os.shell }}
+ forge_platform: ${{ matrix.os.forge_platform }}
env:
APPLE_APP_CERTIFICATE_BASE64: ${{ secrets.APPLE_APP_CERTIFICATE_BASE64 }}
APPLE_APP_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_APP_CERTIFICATE_PASSWORD }}
@@ -48,15 +51,15 @@ jobs:
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
+ WINDOWS_SIGN_EXECUTABLE: ${{ vars.WINDOWS_SIGN_EXECUTABLE }}
- - name: Publish release
- uses: softprops/action-gh-release@v2
+ - name: Upload the artifact
+ uses: actions/upload-artifact@v4
with:
- draft: true
- fail_on_unmatched_files: true
- files: upload/*.*
+ name: release-desktop-${{ matrix.os.name }}-${{ matrix.arch }}
+ path: upload/*.*
- build_linux_server-x64:
+ build_server:
name: Build Linux Server
strategy:
fail-fast: false
@@ -77,9 +80,32 @@ jobs:
os: linux
arch: ${{ matrix.arch }}
+ - name: Upload the artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: release-server-linux-${{ matrix.arch }}
+ path: upload/*.*
+
+ publish_release:
+ name: Publish release
+ runs-on: ubuntu-latest
+ needs:
+ - make-electron
+ - build_server
+ steps:
+ - run: mkdir upload
+
+ - name: Download all artifacts
+ uses: actions/download-artifact@v4
+ with:
+ merge-multiple: true
+ pattern: release-*
+ path: upload
+
- name: Publish release
uses: softprops/action-gh-release@v2
with:
- draft: true
+ draft: false
+ body_path: docs/Release Notes/Release Notes/${{ github.ref_name }}.md
fail_on_unmatched_files: true
files: upload/*.*
diff --git a/.gitignore b/.gitignore
index bc1575665..b8b091d80 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
.DS_Store
node_modules/
dist/
+upload/
build/
coverage/
src/public/app-dist/
@@ -11,6 +12,7 @@ po-*/
.flatpak-builder/
*.db
+!test/**/*.db
!integration-tests/db/document.db
!integration-tests/db/config.ini
integration-tests/db/log
@@ -25,6 +27,7 @@ server-package.json
.idea/shelf/
data/
data-test/
+data-demo/
tmp/
.eslintcache
@@ -35,4 +38,13 @@ images/app-icons/mac/*.png
/playwright-report/
/blob-report/
/playwright/.cache/
-/playwright/.auth/
\ No newline at end of file
+/playwright/.auth/
+
+data-docs/backup
+data-docs/log
+data-docs/session
+data-docs/session_secret.txt
+data-docs/document.*
+
+# Webpack
+webpack-stats.json
\ No newline at end of file
diff --git a/.prettierignore b/.prettierignore
deleted file mode 100644
index 42a133ba8..000000000
--- a/.prettierignore
+++ /dev/null
@@ -1,5 +0,0 @@
-*.html
-*.md
-*.yml
-libraries/*
-docs/*
\ No newline at end of file
diff --git a/.prettierrc b/.prettierrc
deleted file mode 100644
index 036c81de1..000000000
--- a/.prettierrc
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- "printWidth": 200,
- "tabWidth": 4,
- "useTabs": false,
- "semi": true,
- "singleQuote": false,
- "quoteProps": "as-needed",
- "trailingComma": "none",
- "bracketSpacing": true,
- "arrowParens": "always",
- "proseWrap": "preserve",
- "htmlWhitespaceSensitivity": "css",
- "endOfLine": "lf",
- "overrides": [
- {
- "files": ["*.json"],
- "options": {
- "tabWidth": 2
- }
- }
- ]
-}
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
index 7fc3d9975..8823f3cdd 100644
--- a/.vscode/extensions.json
+++ b/.vscode/extensions.json
@@ -1,3 +1,11 @@
{
- "recommendations": ["lokalise.i18n-ally", "editorconfig.editorconfig"]
+ "recommendations": [
+ "lokalise.i18n-ally",
+ "editorconfig.editorconfig",
+ "vitest.explorer",
+ "ms-playwright.playwright",
+ "tobermory.es6-string-html",
+ "dbaeumer.vscode-eslint",
+ "yzhang.markdown-all-in-one"
+ ]
}
diff --git a/.vscode/launch.json b/.vscode/launch.json
index cf21b9ce1..f8d4780a1 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -5,8 +5,8 @@
{
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
- "name": "nodemon server:start",
- "program": "${workspaceFolder}/src/main",
+ "name": "nodemon start-server",
+ "program": "${workspaceFolder}/src/www",
"request": "launch",
"restart": true,
"runtimeExecutable": "nodemon",
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 0733583d4..dd0be9432 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -19,5 +19,12 @@
"[css]": {
"editor.defaultFormatter": "vscode.css-language-features"
},
- "npm.exclude": ["**/build", "**/dist", "**/out/**"]
+ "npm.exclude": [
+ "**/build",
+ "**/dist",
+ "**/out/**"
+ ],
+ "[xml]": {
+ "editor.defaultFormatter": "redhat.vscode-xml"
+ }
}
diff --git a/Dockerfile b/Dockerfile
index 365e4d07f..635a44d3b 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,62 +1,49 @@
# Build stage
FROM node:22.14.0-bullseye-slim AS builder
-# Configure build dependencies in a single layer
-RUN apt-get update && apt-get install -y --no-install-recommends \
- autoconf \
- automake \
- g++ \
- gcc \
- libtool \
- make \
- nasm \
- libpng-dev \
- python3 \
- && rm -rf /var/lib/apt/lists/*
-
-WORKDIR /usr/src/app
+WORKDIR /usr/src/app/build
# Copy only necessary files for build
COPY . .
-COPY server-package.json package.json
# Build and cleanup in a single layer
-RUN cp -R build/src/* src/. && \
- cp build/docker_healthcheck.js . && \
- rm docker_healthcheck.ts && \
- npm install && \
- npm run build:webpack && \
- npm prune --omit=dev && \
+RUN npm ci && \
+ npm run build:prepare-dist && \
npm cache clean --force && \
- cp -r src/public/app/doc_notes src/public/app-dist/. && \
- rm -rf src/public/app/* && \
- mkdir -p src/public/app/services && \
- cp -r build/src/public/app/services/mime_type_definitions.js src/public/app/services/mime_type_definitions.js && \
- rm src/services/asset_path.ts && \
- rm -r build
+ rm -rf build/node_modules && \
+ mv build/* \
+ start-docker.sh \
+ /usr/src/app/ && \
+ rm -rf \
+ /usr/src/app/build \
+ /tmp/node-compile-cache
+
+#TODO: improve node_modules handling in copy-dist/Dockerfile -> remove duplicated work
+# currently copy-dist will copy certain node_module folders, but in the Dockerfile we delete them again (to keep image size down),
+# as we install necessary dependencies in runtime buildstage anyways
# Runtime stage
FROM node:22.14.0-bullseye-slim
-# Install only runtime dependencies
-RUN apt-get update && apt-get install -y --no-install-recommends \
- gosu \
- && rm -rf /var/lib/apt/lists/* && \
- rm -rf /var/cache/apt/*
-
WORKDIR /usr/src/app
-# Copy only necessary files from builder
-COPY --from=builder /usr/src/app/node_modules ./node_modules
-COPY --from=builder /usr/src/app/src ./src
-COPY --from=builder /usr/src/app/db ./db
-COPY --from=builder /usr/src/app/docker_healthcheck.js .
-COPY --from=builder /usr/src/app/start-docker.sh .
-COPY --from=builder /usr/src/app/package.json .
-COPY --from=builder /usr/src/app/config-sample.ini .
-COPY --from=builder /usr/src/app/images ./images
-COPY --from=builder /usr/src/app/translations ./translations
-COPY --from=builder /usr/src/app/libraries ./libraries
+# Install only runtime dependencies
+RUN apt-get update && \
+ apt-get install -y --no-install-recommends \
+ gosu && \
+ rm -rf \
+ /var/lib/apt/lists/* \
+ /var/cache/apt/*
+
+COPY --from=builder /usr/src/app ./
+
+RUN sed -i "/electron/d" package.json && \
+ npm ci --omit=dev && \
+ node --experimental-strip-types ./bin/cleanupNodeModules.ts . --skip-prune-dev-deps && \
+ npm cache clean --force && \
+ rm -rf \
+ /tmp/node-compile-cache \
+ /usr/src/app/bin/cleanupNodeModules.ts
# Configure container
EXPOSE 8080
diff --git a/Dockerfile.alpine b/Dockerfile.alpine
index 36d6f0b7b..88a450723 100644
--- a/Dockerfile.alpine
+++ b/Dockerfile.alpine
@@ -1,38 +1,26 @@
# Build stage
FROM node:22.14.0-alpine AS builder
-# Configure build dependencies
-RUN apk add --no-cache --virtual .build-dependencies \
- autoconf \
- automake \
- g++ \
- gcc \
- libtool \
- make \
- nasm \
- libpng-dev \
- python3
-
-WORKDIR /usr/src/app
+WORKDIR /usr/src/app/build
# Copy only necessary files for build
COPY . .
-COPY server-package.json package.json
# Build and cleanup in a single layer
-RUN cp -R build/src/* src/. && \
- cp build/docker_healthcheck.js . && \
- rm docker_healthcheck.ts && \
- npm install && \
- npm run build:webpack && \
- npm prune --omit=dev && \
+RUN npm ci && \
+ npm run build:prepare-dist && \
npm cache clean --force && \
- cp -r src/public/app/doc_notes src/public/app-dist/. && \
- rm -rf src/public/app && \
- mkdir -p src/public/app/services && \
- cp -r build/src/public/app/services/mime_type_definitions.js src/public/app/services/mime_type_definitions.js && \
- rm src/services/asset_path.ts && \
- rm -r build
+ rm -rf build/node_modules && \
+ mv build/* \
+ start-docker.sh \
+ /usr/src/app/ && \
+ rm -rf \
+ /usr/src/app/build \
+ /tmp/node-compile-cache
+
+#TODO: improve node_modules handling in copy-dist/Dockerfile -> remove duplicated work
+# currently copy-dist will copy certain node_module folders, but in the Dockerfile we delete them again (to keep image size down),
+# as we install necessary dependencies in runtime buildstage anyways
# Runtime stage
FROM node:22.14.0-alpine
@@ -42,17 +30,15 @@ RUN apk add --no-cache su-exec shadow
WORKDIR /usr/src/app
-# Copy only necessary files from builder
-COPY --from=builder /usr/src/app/node_modules ./node_modules
-COPY --from=builder /usr/src/app/src ./src
-COPY --from=builder /usr/src/app/db ./db
-COPY --from=builder /usr/src/app/docker_healthcheck.js .
-COPY --from=builder /usr/src/app/start-docker.sh .
-COPY --from=builder /usr/src/app/package.json .
-COPY --from=builder /usr/src/app/config-sample.ini .
-COPY --from=builder /usr/src/app/images ./images
-COPY --from=builder /usr/src/app/translations ./translations
-COPY --from=builder /usr/src/app/libraries ./libraries
+COPY --from=builder /usr/src/app ./
+
+RUN sed -i "/electron/d" package.json && \
+ npm ci --omit=dev && \
+ node --experimental-strip-types ./bin/cleanupNodeModules.ts . --skip-prune-dev-deps && \
+ npm cache clean --force && \
+ rm -rf \
+ /tmp/node-compile-cache \
+ /usr/src/app/bin/cleanupNodeModules.ts
# Add application user
RUN adduser -s /bin/false node; exit 0
diff --git a/README.md b/README.md
index 0170c8135..bb6e45836 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# TriliumNext Notes
- 
+  
[English](./README.md) | [Chinese](./README-ZH_CN.md) | [Russian](./README.ru.md) | [Japanese](./README.ja.md) | [Italian](./README.it.md) | [Spanish](./README.es.md)
@@ -16,7 +16,7 @@ See [screenshots](https://triliumnext.github.io/Docs/Wiki/screenshot-tour) for q
### Migrating from Trilium?
-There are no special migration steps to migrate from a zadam/Trilium instance to a TriliumNext/Notes instance. Just upgrade your Trilium instance to the latest version and [install TriliumNext/Notes as usual](#-installation)
+There are no special migration steps to migrate from a zadam/Trilium instance to a TriliumNext/Notes instance. Simply [install TriliumNext/Notes](#-installation) as usual and it will use your existing database.
Versions up to and including [v0.90.4](https://github.com/TriliumNext/Notes/releases/tag/v0.90.4) are compatible with the latest zadam/trilium version of [v0.63.7](https://github.com/zadam/trilium/releases/tag/v0.63.7). Any later versions of TriliumNext have their sync versions incremented.
@@ -37,6 +37,7 @@ Feel free to join our official conversations. We would love to hear what feature
* Fast and easy [navigation between notes](https://triliumnext.github.io/Docs/Wiki/note-navigation), full text search and [note hoisting](https://triliumnext.github.io/Docs/Wiki/note-hoisting)
* Seamless [note versioning](https://triliumnext.github.io/Docs/Wiki/note-revisions)
* Note [attributes](https://triliumnext.github.io/Docs/Wiki/attributes) can be used for note organization, querying and advanced [scripting](https://triliumnext.github.io/Docs/Wiki/scripts)
+* Direct OpenID and TOTP integration for more secure login
* [Synchronization](https://triliumnext.github.io/Docs/Wiki/synchronization) with self-hosted sync server
* there's a [3rd party service for hosting synchronisation server](https://trilium.cc/paid-hosting)
* [Sharing](https://triliumnext.github.io/Docs/Wiki/sharing) (publishing) notes to public internet
@@ -65,24 +66,15 @@ To use TriliumNext on your desktop machine (Linux, MacOS, and Windows) you have
* Download the binary release for your platform from the [latest release page](https://github.com/TriliumNext/Notes/releases/latest), unzip the package and run the ```trilium``` executable.
* Access TriliumNext via the web interface of a server installation (see below)
* Currently only the latest versions of Chrome & Firefox are supported (and tested).
-* (Coming Soon) TriliumNext will also be provided as a Flatpak
-
-#### MacOS
-Currently when running TriliumNext/Notes on MacOS, you may get the following error:
-> Apple could not verify "TriliumNext Notes" is free of malware and may harm your Mac or compromise your privacy.
-
-You will need to run the command on your shell to resolve the error (documented [here](https://github.com/TriliumNext/Notes/issues/329#issuecomment-2287164137)):
-
-```bash
-xattr -c "/path/to/Trilium Next.app"
-```
+* TriliumNext is also provided as a Flatpak, but not yet published on FlatHub.
### Mobile
-To use TriliumNext on a mobile device:
+To use TriliumNext on a mobile device, you can use a mobile web browser to access the mobile interface of a server installation (see below).
-* Use a mobile web browser to access the mobile interface of a server installation (see below)
-* Use of a mobile app is not yet supported ([see here](https://github.com/TriliumNext/Notes/issues/72)) to track mobile improvements.
+If you prefer a native Android app, you can use [TriliumDroid](https://apt.izzysoft.de/fdroid/index/apk/eu.fliegendewurst.triliumdroid). Report bugs and missing features at [their repository](https://github.com/FliegendeWurst/TriliumDroid).
+
+See issue https://github.com/TriliumNext/Notes/issues/72 for more information on mobile app support.
### Server
@@ -105,9 +97,11 @@ npm install
npm run server:start
```
+For more details, see the [development docs](https://github.com/TriliumNext/Notes/blob/develop/docs/Developer%20Guide/Developer%20Guide/Building%20and%20deployment/Running%20a%20development%20build.md).
+
### Documentation
-Head on over to our [Docs repo](https://github.com/TriliumNext/Docs)
+See the [documentation guide](https://github.com/TriliumNext/Notes/blob/develop/docs/Developer%20Guide/Developer%20Guide/Documentation.md) for details.
## 👏 Shoutouts
diff --git a/_check_ts_progress.sh b/_check_ts_progress.sh
deleted file mode 100755
index 7332a6054..000000000
--- a/_check_ts_progress.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/usr/bin/env bash
-
-cd src/public
-echo Summary
-cloc HEAD \
- --git --md \
- --include-lang=javascript,typescript
-
-echo By file
-cloc HEAD \
- --git --md \
- --include-lang=javascript,typescript \
- --by-file | grep \.js\|
\ No newline at end of file
diff --git a/bin/build-docker.sh b/bin/build-docker.sh
index a765930db..d95c289d4 100755
--- a/bin/build-docker.sh
+++ b/bin/build-docker.sh
@@ -5,11 +5,6 @@ set -e # Fail on any command error
VERSION=`jq -r ".version" package.json`
SERIES=${VERSION:0:4}-latest
-cat package.json | grep -v electron > server-package.json
-
-echo "Compiling typescript..."
-npx tsc
-
sudo docker build -t triliumnext/notes:$VERSION --network host -t triliumnext/notes:$SERIES .
if [[ $VERSION != *"beta"* ]]; then
diff --git a/bin/build-server.sh b/bin/build-server.sh
index 47bfe9397..93102737c 100755
--- a/bin/build-server.sh
+++ b/bin/build-server.sh
@@ -21,56 +21,53 @@ fi
echo "Selected Arch: $ARCH"
# Set Node.js version and architecture-specific filename
-NODE_VERSION=20.15.1
-NODE_ARCH=$ARCH
+NODE_VERSION=22.14.0
-# Debug output
-echo "Node arch: $NODE_ARCH"
+BUILD_DIR="./build"
+DIST_DIR="./dist"
+CLEANUP_SCRIPT="./bin/cleanupNodeModules.ts"
-# Special case for x64 in Node.js downloads
-if [ "$NODE_ARCH" = "x64" ]; then
- NODE_FILENAME="x64"
-elif [ "$NODE_ARCH" = "arm64" ]; then
- NODE_FILENAME="arm64"
-fi
-# Debug output
-echo "Node filename: $NODE_FILENAME"
+# Trigger the build
+echo "Build start"
+npm run build:prepare-dist
+echo "Build finished"
-PKG_DIR=dist/trilium-linux-${ARCH}-server
-echo "Package directory: $PKG_DIR"
+# pruning of unnecessary files and devDeps in node_modules
+node --experimental-strip-types $CLEANUP_SCRIPT $BUILD_DIR
-if [ "$1" != "DONTCOPY" ]
-then
- # Need to modify copy-trilium.sh to accept the target directory
- ./bin/copy-trilium.sh "$PKG_DIR"
-fi
+NODE_FILENAME=node-v${NODE_VERSION}-linux-${ARCH}
-cd dist
-wget https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-${NODE_FILENAME}.tar.xz
-tar xfJ node-v${NODE_VERSION}-linux-${NODE_FILENAME}.tar.xz
-rm node-v${NODE_VERSION}-linux-${NODE_FILENAME}.tar.xz
+echo "Downloading Node.js runtime $NODE_FILENAME..."
+cd $BUILD_DIR
+wget -qO- https://nodejs.org/dist/v${NODE_VERSION}/${NODE_FILENAME}.tar.xz | tar xfJ -
+mv $NODE_FILENAME node
cd ..
-mv dist/node-v${NODE_VERSION}-linux-${NODE_FILENAME} $PKG_DIR/node
-rm -r $PKG_DIR/node/lib/node_modules/npm
-rm -r $PKG_DIR/node/include/node
+rm -r $BUILD_DIR/node/lib/node_modules/{npm,corepack} \
+ $BUILD_DIR/node/bin/{npm,npx,corepack} \
+ $BUILD_DIR/node/CHANGELOG.md \
+ $BUILD_DIR/node/include/node \
+ $BUILD_DIR/node_modules/electron* \
+ $BUILD_DIR/electron*.{js,map}
-rm -r $PKG_DIR/node_modules/electron*
-rm -r $PKG_DIR/electron*.js
+printf "#!/bin/sh\n./node/bin/node src/main\n" > $BUILD_DIR/trilium.sh
+chmod 755 $BUILD_DIR/trilium.sh
-printf "#!/bin/sh\n./node/bin/node src/main" > $PKG_DIR/trilium.sh
-chmod 755 $PKG_DIR/trilium.sh
-
-cp bin/tpl/anonymize-database.sql $PKG_DIR/
-
-cp -r translations $PKG_DIR/
-cp -r dump-db $PKG_DIR/
-rm -rf $PKG_DIR/dump-db/node_modules
+# TriliumNextTODO: is this still required? If yes → move to copy-dist/copy-trilium
+cp bin/tpl/anonymize-database.sql $BUILD_DIR/
VERSION=`jq -r ".version" package.json`
-cd dist
-tar cJf trilium-linux-${ARCH}-server-${VERSION}.tar.xz trilium-linux-${ARCH}-server
+ARCHIVE_NAME="TriliumNextNotes-Server-${VERSION}-linux-${ARCH}"
+echo "Creating Archive $ARCHIVE_NAME..."
+
+mkdir $DIST_DIR
+cp -r "$BUILD_DIR" "$DIST_DIR/$ARCHIVE_NAME"
+cd $DIST_DIR
+tar cJf "$ARCHIVE_NAME.tar.xz" "$ARCHIVE_NAME"
+rm -rf "$ARCHIVE_NAME"
+
+echo "Server Build Completed!"
\ No newline at end of file
diff --git a/bin/build.sh b/bin/build.sh
deleted file mode 100755
index 7fb41cfcb..000000000
--- a/bin/build.sh
+++ /dev/null
@@ -1,53 +0,0 @@
-#!/usr/bin/env bash
-
-set -e # Fail on any command error
-
-if ! command -v jq &> /dev/null; then
- echo "Missing command: jq"
- exit 1
-fi
-
-if ! command -v fakeroot &> /dev/null; then
- echo "Missing command: fakeroot"
- exit 1
-fi
-
-if ! command -v dpkg-deb &> /dev/null; then
- echo "Missing command: dpkg-deb"
- exit 1
-fi
-
-if dpkg-deb 2>&1 | grep BusyBox &> /dev/null; then
- echo "The dpkg-deb binary provided by BusyBox is not compatible. The Debian tool needs to be used instead."
- exit 1
-fi
-
-if ! command -v wine &> /dev/null; then
- echo "Missing command: wine"
- exit 1
-fi
-
-echo "Deleting existing builds"
-
-rm -rf dist/*
-
-SRC_DIR=dist/trilium-src
-
-bin/copy-trilium.sh $SRC_DIR
-
-# we'll just copy the same SRC dir to all the builds so we don't have to do npm install in each separately
-cp -r $SRC_DIR ./dist/trilium-linux-x64-src
-cp -r $SRC_DIR ./dist/trilium-linux-x64-server
-cp -r $SRC_DIR ./dist/trilium-windows-x64-src
-cp -r $SRC_DIR ./dist/trilium-mac-x64-src
-cp -r $SRC_DIR ./dist/trilium-mac-arm64-src
-
-bin/build-win-x64.sh DONTCOPY
-
-bin/build-mac-x64.sh DONTCOPY
-
-bin/build-mac-arm64.sh DONTCOPY
-
-bin/build-linux-x64.sh DONTCOPY
-
-bin/build-server.sh DONTCOPY
diff --git a/bin/cleanupNodeModules.ts b/bin/cleanupNodeModules.ts
new file mode 100644
index 000000000..bb3e90331
--- /dev/null
+++ b/bin/cleanupNodeModules.ts
@@ -0,0 +1,109 @@
+import fs from "fs-extra";
+import path from "path";
+import type { Dirent } from "fs-extra";
+import { execSync } from "node:child_process";
+
+/**
+ * Example usage with node >= v22:
+ * node --experimental-strip-types bin/cleanupNodeModules.ts /path/to/build/folder [--skip-prune-dev-deps]
+ * Example usage with tsx:
+ * tsx bin/cleanupNodeModules.ts /path/to/build/folder [--skip-prune-dev-deps]
+ */
+function main() {
+
+ if (process.argv.length > 4 || process.argv.length < 3) {
+ console.error("Usage: cleanupNodeModules.ts [path-to-build-folder] [--skip-prune-dev-deps]");
+ process.exit(1);
+ }
+
+ const basePath = process.argv[2];
+ const pruneDevDeps = process.argv[3] !== "--skip-prune-dev-deps";
+
+ if (!fs.existsSync(basePath)) {
+ console.error(`Supplied path '${basePath}' does not exist. Aborting.`);
+ process.exit(1);
+ }
+
+ console.log(`Starting pruning of node_modules ${!pruneDevDeps ? '(skipping npm pruning)' : ''} in '${basePath}'...`);
+ cleanupNodeModules(basePath, pruneDevDeps);
+ console.log("Successfully pruned node_modules.");
+}
+
+function cleanupNodeModules(basePath: string, pruneDevDeps: boolean = true) {
+
+ // This needs to run for the server and Docker build,
+ // but needs to be skipped for electron-forge: its
+ // built-in pruning takes care of it already
+ if (pruneDevDeps) {
+ execSync(`npm ci --omit=dev --prefix ${basePath}`);
+ }
+
+ const nodeModulesDirPath = path.join(basePath, "node_modules");
+ const nodeModulesContent = fs.readdirSync(nodeModulesDirPath, { recursive: true, withFileTypes: true });
+ //const libDir = fs.readdirSync(path.join(basePath, "./libraries"), { recursive: true, withFileTypes: true });
+
+ /**
+ * Delete unnecessary folders
+ */
+ const filterableDirs = new Set([
+ "demo",
+ "demos",
+ "doc",
+ "docs",
+ "example",
+ "examples",
+ "test",
+ "tests"
+ ]);
+
+ nodeModulesContent
+ .filter(el => el.isDirectory() && filterableDirs.has(el.name))
+ .forEach(dir => removeDirent(dir));
+
+ /**
+ * Delete unnecessary files based on file extension
+ * TODO filter out useless (README).md files
+ */
+ const filterableFileExt = new Set([
+ "ts",
+ "map"
+ ]);
+
+ nodeModulesContent
+ // TriliumNextTODO: check if we can improve this naive file ext matching, without introducing any additional dependency
+ .filter(el => el.isFile() && filterableFileExt.has(el.name.split(".").at(-1) || ""))
+ .forEach(dir => removeDirent(dir));
+
+
+ /**
+ * Delete specific unnecessary folders
+ * TODO: check if we want removeSync to throw an error, if path does not exist anymore -> currently it will silently fail
+ */
+ const extraFoldersDelete = new Set([
+ path.join(nodeModulesDirPath, ".bin"),
+ path.join(nodeModulesDirPath, "@excalidraw", "excalidraw", "dist", "dev"),
+ path.join(nodeModulesDirPath, "boxicons", "svg"),
+ path.join(nodeModulesDirPath, "boxicons", "node_modules"),
+ path.join(nodeModulesDirPath, "boxicons", "src"),
+ path.join(nodeModulesDirPath, "boxicons", "iconjar"),
+ path.join(nodeModulesDirPath, "@jimp", "plugin-print", "fonts"),
+ path.join(nodeModulesDirPath, "jimp", "dist", "browser") // missing "@" in front of jimp is not a typo here
+ ]);
+
+ nodeModulesContent
+ .filter(el => el.isDirectory() && extraFoldersDelete.has(path.join(el.parentPath, el.name)))
+ .forEach(dir => removeDirent(dir))
+}
+
+
+function removeDirent(el: Dirent) {
+ const elementToDelete = path.join(el.parentPath, el.name);
+ fs.removeSync(elementToDelete);
+
+ if (process.env.VERBOSE) {
+ console.log(`Deleted ${elementToDelete}`);
+ }
+
+}
+
+main()
\ No newline at end of file
diff --git a/bin/copy-dist.ts b/bin/copy-dist.ts
index 2a2b75d56..404cf0991 100644
--- a/bin/copy-dist.ts
+++ b/bin/copy-dist.ts
@@ -1,9 +1,7 @@
import fs from "fs-extra";
import path from "path";
-const DEST_DIR = "./dist";
-const DEST_DIR_SRC = path.join(DEST_DIR, "src");
-const DEST_DIR_NODE_MODULES = path.join(DEST_DIR, "node_modules");
+const DEST_DIR = "./build";
const VERBOSE = process.env.VERBOSE;
@@ -13,43 +11,40 @@ function log(...args: any[]) {
}
}
-async function copyNodeModuleFileOrFolder(source: string) {
- const adjustedSource = source.substring(13);
- const destination = path.join(DEST_DIR_NODE_MODULES, adjustedSource);
+try {
- log(`Copying ${source} to ${destination}`);
- await fs.ensureDir(path.dirname(destination));
- await fs.copy(source, destination);
-}
-
-const copy = async () => {
- for (const srcFile of fs.readdirSync("build")) {
- const destFile = path.join(DEST_DIR, path.basename(srcFile));
- log(`Copying source ${srcFile} -> ${destFile}.`);
- fs.copySync(path.join("build", srcFile), destFile, { recursive: true });
- }
-
- const filesToCopy = [
- "config-sample.ini",
- "tsconfig.webpack.json",
+ const assetsToCopy = new Set([
+ // copy node_module, to avoid downloading packages a 2nd time during pruning
+ "./node_modules",
+ "./images",
+ "./libraries",
+ "./translations",
+ "./db",
+ "./config-sample.ini",
+ "./package-lock.json",
+ "./package.json",
+ "./LICENSE",
+ "./README.md",
+ "./forge.config.cjs",
+ "./bin/tpl/",
+ "./bin/cleanupNodeModules.ts",
+ "./bin/electron-forge/desktop.ejs",
+ "./bin/electron-forge/sign-windows.cjs",
+ "./src/views/",
"./src/etapi/etapi.openapi.yaml",
- "./src/routes/api/openapi.json"
- ];
- for (const file of filesToCopy) {
- log(`Copying ${file}`);
- await fs.copy(file, path.join(DEST_DIR, file));
- }
+ "./src/routes/api/openapi.json",
+ "./src/public/icon.png",
+ "./src/public/manifest.webmanifest",
+ "./src/public/robots.txt",
+ "./src/public/fonts",
+ "./src/public/stylesheets",
+ "./src/public/translations",
+ "./packages/turndown-plugin-gfm/src"
+ ]);
- const dirsToCopy = ["images", "libraries", "translations", "db"];
- for (const dir of dirsToCopy) {
- log(`Copying ${dir}`);
- await fs.copy(dir, path.join(DEST_DIR, dir));
- }
-
- const srcDirsToCopy = ["./src/public", "./src/views", "./build"];
- for (const dir of srcDirsToCopy) {
- log(`Copying ${dir}`);
- await fs.copy(dir, path.join(DEST_DIR_SRC, path.basename(dir)));
+ for (const asset of assetsToCopy) {
+ log(`Copying ${asset}`);
+ fs.copySync(asset, path.join(DEST_DIR, asset));
}
/**
@@ -58,59 +53,13 @@ const copy = async () => {
const publicDirsToCopy = ["./src/public/app/doc_notes"];
const PUBLIC_DIR = path.join(DEST_DIR, "src", "public", "app-dist");
for (const dir of publicDirsToCopy) {
- await fs.copy(dir, path.join(PUBLIC_DIR, path.basename(dir)));
+ fs.copySync(dir, path.join(PUBLIC_DIR, path.basename(dir)));
}
- const nodeModulesFile = [
- "node_modules/react/umd/react.production.min.js",
- "node_modules/react/umd/react.development.js",
- "node_modules/react-dom/umd/react-dom.production.min.js",
- "node_modules/react-dom/umd/react-dom.development.js",
- "node_modules/katex/dist/katex.min.js",
- "node_modules/katex/dist/contrib/mhchem.min.js",
- "node_modules/katex/dist/contrib/auto-render.min.js",
- "node_modules/@highlightjs/cdn-assets/highlight.min.js",
- "node_modules/@mind-elixir/node-menu/dist/node-menu.umd.cjs"
- ];
+ console.log("Copying complete!")
- for (const file of nodeModulesFile) {
- await copyNodeModuleFileOrFolder(file);
- }
+} catch(err) {
+ console.error("Error during copy:", err)
+ process.exit(1)
+}
- const nodeModulesFolder = [
- "node_modules/@excalidraw/excalidraw/dist/",
- "node_modules/katex/dist/",
- "node_modules/dayjs/",
- "node_modules/boxicons/css/",
- "node_modules/boxicons/fonts/",
- "node_modules/mermaid/dist/",
- "node_modules/jquery/dist/",
- "node_modules/jquery-hotkeys/",
- "node_modules/split.js/dist/",
- "node_modules/panzoom/dist/",
- "node_modules/i18next/",
- "node_modules/i18next-http-backend/",
- "node_modules/jsplumb/dist/",
- "node_modules/vanilla-js-wheel-zoom/dist/",
- "node_modules/mark.js/dist/",
- "node_modules/normalize.css/",
- "node_modules/jquery.fancytree/dist/",
- "node_modules/autocomplete.js/dist/",
- "node_modules/codemirror/lib/",
- "node_modules/codemirror/addon/",
- "node_modules/codemirror/mode/",
- "node_modules/codemirror/keymap/",
- "node_modules/mind-elixir/dist/",
- "node_modules/@highlightjs/cdn-assets/languages",
- "node_modules/@highlightjs/cdn-assets/styles",
- "node_modules/leaflet/dist"
- ];
-
- for (const folder of nodeModulesFolder) {
- await copyNodeModuleFileOrFolder(folder);
- }
-};
-
-copy()
- .then(() => console.log("Copying complete!"))
- .catch((err) => console.error("Error during copy:", err));
diff --git a/bin/copy-trilium.sh b/bin/copy-trilium.sh
deleted file mode 100755
index e1d0e197f..000000000
--- a/bin/copy-trilium.sh
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/usr/bin/env bash
-
-set -e # Fail on any command error
-shopt -s globstar
-
-if [[ $# -eq 0 ]] ; then
- echo "Missing argument of target directory"
- exit 1
-fi
-if ! [[ $(which npm) ]]; then
- echo "Missing npm"
- exit 1
-fi
-
-# Trigger the TypeScript build
-echo TypeScript build start
-npx tsc
-echo TypeScript build finished
-
-# Copy the TypeScript artifacts
-DIR="$1"
-rm -rf "$DIR"
-mkdir -pv "$DIR"
-
-echo Webpack start
-npm run build:webpack
-echo Webpack finish
-
-echo "Copying Trilium to build directory $DIR"
-
-for d in 'images' 'libraries' 'src' 'db'; do
- cp -r "$d" "$DIR"/
-done
-
-for f in 'package.json' 'package-lock.json' 'README.md' 'LICENSE' 'config-sample.ini'; do
- cp "$f" "$DIR"/
-done
-
-# Patch package.json main
-sed -i 's/.\/dist\/electron-main.js/electron-main.js/g' "$DIR/package.json"
-
-script_dir=$(realpath $(dirname $0))
-cp -R "$script_dir/../build/src" "$DIR"
-cp "$script_dir/../build/electron-main.js" "$DIR"
-
-# run in subshell (so we return to original dir)
-(cd $DIR && npm install --omit=dev --legacy-peer-deps)
-
-if [[ -d "$DIR"/node_modules ]]; then
- # cleanup of useless files in dependencies
- for d in 'image-q/demo' \
- '@excalidraw/excalidraw/dist/excalidraw-assets-dev' '@excalidraw/excalidraw/dist/excalidraw.development.js' '@excalidraw/excalidraw/dist/excalidraw-with-preact.development.js' \
- 'mermaid/dist/mermaid.js' \
- 'boxicons/svg' 'boxicons/node_modules/react'/* \
- '@jimp/plugin-print/fonts' 'jimp/browser' 'jimp/fonts'; do
- [[ -e "$DIR"/node_modules/"$d" ]] && rm -r "$DIR"/node_modules/"$d"
- done
-
- # delete all tests (there are often large images as test file for jimp etc.)
- for d in 'test' 'docs' 'demo' 'example'; do
- find "$DIR"/node_modules -name "$d" -exec rm -rf {} +
- done
-fi
-
-find $DIR/libraries -name "*.map" -type f -delete
-find $DIR/node_modules -name "*.map" -type f -delete
-find $DIR -name "*.ts" -type f -delete
-
-d="$DIR"/src/public
-[[ -d "$d"/app-dist ]] || mkdir -pv "$d"/app-dist
-cp -r "$d"/app/doc_notes "$d"/app-dist/
-
-rm -rf "$d"/app
-unset f d DIR
diff --git a/bin/docs/.env.example b/bin/docs/.env.example
deleted file mode 100644
index 03006fb86..000000000
--- a/bin/docs/.env.example
+++ /dev/null
@@ -1,3 +0,0 @@
-SHARE_PROTOCOL=http
-SHARE_HOST=notes.johnsmith.me
-ROOT_NOTE_ID=4yYHqKbLovVX
\ No newline at end of file
diff --git a/bin/docs/.gitignore b/bin/docs/.gitignore
deleted file mode 100644
index 5ad213baa..000000000
--- a/bin/docs/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-output
-.env
\ No newline at end of file
diff --git a/bin/docs/assets/v0.63.6/app-dist/share.js b/bin/docs/assets/v0.63.6/app-dist/share.js
deleted file mode 100644
index 3c3282497..000000000
--- a/bin/docs/assets/v0.63.6/app-dist/share.js
+++ /dev/null
@@ -1,27 +0,0 @@
-/**
- * Fetch note with given ID from backend
- *
- * @param noteId of the given note to be fetched. If false, fetches current note.
- */
-async function fetchNote(noteId = null) {
- if (!noteId) {
- noteId = document.body.getAttribute("data-note-id");
- }
-
- const resp = await fetch(`api/notes/${noteId}`);
-
- return await resp.json();
-}
-
-document.addEventListener(
- "DOMContentLoaded",
- () => {
- const toggleMenuButton = document.getElementById("toggleMenuButton");
- const layout = document.getElementById("layout");
-
- if (toggleMenuButton && layout) {
- toggleMenuButton.addEventListener("click", () => layout.classList.toggle("showMenu"));
- }
- },
- false
-);
diff --git a/bin/docs/assets/v0.63.6/libraries/ckeditor/ckeditor-content.css b/bin/docs/assets/v0.63.6/libraries/ckeditor/ckeditor-content.css
deleted file mode 100644
index 41d0ab466..000000000
--- a/bin/docs/assets/v0.63.6/libraries/ckeditor/ckeditor-content.css
+++ /dev/null
@@ -1,554 +0,0 @@
-/* !!!!!! TRILIUM CUSTOM CHANGES !!!!!! */
-
-.printed-content .ck-widget__selection-handle,
-.printed-content .ck-widget__type-around {
- /* gets rid of triangles: https://github.com/zadam/trilium/issues/1129 */
- display: none;
-}
-
-/*
- * CKEditor 5 (v41.0.0) content styles.
- * Generated on Fri, 26 Jan 2024 10:23:49 GMT.
- * For more information, check out https://ckeditor.com/docs/ckeditor5/latest/installation/advanced/content-styles.html
- */
-
-:root {
- --ck-color-image-caption-background: hsl(0, 0%, 97%);
- --ck-color-image-caption-text: hsl(0, 0%, 20%);
- --ck-color-mention-background: hsla(341, 100%, 30%, 0.1);
- --ck-color-mention-text: hsl(341, 100%, 30%);
- --ck-color-selector-caption-background: hsl(0, 0%, 97%);
- --ck-color-selector-caption-text: hsl(0, 0%, 20%);
- --ck-highlight-marker-blue: hsl(201, 97%, 72%);
- --ck-highlight-marker-green: hsl(120, 93%, 68%);
- --ck-highlight-marker-pink: hsl(345, 96%, 73%);
- --ck-highlight-marker-yellow: hsl(60, 97%, 73%);
- --ck-highlight-pen-green: hsl(112, 100%, 27%);
- --ck-highlight-pen-red: hsl(0, 85%, 49%);
- --ck-image-style-spacing: 1.5em;
- --ck-inline-image-style-spacing: calc(var(--ck-image-style-spacing) / 2);
- --ck-todo-list-checkmark-size: 16px;
-}
-
-/* @ckeditor/ckeditor5-table/theme/tablecolumnresize.css */
-.ck-content .table .ck-table-resized {
- table-layout: fixed;
-}
-/* @ckeditor/ckeditor5-table/theme/tablecolumnresize.css */
-.ck-content .table table {
- overflow: hidden;
-}
-/* @ckeditor/ckeditor5-table/theme/tablecolumnresize.css */
-.ck-content .table td,
-.ck-content .table th {
- overflow-wrap: break-word;
- position: relative;
-}
-/* @ckeditor/ckeditor5-table/theme/table.css */
-.ck-content .table {
- margin: 0.9em auto;
- display: table;
-}
-/* @ckeditor/ckeditor5-table/theme/table.css */
-.ck-content .table table {
- border-collapse: collapse;
- border-spacing: 0;
- width: 100%;
- height: 100%;
- border: 1px double hsl(0, 0%, 70%);
-}
-/* @ckeditor/ckeditor5-table/theme/table.css */
-.ck-content .table table td,
-.ck-content .table table th {
- min-width: 2em;
- padding: 0.4em;
- border: 1px solid hsl(0, 0%, 75%);
-}
-/* @ckeditor/ckeditor5-table/theme/table.css */
-.ck-content .table table th {
- font-weight: bold;
- background: hsla(0, 0%, 0%, 5%);
-}
-/* @ckeditor/ckeditor5-table/theme/table.css */
-.ck-content[dir="rtl"] .table th {
- text-align: right;
-}
-/* @ckeditor/ckeditor5-table/theme/table.css */
-.ck-content[dir="ltr"] .table th {
- text-align: left;
-}
-/* @ckeditor/ckeditor5-table/theme/tablecaption.css */
-.ck-content .table > figcaption {
- display: table-caption;
- caption-side: top;
- word-break: break-word;
- text-align: center;
- color: var(--ck-color-selector-caption-text);
- background-color: var(--ck-color-selector-caption-background);
- padding: 0.6em;
- font-size: 0.75em;
- outline-offset: -1px;
-}
-/* @ckeditor/ckeditor5-page-break/theme/pagebreak.css */
-.ck-content .page-break {
- position: relative;
- clear: both;
- padding: 5px 0;
- display: flex;
- align-items: center;
- justify-content: center;
-}
-/* @ckeditor/ckeditor5-page-break/theme/pagebreak.css */
-.ck-content .page-break::after {
- content: "";
- position: absolute;
- border-bottom: 2px dashed hsl(0, 0%, 77%);
- width: 100%;
-}
-/* @ckeditor/ckeditor5-page-break/theme/pagebreak.css */
-.ck-content .page-break__label {
- position: relative;
- z-index: 1;
- padding: 0.3em 0.6em;
- display: block;
- text-transform: uppercase;
- border: 1px solid hsl(0, 0%, 77%);
- border-radius: 2px;
- font-family: Helvetica, Arial, Tahoma, Verdana, Sans-Serif;
- font-size: 0.75em;
- font-weight: bold;
- color: hsl(0, 0%, 20%);
- background: hsl(0, 0%, 100%);
- box-shadow: 2px 2px 1px hsla(0, 0%, 0%, 0.15);
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
-}
-/* @ckeditor/ckeditor5-media-embed/theme/mediaembed.css */
-.ck-content .media {
- clear: both;
- margin: 0.9em 0;
- display: block;
- min-width: 15em;
-}
-/* @ckeditor/ckeditor5-list/theme/todolist.css */
-.ck-content .todo-list {
- list-style: none;
-}
-/* @ckeditor/ckeditor5-list/theme/todolist.css */
-.ck-content .todo-list li {
- position: relative;
- margin-bottom: 5px;
-}
-/* @ckeditor/ckeditor5-list/theme/todolist.css */
-.ck-content .todo-list li .todo-list {
- margin-top: 5px;
-}
-/* @ckeditor/ckeditor5-list/theme/todolist.css */
-.ck-content .todo-list .todo-list__label > input {
- -webkit-appearance: none;
- display: inline-block;
- position: relative;
- width: var(--ck-todo-list-checkmark-size);
- height: var(--ck-todo-list-checkmark-size);
- vertical-align: middle;
- border: 0;
- left: -25px;
- margin-right: -15px;
- right: 0;
- margin-left: 0;
-}
-/* @ckeditor/ckeditor5-list/theme/todolist.css */
-.ck-content[dir="rtl"] .todo-list .todo-list__label > input {
- left: 0;
- margin-right: 0;
- right: -25px;
- margin-left: -15px;
-}
-/* @ckeditor/ckeditor5-list/theme/todolist.css */
-.ck-content .todo-list .todo-list__label > input::before {
- display: block;
- position: absolute;
- box-sizing: border-box;
- content: "";
- width: 100%;
- height: 100%;
- border: 1px solid hsl(0, 0%, 20%);
- border-radius: 2px;
- transition: 250ms ease-in-out box-shadow;
-}
-/* @ckeditor/ckeditor5-list/theme/todolist.css */
-.ck-content .todo-list .todo-list__label > input::after {
- display: block;
- position: absolute;
- box-sizing: content-box;
- pointer-events: none;
- content: "";
- left: calc(var(--ck-todo-list-checkmark-size) / 3);
- top: calc(var(--ck-todo-list-checkmark-size) / 5.3);
- width: calc(var(--ck-todo-list-checkmark-size) / 5.3);
- height: calc(var(--ck-todo-list-checkmark-size) / 2.6);
- border-style: solid;
- border-color: transparent;
- border-width: 0 calc(var(--ck-todo-list-checkmark-size) / 8) calc(var(--ck-todo-list-checkmark-size) / 8) 0;
- transform: rotate(45deg);
-}
-/* @ckeditor/ckeditor5-list/theme/todolist.css */
-.ck-content .todo-list .todo-list__label > input[checked]::before {
- background: hsl(126, 64%, 41%);
- border-color: hsl(126, 64%, 41%);
-}
-/* @ckeditor/ckeditor5-list/theme/todolist.css */
-.ck-content .todo-list .todo-list__label > input[checked]::after {
- border-color: hsl(0, 0%, 100%);
-}
-/* @ckeditor/ckeditor5-list/theme/todolist.css */
-.ck-content .todo-list .todo-list__label .todo-list__label__description {
- vertical-align: middle;
-}
-/* @ckeditor/ckeditor5-list/theme/todolist.css */
-.ck-content .todo-list .todo-list__label.todo-list__label_without-description input[type="checkbox"] {
- position: absolute;
-}
-/* @ckeditor/ckeditor5-list/theme/todolist.css */
-.ck-editor__editable.ck-content .todo-list .todo-list__label > input,
-.ck-editor__editable.ck-content .todo-list .todo-list__label > span[contenteditable="false"] > input {
- cursor: pointer;
-}
-/* @ckeditor/ckeditor5-list/theme/todolist.css */
-.ck-editor__editable.ck-content .todo-list .todo-list__label > input:hover::before,
-.ck-editor__editable.ck-content .todo-list .todo-list__label > span[contenteditable="false"] > input:hover::before {
- box-shadow: 0 0 0 5px hsla(0, 0%, 0%, 0.1);
-}
-/* @ckeditor/ckeditor5-list/theme/todolist.css */
-.ck-editor__editable.ck-content .todo-list .todo-list__label > span[contenteditable="false"] > input {
- -webkit-appearance: none;
- display: inline-block;
- position: relative;
- width: var(--ck-todo-list-checkmark-size);
- height: var(--ck-todo-list-checkmark-size);
- vertical-align: middle;
- border: 0;
- left: -25px;
- margin-right: -15px;
- right: 0;
- margin-left: 0;
-}
-/* @ckeditor/ckeditor5-list/theme/todolist.css */
-.ck-editor__editable.ck-content[dir="rtl"] .todo-list .todo-list__label > span[contenteditable="false"] > input {
- left: 0;
- margin-right: 0;
- right: -25px;
- margin-left: -15px;
-}
-/* @ckeditor/ckeditor5-list/theme/todolist.css */
-.ck-editor__editable.ck-content .todo-list .todo-list__label > span[contenteditable="false"] > input::before {
- display: block;
- position: absolute;
- box-sizing: border-box;
- content: "";
- width: 100%;
- height: 100%;
- border: 1px solid hsl(0, 0%, 20%);
- border-radius: 2px;
- transition: 250ms ease-in-out box-shadow;
-}
-/* @ckeditor/ckeditor5-list/theme/todolist.css */
-.ck-editor__editable.ck-content .todo-list .todo-list__label > span[contenteditable="false"] > input::after {
- display: block;
- position: absolute;
- box-sizing: content-box;
- pointer-events: none;
- content: "";
- left: calc(var(--ck-todo-list-checkmark-size) / 3);
- top: calc(var(--ck-todo-list-checkmark-size) / 5.3);
- width: calc(var(--ck-todo-list-checkmark-size) / 5.3);
- height: calc(var(--ck-todo-list-checkmark-size) / 2.6);
- border-style: solid;
- border-color: transparent;
- border-width: 0 calc(var(--ck-todo-list-checkmark-size) / 8) calc(var(--ck-todo-list-checkmark-size) / 8) 0;
- transform: rotate(45deg);
-}
-/* @ckeditor/ckeditor5-list/theme/todolist.css */
-.ck-editor__editable.ck-content .todo-list .todo-list__label > span[contenteditable="false"] > input[checked]::before {
- background: hsl(126, 64%, 41%);
- border-color: hsl(126, 64%, 41%);
-}
-/* @ckeditor/ckeditor5-list/theme/todolist.css */
-.ck-editor__editable.ck-content .todo-list .todo-list__label > span[contenteditable="false"] > input[checked]::after {
- border-color: hsl(0, 0%, 100%);
-}
-/* @ckeditor/ckeditor5-list/theme/todolist.css */
-.ck-editor__editable.ck-content .todo-list .todo-list__label.todo-list__label_without-description input[type="checkbox"] {
- position: absolute;
-}
-/* @ckeditor/ckeditor5-list/theme/list.css */
-.ck-content ol {
- list-style-type: decimal;
-}
-/* @ckeditor/ckeditor5-list/theme/list.css */
-.ck-content ol ol {
- list-style-type: lower-latin;
-}
-/* @ckeditor/ckeditor5-list/theme/list.css */
-.ck-content ol ol ol {
- list-style-type: lower-roman;
-}
-/* @ckeditor/ckeditor5-list/theme/list.css */
-.ck-content ol ol ol ol {
- list-style-type: upper-latin;
-}
-/* @ckeditor/ckeditor5-list/theme/list.css */
-.ck-content ol ol ol ol ol {
- list-style-type: upper-roman;
-}
-/* @ckeditor/ckeditor5-list/theme/list.css */
-.ck-content ul {
- list-style-type: disc;
-}
-/* @ckeditor/ckeditor5-list/theme/list.css */
-.ck-content ul ul {
- list-style-type: circle;
-}
-/* @ckeditor/ckeditor5-list/theme/list.css */
-.ck-content ul ul ul {
- list-style-type: square;
-}
-/* @ckeditor/ckeditor5-list/theme/list.css */
-.ck-content ul ul ul ul {
- list-style-type: square;
-}
-/* @ckeditor/ckeditor5-image/theme/image.css */
-.ck-content .image {
- display: table;
- clear: both;
- text-align: center;
- margin: 0.9em auto;
- min-width: 50px;
-}
-/* @ckeditor/ckeditor5-image/theme/image.css */
-.ck-content .image img {
- display: block;
- margin: 0 auto;
- max-width: 100%;
- min-width: 100%;
- height: auto;
-}
-/* @ckeditor/ckeditor5-image/theme/image.css */
-.ck-content .image-inline {
- /*
- * Normally, the .image-inline would have "display: inline-block" and "img { width: 100% }" (to follow the wrapper while resizing).;
- * Unfortunately, together with "srcset", it gets automatically stretched up to the width of the editing root.
- * This strange behavior does not happen with inline-flex.
- */
- display: inline-flex;
- max-width: 100%;
- align-items: flex-start;
-}
-/* @ckeditor/ckeditor5-image/theme/image.css */
-.ck-content .image-inline picture {
- display: flex;
-}
-/* @ckeditor/ckeditor5-image/theme/image.css */
-.ck-content .image-inline picture,
-.ck-content .image-inline img {
- flex-grow: 1;
- flex-shrink: 1;
- max-width: 100%;
-}
-/* @ckeditor/ckeditor5-image/theme/imageresize.css */
-.ck-content img.image_resized {
- height: auto;
-}
-/* @ckeditor/ckeditor5-image/theme/imageresize.css */
-.ck-content .image.image_resized {
- max-width: 100%;
- display: block;
- box-sizing: border-box;
-}
-/* @ckeditor/ckeditor5-image/theme/imageresize.css */
-.ck-content .image.image_resized img {
- width: 100%;
-}
-/* @ckeditor/ckeditor5-image/theme/imageresize.css */
-.ck-content .image.image_resized > figcaption {
- display: block;
-}
-/* @ckeditor/ckeditor5-image/theme/imagecaption.css */
-.ck-content .image > figcaption {
- display: table-caption;
- caption-side: bottom;
- word-break: break-word;
- color: var(--ck-color-image-caption-text);
- background-color: var(--ck-color-image-caption-background);
- padding: 0.6em;
- font-size: 0.75em;
- outline-offset: -1px;
-}
-/* @ckeditor/ckeditor5-image/theme/imagestyle.css */
-.ck-content .image-style-block-align-left,
-.ck-content .image-style-block-align-right {
- max-width: calc(100% - var(--ck-image-style-spacing));
-}
-/* @ckeditor/ckeditor5-image/theme/imagestyle.css */
-.ck-content .image-style-align-left,
-.ck-content .image-style-align-right {
- clear: none;
-}
-/* @ckeditor/ckeditor5-image/theme/imagestyle.css */
-.ck-content .image-style-side {
- float: right;
- margin-left: var(--ck-image-style-spacing);
- max-width: 50%;
-}
-/* @ckeditor/ckeditor5-image/theme/imagestyle.css */
-.ck-content .image-style-align-left {
- float: left;
- margin-right: var(--ck-image-style-spacing);
-}
-/* @ckeditor/ckeditor5-image/theme/imagestyle.css */
-.ck-content .image-style-align-center {
- margin-left: auto;
- margin-right: auto;
-}
-/* @ckeditor/ckeditor5-image/theme/imagestyle.css */
-.ck-content .image-style-align-right {
- float: right;
- margin-left: var(--ck-image-style-spacing);
-}
-/* @ckeditor/ckeditor5-image/theme/imagestyle.css */
-.ck-content .image-style-block-align-right {
- margin-right: 0;
- margin-left: auto;
-}
-/* @ckeditor/ckeditor5-image/theme/imagestyle.css */
-.ck-content .image-style-block-align-left {
- margin-left: 0;
- margin-right: auto;
-}
-/* @ckeditor/ckeditor5-image/theme/imagestyle.css */
-.ck-content p + .image-style-align-left,
-.ck-content p + .image-style-align-right,
-.ck-content p + .image-style-side {
- margin-top: 0;
-}
-/* @ckeditor/ckeditor5-image/theme/imagestyle.css */
-.ck-content .image-inline.image-style-align-left,
-.ck-content .image-inline.image-style-align-right {
- margin-top: var(--ck-inline-image-style-spacing);
- margin-bottom: var(--ck-inline-image-style-spacing);
-}
-/* @ckeditor/ckeditor5-image/theme/imagestyle.css */
-.ck-content .image-inline.image-style-align-left {
- margin-right: var(--ck-inline-image-style-spacing);
-}
-/* @ckeditor/ckeditor5-image/theme/imagestyle.css */
-.ck-content .image-inline.image-style-align-right {
- margin-left: var(--ck-inline-image-style-spacing);
-}
-/* @ckeditor/ckeditor5-highlight/theme/highlight.css */
-.ck-content .marker-yellow {
- background-color: var(--ck-highlight-marker-yellow);
-}
-/* @ckeditor/ckeditor5-highlight/theme/highlight.css */
-.ck-content .marker-green {
- background-color: var(--ck-highlight-marker-green);
-}
-/* @ckeditor/ckeditor5-highlight/theme/highlight.css */
-.ck-content .marker-pink {
- background-color: var(--ck-highlight-marker-pink);
-}
-/* @ckeditor/ckeditor5-highlight/theme/highlight.css */
-.ck-content .marker-blue {
- background-color: var(--ck-highlight-marker-blue);
-}
-/* @ckeditor/ckeditor5-highlight/theme/highlight.css */
-.ck-content .pen-red {
- color: var(--ck-highlight-pen-red);
- background-color: transparent;
-}
-/* @ckeditor/ckeditor5-highlight/theme/highlight.css */
-.ck-content .pen-green {
- color: var(--ck-highlight-pen-green);
- background-color: transparent;
-}
-/* @ckeditor/ckeditor5-block-quote/theme/blockquote.css */
-.ck-content blockquote {
- overflow: hidden;
- padding-right: 1.5em;
- padding-left: 1.5em;
- margin-left: 0;
- margin-right: 0;
- font-style: italic;
- border-left: solid 5px hsl(0, 0%, 80%);
-}
-/* @ckeditor/ckeditor5-block-quote/theme/blockquote.css */
-.ck-content[dir="rtl"] blockquote {
- border-left: 0;
- border-right: solid 5px hsl(0, 0%, 80%);
-}
-/* @ckeditor/ckeditor5-basic-styles/theme/code.css */
-.ck-content code {
- background-color: hsla(0, 0%, 78%, 0.3);
- padding: 0.15em;
- border-radius: 2px;
-}
-/* @ckeditor/ckeditor5-font/theme/fontsize.css */
-.ck-content .text-tiny {
- font-size: 0.7em;
-}
-/* @ckeditor/ckeditor5-font/theme/fontsize.css */
-.ck-content .text-small {
- font-size: 0.85em;
-}
-/* @ckeditor/ckeditor5-font/theme/fontsize.css */
-.ck-content .text-big {
- font-size: 1.4em;
-}
-/* @ckeditor/ckeditor5-font/theme/fontsize.css */
-.ck-content .text-huge {
- font-size: 1.8em;
-}
-/* @ckeditor/ckeditor5-mention/theme/mention.css */
-.ck-content .mention {
- background: var(--ck-color-mention-background);
- color: var(--ck-color-mention-text);
-}
-/* @ckeditor/ckeditor5-horizontal-line/theme/horizontalline.css */
-.ck-content hr {
- margin: 15px 0;
- height: 4px;
- background: hsl(0, 0%, 87%);
- border: 0;
-}
-/* @ckeditor/ckeditor5-code-block/theme/codeblock.css */
-.ck-content pre {
- padding: 1em;
- color: hsl(0, 0%, 20.8%);
- background: hsla(0, 0%, 78%, 0.3);
- border: 1px solid hsl(0, 0%, 77%);
- border-radius: 2px;
- text-align: left;
- direction: ltr;
- tab-size: 4;
- white-space: pre-wrap;
- font-style: normal;
- min-width: 200px;
-}
-/* @ckeditor/ckeditor5-code-block/theme/codeblock.css */
-.ck-content pre code {
- background: unset;
- padding: 0;
- border-radius: 0;
-}
-@media print {
- /* @ckeditor/ckeditor5-page-break/theme/pagebreak.css */
- .ck-content .page-break {
- padding: 0;
- }
- /* @ckeditor/ckeditor5-page-break/theme/pagebreak.css */
- .ck-content .page-break::after {
- display: none;
- }
-}
diff --git a/bin/docs/assets/v0.63.6/libraries/normalize.min.css b/bin/docs/assets/v0.63.6/libraries/normalize.min.css
deleted file mode 100644
index 3d24d023d..000000000
--- a/bin/docs/assets/v0.63.6/libraries/normalize.min.css
+++ /dev/null
@@ -1,148 +0,0 @@
-/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
-html {
- line-height: 1.15;
- -webkit-text-size-adjust: 100%;
-}
-body {
- margin: 0;
-}
-main {
- display: block;
-}
-h1 {
- font-size: 2em;
- margin: 0.67em 0;
-}
-hr {
- box-sizing: content-box;
- height: 0;
- overflow: visible;
-}
-pre {
- font-family: monospace, monospace;
- font-size: 1em;
-}
-a {
- background-color: transparent;
-}
-abbr[title] {
- border-bottom: none;
- text-decoration: underline;
- text-decoration: underline dotted;
-}
-b,
-strong {
- font-weight: bolder;
-}
-code,
-kbd,
-samp {
- font-family: monospace, monospace;
- font-size: 1em;
-}
-small {
- font-size: 80%;
-}
-sub,
-sup {
- font-size: 75%;
- line-height: 0;
- position: relative;
- vertical-align: baseline;
-}
-sub {
- bottom: -0.25em;
-}
-sup {
- top: -0.5em;
-}
-img {
- border-style: none;
-}
-button,
-input,
-optgroup,
-select,
-textarea {
- font-family: inherit;
- font-size: 100%;
- line-height: 1.15;
- margin: 0;
-}
-button,
-input {
- overflow: visible;
-}
-button,
-select {
- text-transform: none;
-}
-[type="button"],
-[type="reset"],
-[type="submit"],
-button {
- -webkit-appearance: button;
-}
-[type="button"]::-moz-focus-inner,
-[type="reset"]::-moz-focus-inner,
-[type="submit"]::-moz-focus-inner,
-button::-moz-focus-inner {
- border-style: none;
- padding: 0;
-}
-[type="button"]:-moz-focusring,
-[type="reset"]:-moz-focusring,
-[type="submit"]:-moz-focusring,
-button:-moz-focusring {
- outline: 1px dotted ButtonText;
-}
-fieldset {
- padding: 0.35em 0.75em 0.625em;
-}
-legend {
- box-sizing: border-box;
- color: inherit;
- display: table;
- max-width: 100%;
- padding: 0;
- white-space: normal;
-}
-progress {
- vertical-align: baseline;
-}
-textarea {
- overflow: auto;
-}
-[type="checkbox"],
-[type="radio"] {
- box-sizing: border-box;
- padding: 0;
-}
-[type="number"]::-webkit-inner-spin-button,
-[type="number"]::-webkit-outer-spin-button {
- height: auto;
-}
-[type="search"] {
- -webkit-appearance: textfield;
- outline-offset: -2px;
-}
-[type="search"]::-webkit-search-decoration {
- -webkit-appearance: none;
-}
-::-webkit-file-upload-button {
- -webkit-appearance: button;
- font: inherit;
-}
-details {
- display: block;
-}
-summary {
- display: list-item;
-}
-template {
- display: none;
-}
-[hidden] {
- display: none;
-}
-/*# sourceMappingURL=normalize.min.css.map */
diff --git a/bin/docs/assets/v0.63.6/stylesheets/share.css b/bin/docs/assets/v0.63.6/stylesheets/share.css
deleted file mode 100644
index 457898d8f..000000000
--- a/bin/docs/assets/v0.63.6/stylesheets/share.css
+++ /dev/null
@@ -1,165 +0,0 @@
-body {
- font-family: "Lucida Grande", "Lucida Sans Unicode", arial, sans-serif;
- line-height: 1.5;
-}
-
-#layout {
- max-width: 1200px;
- margin: 0 auto;
- display: flex;
- flex-direction: row-reverse;
-}
-
-#menu {
- padding: 25px;
- flex-basis: 0;
- flex-grow: 1;
- overflow: auto;
-}
-
-#menu p {
- margin: 0;
-}
-
-#menu > p {
- font-weight: bold;
- font-size: 110%;
-}
-
-#menu ul {
- padding-left: 20px;
-}
-
-#main {
- flex-basis: 0;
- flex-grow: 3;
- overflow: auto;
- padding: 10px 20px 20px 20px;
-}
-
-#parentLink {
- float: right;
- margin-top: 20px;
-}
-
-#title {
- margin: 0;
- padding-top: 10px;
-}
-
-img {
- max-width: 100%;
-}
-
-pre {
- white-space: pre-wrap;
- word-wrap: anywhere;
-}
-
-iframe.pdf-view {
- width: 100%;
- height: 800px;
-}
-
-#toggleMenuButton {
- display: none;
- position: fixed;
- top: 8px;
- left: 5px;
- width: 1.4em;
- border-radius: 5px;
- border: 1px solid #aaa;
- font-size: 2rem;
- z-index: 10;
- height: auto;
- color: black;
- cursor: pointer;
-}
-
-#childLinks.grid ul {
- list-style-type: none;
- display: flex;
- flex-wrap: wrap;
- padding: 0;
-}
-
-#childLinks.grid ul li {
- width: 180px;
- height: 140px;
- padding: 10px;
-}
-
-#childLinks.grid ul li a {
- display: flex;
- flex-direction: column;
- height: 100%;
- width: 100%;
- border: 1px solid #ddd;
- border-radius: 5px;
- justify-content: center;
- align-content: center;
- text-align: center;
- font-size: large;
-}
-
-#childLinks.grid ul li a:hover {
- background: #eee;
-}
-
-#childLinks.list ul {
- list-style-type: none;
- display: inline-flex;
- flex-wrap: wrap;
- padding: 0;
- margin-top: 5px;
-}
-
-#childLinks.list ul li {
- margin-right: 20px;
-}
-
-#noteClippedFrom {
- padding: 10px 0 10px 0;
- margin: 20px 0 20px 0;
- color: #666;
- border: 1px solid #ddd;
- border-left: 0;
- border-right: 0;
-}
-
-#toggleMenuButton::after {
- position: relative;
- top: -2px;
- left: 1px;
-}
-
-@media (max-width: 48em) {
- #layout.showMenu #menu {
- display: block;
- margin-top: 40px;
- }
-
- #toggleMenuButton {
- display: block;
- }
-
- #layout.showMenu #main {
- display: none;
- }
-
- #title {
- padding-left: 60px;
- }
-
- #layout.showMenu #toggleMenuButton::after {
- content: "«";
- }
-
- #toggleMenuButton::after {
- content: "»";
- }
-
- #menu {
- display: none;
- }
-}
diff --git a/bin/docs/index.template.html b/bin/docs/index.template.html
deleted file mode 100644
index b2580cb88..000000000
--- a/bin/docs/index.template.html
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/bin/docs/prepare.sh b/bin/docs/prepare.sh
deleted file mode 100755
index 35e761b6d..000000000
--- a/bin/docs/prepare.sh
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/env bash
-
-script_dir=$(realpath $(dirname $0))
-
-cd "$script_dir"
-
-env_file="$script_dir/.env"
-
-if [ ! -f "$env_file" ]; then
- echo "Missing .env file, cannot proceed."
- exit 1
-fi
-
-output_dir="$script_dir/../../docs"
-mkdir -p "$output_dir"
-rm -f "$output_dir"/*
-rm -rf "$output_dir"/{assets,share}
-
-source "$env_file"
-
-# Download everything in output/notes.example.com/share/...
-share_url="$SHARE_PROTOCOL://$SHARE_HOST/share/$ROOT_NOTE_ID"
-wget -rpEk -e robots=off "$share_url" -P "$output_dir"
-if [ $? -ne 0 ]; then
- echo -e \\nDownloading failed, make sure you are using the real wget package and not the busybox one.
- exit 1
-fi
-
-# Get rid of the domain in the output folder
-mv "$output_dir/$SHARE_HOST"/* "$output_dir/"
-rmdir "$output_dir/$SHARE_HOST"
-
-# Create home page with redirect
-index_dest_path="$output_dir/index.html"
-cp index.template.html "$index_dest_path"
-sed -i "s/{{ROOT_NOTE_ID}}/$ROOT_NOTE_ID/g" "$index_dest_path"
-
-# Rewrite links to get rid of the share folder
-sed -i "s/ {
- const sql = require("../../src/services/sql");
- const utils = require("../../src/services/utils");
+import sql from "../../src/services/sql";
+import utils from "../../src/services/utils";
+interface NoteContentsRow {
+ noteId: string;
+ content: string | Buffer;
+ dateModified: string;
+ utcDateModified: string;
+}
+
+interface NoteRevisionContents {
+ noteRevisionId: string;
+ content: string | Buffer;
+ utcDateModified: string;
+}
+
+export default () => {
const existingBlobIds = new Set();
- for (const noteId of sql.getColumn(`SELECT noteId FROM note_contents`)) {
- const row = sql.getRow(`SELECT noteId, content, dateModified, utcDateModified FROM note_contents WHERE noteId = ?`, [noteId]);
+ for (const noteId of sql.getColumn(/*sql*/`SELECT noteId FROM note_contents`)) {
+ const row = sql.getRow(/*sql*/`SELECT noteId, content, dateModified, utcDateModified FROM note_contents WHERE noteId = ?`, [noteId]);
const blobId = utils.hashedBlobId(row.content);
if (!existingBlobIds.has(blobId)) {
@@ -27,8 +40,8 @@ module.exports = () => {
sql.execute("UPDATE notes SET blobId = ? WHERE noteId = ?", [blobId, row.noteId]);
}
- for (const noteRevisionId of sql.getColumn(`SELECT noteRevisionId FROM note_revision_contents`)) {
- const row = sql.getRow(`SELECT noteRevisionId, content, utcDateModified FROM note_revision_contents WHERE noteRevisionId = ?`, [noteRevisionId]);
+ for (const noteRevisionId of sql.getColumn(/*sql*/`SELECT noteRevisionId FROM note_revision_contents`)) {
+ const row = sql.getRow(/*sql*/`SELECT noteRevisionId, content, utcDateModified FROM note_revision_contents WHERE noteRevisionId = ?`, [noteRevisionId]);
const blobId = utils.hashedBlobId(row.content);
if (!existingBlobIds.has(blobId)) {
@@ -44,7 +57,7 @@ module.exports = () => {
sql.execute("UPDATE entity_changes SET entityName = 'blobs', entityId = ? WHERE entityName = 'note_revision_contents' AND entityId = ?", [blobId, row.noteRevisionId]);
} else {
// duplicates
- sql.execute("DELETE FROM entity_changes WHERE entityName = 'note_revision_contents' AND entityId = ?", [row.noteId]);
+ sql.execute("DELETE FROM entity_changes WHERE entityName = 'note_revision_contents' AND entityId = ?", [row.noteRevisionId]);
}
sql.execute("UPDATE note_revisions SET blobId = ? WHERE noteRevisionId = ?", [blobId, row.noteRevisionId]);
diff --git a/db/migrations/0220__migrate_images_to_attachments.js b/db/migrations/0220__migrate_images_to_attachments.ts
similarity index 60%
rename from db/migrations/0220__migrate_images_to_attachments.js
rename to db/migrations/0220__migrate_images_to_attachments.ts
index a93e2028d..f54f4a956 100644
--- a/db/migrations/0220__migrate_images_to_attachments.js
+++ b/db/migrations/0220__migrate_images_to_attachments.ts
@@ -1,15 +1,15 @@
-module.exports = () => {
- const beccaLoader = require("../../src/becca/becca_loader");
- const becca = require("../../src/becca/becca");
- const cls = require("../../src/services/cls");
- const log = require("../../src/services/log");
- const sql = require("../../src/services/sql");
+import becca from "../../src/becca/becca";
+import becca_loader from "../../src/becca/becca_loader";
+import cls from "../../src/services/cls";
+import log from "../../src/services/log";
+import sql from "../../src/services/sql";
+export default () => {
cls.init(() => {
// emergency disabling of image compression since it appears to make problems in migration to 0.61
- sql.execute(`UPDATE options SET value = 'false' WHERE name = 'compressImages'`);
+ sql.execute(/*sql*/`UPDATE options SET value = 'false' WHERE name = 'compressImages'`);
- beccaLoader.load();
+ becca_loader.load();
for (const note of Object.values(becca.notes)) {
try {
diff --git a/db/migrations/0229__add_oauth_user_data_table.sql b/db/migrations/0229__add_oauth_user_data_table.sql
new file mode 100644
index 000000000..ea2db4ef9
--- /dev/null
+++ b/db/migrations/0229__add_oauth_user_data_table.sql
@@ -0,0 +1,14 @@
+-- Add the oauth user data table
+CREATE TABLE IF NOT EXISTS "user_data"
+(
+ tmpID INT,
+ username TEXT,
+ email TEXT,
+ userIDEncryptedDataKey TEXT,
+ userIDVerificationHash TEXT,
+ salt TEXT,
+ derivedKey TEXT,
+ isSetup TEXT DEFAULT "false",
+ UNIQUE (tmpID),
+ PRIMARY KEY (tmpID)
+);
\ No newline at end of file
diff --git a/db/migrations/0229__tasks.sql b/db/migrations/0229__tasks.sql
deleted file mode 100644
index 4d0381db2..000000000
--- a/db/migrations/0229__tasks.sql
+++ /dev/null
@@ -1,10 +0,0 @@
-CREATE TABLE IF NOT EXISTS "tasks"
-(
- "taskId" TEXT NOT NULL PRIMARY KEY,
- "parentNoteId" TEXT NOT NULL,
- "title" TEXT NOT NULL DEFAULT "",
- "dueDate" INTEGER,
- "isDone" INTEGER NOT NULL DEFAULT 0,
- "isDeleted" INTEGER NOT NULL DEFAULT 0,
- "utcDateModified" TEXT NOT NULL
-);
\ No newline at end of file
diff --git a/db/schema.sql b/db/schema.sql
index 77361f5ed..8bf9db1e7 100644
--- a/db/schema.sql
+++ b/db/schema.sql
@@ -126,20 +126,22 @@ CREATE TABLE IF NOT EXISTS "attachments"
utcDateScheduledForErasureSince TEXT DEFAULT NULL,
isDeleted INT not null,
deleteId TEXT DEFAULT NULL);
+CREATE TABLE IF NOT EXISTS "user_data"
+(
+ tmpID INT,
+ username TEXT,
+ email TEXT,
+ userIDEncryptedDataKey TEXT,
+ userIDVerificationHash TEXT,
+ salt TEXT,
+ derivedKey TEXT,
+ isSetup TEXT DEFAULT "false",
+ UNIQUE (tmpID),
+ PRIMARY KEY (tmpID)
+);
CREATE INDEX IDX_attachments_ownerId_role
on attachments (ownerId, role);
CREATE INDEX IDX_notes_blobId on notes (blobId);
CREATE INDEX IDX_revisions_blobId on revisions (blobId);
CREATE INDEX IDX_attachments_blobId on attachments (blobId);
-
-CREATE TABLE IF NOT EXISTS "tasks"
-(
- "taskId" TEXT NOT NULL PRIMARY KEY,
- "parentNoteId" TEXT NOT NULL,
- "title" TEXT NOT NULL DEFAULT "",
- "dueDate" INTEGER,
- "isDone" INTEGER NOT NULL DEFAULT 0,
- "isDeleted" INTEGER NOT NULL DEFAULT 0,
- "utcDateModified" TEXT NOT NULL
-);
\ No newline at end of file
diff --git a/demo/!!!meta.json b/demo/!!!meta.json
new file mode 100644
index 000000000..4899c4606
--- /dev/null
+++ b/demo/!!!meta.json
@@ -0,0 +1,6088 @@
+{
+ "formatVersion": 2,
+ "appVersion": "0.92.5-beta",
+ "files": [
+ {
+ "isClone": false,
+ "noteId": "root",
+ "notePath": [
+ "root"
+ ],
+ "title": "root",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": true,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "attachments": [],
+ "dirFileName": "root",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "sxsosDSEMa8u",
+ "notePath": [
+ "root",
+ "sxsosDSEMa8u"
+ ],
+ "title": "Journal",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": true,
+ "type": "book",
+ "mime": "",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "calendarRoot",
+ "value": "",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bx-calendar",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "label",
+ "name": "viewType",
+ "value": "calendar",
+ "isInheritable": false,
+ "position": 30
+ },
+ {
+ "type": "label",
+ "name": "calendar:view",
+ "value": "dayGridMonth",
+ "isInheritable": false,
+ "position": 40
+ }
+ ],
+ "dataFileName": "Journal.dat",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "Fb7eMY46lT6k",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k"
+ ],
+ "title": "Trilium Demo",
+ "notePosition": 20,
+ "prefix": null,
+ "isExpanded": true,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "qP9UEZ4kQ0NK",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "8DORylN1bL6J",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "rIP0ngPPeia6",
+ "isInheritable": false,
+ "position": 30
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "TIKj1aLdHCzw",
+ "isInheritable": false,
+ "position": 40
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "xd22mlgxfdWw",
+ "isInheritable": false,
+ "position": 50
+ },
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bx-book-reader",
+ "isInheritable": false,
+ "position": 70
+ }
+ ],
+ "format": "html",
+ "dataFileName": "Trilium Demo.html",
+ "attachments": [
+ {
+ "attachmentId": "96nFd7uePoSp",
+ "title": "icon-color.svg",
+ "role": "image",
+ "mime": "image/svg+xml",
+ "position": 10,
+ "dataFileName": "Trilium Demo_icon-color.svg"
+ }
+ ],
+ "dirFileName": "Trilium Demo",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "B08ZaJdYTK5v",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "B08ZaJdYTK5v"
+ ],
+ "title": "Inbox",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": true,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bxs-inbox",
+ "isInheritable": false,
+ "position": 1
+ }
+ ],
+ "format": "html",
+ "dataFileName": "Inbox.html",
+ "attachments": [],
+ "dirFileName": "Inbox",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "nMiFslI2hks0",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "B08ZaJdYTK5v",
+ "nMiFslI2hks0"
+ ],
+ "title": "Grocery list for today",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "Grocery list for today.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "RsIQGAjjnfgv",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "B08ZaJdYTK5v",
+ "RsIQGAjjnfgv"
+ ],
+ "title": "Book to read",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "Book to read.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "47q1VMmTjJtx",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "B08ZaJdYTK5v",
+ "47q1VMmTjJtx"
+ ],
+ "title": "The Last Question",
+ "notePosition": 20,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "relation",
+ "name": "includeNoteLink",
+ "value": "ZWCYra81yOFO",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "_help_nBAXQFj20hS1",
+ "isInheritable": false,
+ "position": 20
+ }
+ ],
+ "format": "html",
+ "dataFileName": "The Last Question.html",
+ "attachments": [],
+ "dirFileName": "The Last Question",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "ZWCYra81yOFO",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "B08ZaJdYTK5v",
+ "47q1VMmTjJtx",
+ "ZWCYra81yOFO"
+ ],
+ "title": "The Last Question by Issac Asimov.pdf",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "file",
+ "mime": "application/pdf",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "originalFileName",
+ "value": "the_last_question_-_issac_asimov.pdf",
+ "isInheritable": false,
+ "position": 1
+ }
+ ],
+ "dataFileName": "The Last Question by Issac.pdf",
+ "attachments": []
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "vHpMd49rAUWn",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "vHpMd49rAUWn"
+ ],
+ "title": "Formatting examples",
+ "notePosition": 20,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "book",
+ "mime": "",
+ "attributes": [],
+ "attachments": [],
+ "dirFileName": "Formatting examples",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "qP9UEZ4kQ0NK",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "vHpMd49rAUWn",
+ "qP9UEZ4kQ0NK"
+ ],
+ "title": "School schedule",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bx-table",
+ "isInheritable": false,
+ "position": 10
+ }
+ ],
+ "format": "html",
+ "dataFileName": "School schedule.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "8DORylN1bL6J",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "vHpMd49rAUWn",
+ "8DORylN1bL6J"
+ ],
+ "title": "Checkbox lists",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bx-check",
+ "isInheritable": false,
+ "position": 1
+ }
+ ],
+ "format": "html",
+ "dataFileName": "Checkbox lists.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "rIP0ngPPeia6",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "vHpMd49rAUWn",
+ "rIP0ngPPeia6"
+ ],
+ "title": "Highlighting",
+ "notePosition": 20,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bxs-pencil",
+ "isInheritable": false,
+ "position": 1
+ }
+ ],
+ "format": "html",
+ "dataFileName": "Highlighting.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "TIKj1aLdHCzw",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "vHpMd49rAUWn",
+ "TIKj1aLdHCzw"
+ ],
+ "title": "Code blocks",
+ "notePosition": 30,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "relation",
+ "name": "internalLink",
+ "value": "IPifAXM3cyRS",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bx-code-alt",
+ "isInheritable": false,
+ "position": 2
+ }
+ ],
+ "format": "html",
+ "dataFileName": "Code blocks.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "xd22mlgxfdWw",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "vHpMd49rAUWn",
+ "xd22mlgxfdWw"
+ ],
+ "title": "Math",
+ "notePosition": 40,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bx-calculator",
+ "isInheritable": false,
+ "position": 1
+ }
+ ],
+ "format": "html",
+ "dataFileName": "Math.html",
+ "attachments": []
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "eYIqnBvdAmaE",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE"
+ ],
+ "title": "Journal",
+ "notePosition": 30,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "sorted",
+ "value": "",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "relation",
+ "name": "child:child:child:template",
+ "value": "sINmXkCzncB4",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bx-calendar",
+ "isInheritable": false,
+ "position": 30
+ }
+ ],
+ "format": "html",
+ "dataFileName": "Journal.html",
+ "attachments": [],
+ "dirFileName": "Journal",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "3H4RMc45XIpI",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI"
+ ],
+ "title": "2021",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "sorted",
+ "value": "",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "label",
+ "name": "yearNote",
+ "value": "2021",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "relation",
+ "name": "child:child:template",
+ "value": "sINmXkCzncB4",
+ "isInheritable": false,
+ "position": 30
+ }
+ ],
+ "format": "html",
+ "attachments": [],
+ "dirFileName": "2021",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "oNJGQb0t2SGb",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "oNJGQb0t2SGb"
+ ],
+ "title": "11 - November",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "sorted",
+ "value": "",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "label",
+ "name": "monthNote",
+ "value": "2021-11",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "relation",
+ "name": "child:template",
+ "value": "sINmXkCzncB4",
+ "isInheritable": false,
+ "position": 30
+ }
+ ],
+ "format": "html",
+ "attachments": [],
+ "dirFileName": "11 - November",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "JvGlcvRf2Lu8",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "oNJGQb0t2SGb",
+ "JvGlcvRf2Lu8"
+ ],
+ "title": "28 - Tuesday",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "dateNote",
+ "value": "2021-11-28",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "relation",
+ "name": "template",
+ "value": "sINmXkCzncB4",
+ "isInheritable": false,
+ "position": 20
+ }
+ ],
+ "format": "html",
+ "dataFileName": "28 - Tuesday.html",
+ "attachments": [],
+ "dirFileName": "28 - Tuesday",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "k11dU4eL5Teq",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "oNJGQb0t2SGb",
+ "JvGlcvRf2Lu8",
+ "k11dU4eL5Teq"
+ ],
+ "title": "Phone call about work project",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": true,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "Phone call about work project.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "RNf8bX9CdR1k",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "oNJGQb0t2SGb",
+ "JvGlcvRf2Lu8",
+ "RNf8bX9CdR1k"
+ ],
+ "title": "Christmas gift ideas",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "Christmas gift ideas.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "AaxrGGwyIPxO",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "oNJGQb0t2SGb",
+ "JvGlcvRf2Lu8",
+ "AaxrGGwyIPxO"
+ ],
+ "title": "Trusted timestamping",
+ "notePosition": 20,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "Trusted timestamping.html",
+ "attachments": []
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "BkmGEUBkAvZC",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "BkmGEUBkAvZC"
+ ],
+ "title": "12 - December",
+ "notePosition": 20,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "sorted",
+ "value": "",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "label",
+ "name": "monthNote",
+ "value": "2021-12",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "relation",
+ "name": "child:template",
+ "value": "sINmXkCzncB4",
+ "isInheritable": false,
+ "position": 30
+ }
+ ],
+ "format": "html",
+ "attachments": [],
+ "dirFileName": "12 - December",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "S9e1O6walQlq",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "BkmGEUBkAvZC",
+ "S9e1O6walQlq"
+ ],
+ "title": "18 - Monday",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "relation",
+ "name": "template",
+ "value": "sINmXkCzncB4",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "label",
+ "name": "dateNote",
+ "value": "2021-12-18",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "label",
+ "name": "weight",
+ "value": "74.9",
+ "isInheritable": false,
+ "position": 30
+ }
+ ],
+ "format": "html",
+ "dataFileName": "18 - Monday.html",
+ "attachments": [],
+ "dirFileName": "18 - Monday",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "aqelIyWn57Aa",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "BkmGEUBkAvZC",
+ "S9e1O6walQlq",
+ "aqelIyWn57Aa"
+ ],
+ "title": "Meeting minutes",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "Meeting minutes.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "xqGIjsmQPRPq",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "BkmGEUBkAvZC",
+ "S9e1O6walQlq",
+ "xqGIjsmQPRPq"
+ ],
+ "title": "Photos from the trip",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "book",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "bookZoomLevel",
+ "value": "2",
+ "isInheritable": false,
+ "position": 0
+ }
+ ],
+ "attachments": [],
+ "dirFileName": "Photos from the trip",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "1EdiWGOQB4RK",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "BkmGEUBkAvZC",
+ "S9e1O6walQlq",
+ "xqGIjsmQPRPq",
+ "1EdiWGOQB4RK"
+ ],
+ "title": "01.jpeg",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "image",
+ "mime": "image/jpg",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "originalFileName",
+ "value": "01.jpeg",
+ "isInheritable": false,
+ "position": 1
+ },
+ {
+ "type": "label",
+ "name": "fileSize",
+ "value": "16881",
+ "isInheritable": false,
+ "position": 2
+ }
+ ],
+ "dataFileName": "01.jpeg",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "NUeVuPpK1N7f",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "BkmGEUBkAvZC",
+ "S9e1O6walQlq",
+ "xqGIjsmQPRPq",
+ "NUeVuPpK1N7f"
+ ],
+ "title": "02.jpeg",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "image",
+ "mime": "image/jpg",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "originalFileName",
+ "value": "02.jpeg",
+ "isInheritable": false,
+ "position": 1
+ },
+ {
+ "type": "label",
+ "name": "fileSize",
+ "value": "31697",
+ "isInheritable": false,
+ "position": 2
+ }
+ ],
+ "dataFileName": "02.jpeg",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "u3Cb1NkuHVFu",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "BkmGEUBkAvZC",
+ "S9e1O6walQlq",
+ "xqGIjsmQPRPq",
+ "u3Cb1NkuHVFu"
+ ],
+ "title": "03.jpeg",
+ "notePosition": 20,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "image",
+ "mime": "image/jpg",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "originalFileName",
+ "value": "03.jpeg",
+ "isInheritable": false,
+ "position": 1
+ },
+ {
+ "type": "label",
+ "name": "fileSize",
+ "value": "72522",
+ "isInheritable": false,
+ "position": 2
+ }
+ ],
+ "dataFileName": "03.jpeg",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "RMk5ZL0mw2vh",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "BkmGEUBkAvZC",
+ "S9e1O6walQlq",
+ "xqGIjsmQPRPq",
+ "RMk5ZL0mw2vh"
+ ],
+ "title": "04.jpeg",
+ "notePosition": 30,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "image",
+ "mime": "image/jpg",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "originalFileName",
+ "value": "04.jpeg",
+ "isInheritable": false,
+ "position": 1
+ },
+ {
+ "type": "label",
+ "name": "fileSize",
+ "value": "43670",
+ "isInheritable": false,
+ "position": 2
+ }
+ ],
+ "dataFileName": "04.jpeg",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "lA77h6Gld6Af",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "BkmGEUBkAvZC",
+ "S9e1O6walQlq",
+ "xqGIjsmQPRPq",
+ "lA77h6Gld6Af"
+ ],
+ "title": "05.jpeg",
+ "notePosition": 40,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "image",
+ "mime": "image/jpg",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "originalFileName",
+ "value": "05.jpeg",
+ "isInheritable": false,
+ "position": 1
+ },
+ {
+ "type": "label",
+ "name": "fileSize",
+ "value": "22327",
+ "isInheritable": false,
+ "position": 2
+ }
+ ],
+ "dataFileName": "05.jpeg",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "5bKca24TwvXi",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "BkmGEUBkAvZC",
+ "S9e1O6walQlq",
+ "xqGIjsmQPRPq",
+ "5bKca24TwvXi"
+ ],
+ "title": "06.jpeg",
+ "notePosition": 50,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "image",
+ "mime": "image/jpg",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "originalFileName",
+ "value": "06.jpeg",
+ "isInheritable": false,
+ "position": 1
+ },
+ {
+ "type": "label",
+ "name": "fileSize",
+ "value": "79751",
+ "isInheritable": false,
+ "position": 2
+ }
+ ],
+ "dataFileName": "06.jpeg",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "Dw80f8XRUEkb",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "BkmGEUBkAvZC",
+ "S9e1O6walQlq",
+ "xqGIjsmQPRPq",
+ "Dw80f8XRUEkb"
+ ],
+ "title": "07.jpeg",
+ "notePosition": 60,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "image",
+ "mime": "image/jpg",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "originalFileName",
+ "value": "07.jpeg",
+ "isInheritable": false,
+ "position": 1
+ },
+ {
+ "type": "label",
+ "name": "fileSize",
+ "value": "30223",
+ "isInheritable": false,
+ "position": 2
+ }
+ ],
+ "dataFileName": "07.jpeg",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "3B4wY3ysFzUL",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "BkmGEUBkAvZC",
+ "S9e1O6walQlq",
+ "xqGIjsmQPRPq",
+ "3B4wY3ysFzUL"
+ ],
+ "title": "08.jpeg",
+ "notePosition": 70,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "image",
+ "mime": "image/jpg",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "originalFileName",
+ "value": "08.jpeg",
+ "isInheritable": false,
+ "position": 1
+ },
+ {
+ "type": "label",
+ "name": "fileSize",
+ "value": "39928",
+ "isInheritable": false,
+ "position": 2
+ }
+ ],
+ "dataFileName": "08.jpeg",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "8rJBABNUlLlJ",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "BkmGEUBkAvZC",
+ "S9e1O6walQlq",
+ "xqGIjsmQPRPq",
+ "8rJBABNUlLlJ"
+ ],
+ "title": "09.jpeg",
+ "notePosition": 80,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "image",
+ "mime": "image/jpg",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "originalFileName",
+ "value": "09.jpeg",
+ "isInheritable": false,
+ "position": 1
+ },
+ {
+ "type": "label",
+ "name": "fileSize",
+ "value": "48918",
+ "isInheritable": false,
+ "position": 2
+ }
+ ],
+ "dataFileName": "09.jpeg",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "2mkSjqnJhj9i",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "BkmGEUBkAvZC",
+ "S9e1O6walQlq",
+ "xqGIjsmQPRPq",
+ "2mkSjqnJhj9i"
+ ],
+ "title": "10.jpeg",
+ "notePosition": 90,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "image",
+ "mime": "image/jpg",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "originalFileName",
+ "value": "10.jpeg",
+ "isInheritable": false,
+ "position": 1
+ },
+ {
+ "type": "label",
+ "name": "fileSize",
+ "value": "44150",
+ "isInheritable": false,
+ "position": 2
+ }
+ ],
+ "dataFileName": "10.jpeg",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "oPcnET6xqcz1",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "BkmGEUBkAvZC",
+ "S9e1O6walQlq",
+ "xqGIjsmQPRPq",
+ "oPcnET6xqcz1"
+ ],
+ "title": "11.jpeg",
+ "notePosition": 100,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "image",
+ "mime": "image/jpg",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "originalFileName",
+ "value": "11.jpeg",
+ "isInheritable": false,
+ "position": 1
+ },
+ {
+ "type": "label",
+ "name": "fileSize",
+ "value": "76231",
+ "isInheritable": false,
+ "position": 2
+ }
+ ],
+ "dataFileName": "11.jpeg",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "V1OwJwsPuBzj",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "BkmGEUBkAvZC",
+ "S9e1O6walQlq",
+ "xqGIjsmQPRPq",
+ "V1OwJwsPuBzj"
+ ],
+ "title": "12.jpeg",
+ "notePosition": 110,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "image",
+ "mime": "image/jpg",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "originalFileName",
+ "value": "12.jpeg",
+ "isInheritable": false,
+ "position": 1
+ },
+ {
+ "type": "label",
+ "name": "fileSize",
+ "value": "44286",
+ "isInheritable": false,
+ "position": 2
+ }
+ ],
+ "dataFileName": "12.jpeg",
+ "attachments": []
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "vH389HhCX3to",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "BkmGEUBkAvZC",
+ "S9e1O6walQlq",
+ "vH389HhCX3to"
+ ],
+ "title": "Send invites for christmas party",
+ "notePosition": 20,
+ "prefix": "TODO",
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "task",
+ "value": "",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "label",
+ "name": "location",
+ "value": "work",
+ "isInheritable": false,
+ "position": 30
+ },
+ {
+ "type": "label",
+ "name": "cssClass",
+ "value": "todo",
+ "isInheritable": false,
+ "position": 40
+ },
+ {
+ "type": "label",
+ "name": "cssClass",
+ "value": "todo",
+ "isInheritable": false,
+ "position": 50
+ },
+ {
+ "type": "label",
+ "name": "todoDate",
+ "value": "2021-12-18",
+ "isInheritable": false,
+ "position": 60
+ }
+ ],
+ "format": "html",
+ "dataFileName": "TODO - Send invites for christ.html",
+ "attachments": []
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "Xa15h4cRL6O8",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "BkmGEUBkAvZC",
+ "Xa15h4cRL6O8"
+ ],
+ "title": "19 - Tuesday",
+ "notePosition": 20,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "relation",
+ "name": "template",
+ "value": "sINmXkCzncB4",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "label",
+ "name": "dateNote",
+ "value": "2021-12-19",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "label",
+ "name": "weight",
+ "value": "75.4",
+ "isInheritable": false,
+ "position": 30
+ }
+ ],
+ "format": "html",
+ "dataFileName": "19 - Tuesday.html",
+ "attachments": [],
+ "dirFileName": "19 - Tuesday",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "KaNVFkFBdkvZ",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "BkmGEUBkAvZC",
+ "Xa15h4cRL6O8",
+ "KaNVFkFBdkvZ"
+ ],
+ "title": "Dentist appointment",
+ "notePosition": 0,
+ "prefix": "DONE",
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "task",
+ "value": "",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "label",
+ "name": "tag",
+ "value": "health",
+ "isInheritable": false,
+ "position": 30
+ },
+ {
+ "type": "label",
+ "name": "cssClass",
+ "value": "done",
+ "isInheritable": false,
+ "position": 40
+ },
+ {
+ "type": "label",
+ "name": "todoDate",
+ "value": "2021-12-19",
+ "isInheritable": false,
+ "position": 50
+ },
+ {
+ "type": "label",
+ "name": "doneDate",
+ "value": "2021-12-19",
+ "isInheritable": false,
+ "position": 60
+ }
+ ],
+ "format": "html",
+ "dataFileName": "DONE - Dentist appointment.html",
+ "attachments": []
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "mMQKGLEGtRHn",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "BkmGEUBkAvZC",
+ "mMQKGLEGtRHn"
+ ],
+ "title": "20 - Wednesday",
+ "notePosition": 30,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "relation",
+ "name": "template",
+ "value": "sINmXkCzncB4",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "label",
+ "name": "dateNote",
+ "value": "2021-12-20",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "label",
+ "name": "weight",
+ "value": "75.2",
+ "isInheritable": false,
+ "position": 30
+ }
+ ],
+ "format": "html",
+ "dataFileName": "20 - Wednesday.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "ZZz9RKYGLcK7",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "BkmGEUBkAvZC",
+ "ZZz9RKYGLcK7"
+ ],
+ "title": "21 - Thursday",
+ "notePosition": 40,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "dateNote",
+ "value": "2021-12-21",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "relation",
+ "name": "template",
+ "value": "sINmXkCzncB4",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "label",
+ "name": "weight",
+ "value": "76",
+ "isInheritable": false,
+ "position": 30
+ }
+ ],
+ "format": "html",
+ "dataFileName": "21 - Thursday.html",
+ "attachments": [],
+ "dirFileName": "21 - Thursday",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "hXwLRiT7g4dE",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "BkmGEUBkAvZC",
+ "ZZz9RKYGLcK7",
+ "hXwLRiT7g4dE"
+ ],
+ "title": "Christmas shopping",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": true,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "Christmas shopping.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "jpcqxgiEtJkn",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "BkmGEUBkAvZC",
+ "ZZz9RKYGLcK7",
+ "jpcqxgiEtJkn"
+ ],
+ "title": "Office party",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "Office party.html",
+ "attachments": []
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "KgE3kYIT24Sb",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "BkmGEUBkAvZC",
+ "KgE3kYIT24Sb"
+ ],
+ "title": "22 - Friday",
+ "notePosition": 50,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "dateNote",
+ "value": "2021-12-22",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "relation",
+ "name": "template",
+ "value": "sINmXkCzncB4",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "label",
+ "name": "weight",
+ "value": "75.9",
+ "isInheritable": false,
+ "position": 30
+ }
+ ],
+ "format": "html",
+ "dataFileName": "22 - Friday.html",
+ "attachments": [],
+ "dirFileName": "22 - Friday",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "AEa2Sy5UwdT4",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "BkmGEUBkAvZC",
+ "KgE3kYIT24Sb",
+ "AEa2Sy5UwdT4"
+ ],
+ "title": "Christmas shopping",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "Christmas shopping.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "NhSSbIObzEsM",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "BkmGEUBkAvZC",
+ "KgE3kYIT24Sb",
+ "NhSSbIObzEsM"
+ ],
+ "title": "The Mechanical",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "relation",
+ "name": "template",
+ "value": "ODEzxhfMalvQ",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "label",
+ "name": "link",
+ "value": "https://www.amazon.com/Mechanical-Alchemy-Wars-Ian-Tregillis/dp/0316248002",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "label",
+ "name": "author",
+ "value": "Ian Tregillis",
+ "isInheritable": false,
+ "position": 30
+ },
+ {
+ "type": "label",
+ "name": "readingStart",
+ "value": "2018-05-05",
+ "isInheritable": false,
+ "position": 40
+ },
+ {
+ "type": "label",
+ "name": "readingEnd",
+ "value": "2018-05-23",
+ "isInheritable": false,
+ "position": 50
+ }
+ ],
+ "format": "html",
+ "dataFileName": "The Mechanical.html",
+ "attachments": [],
+ "dirFileName": "The Mechanical",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "QGIhTr2UNF8V",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "BkmGEUBkAvZC",
+ "KgE3kYIT24Sb",
+ "NhSSbIObzEsM",
+ "QGIhTr2UNF8V"
+ ],
+ "title": "Highlights",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "Highlights.html",
+ "attachments": []
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "uDulJuuQUQV9",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "BkmGEUBkAvZC",
+ "uDulJuuQUQV9"
+ ],
+ "title": "23 - Saturday",
+ "notePosition": 60,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "relation",
+ "name": "template",
+ "value": "sINmXkCzncB4",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "label",
+ "name": "dateNote",
+ "value": "2021-12-23",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "label",
+ "name": "weight",
+ "value": "75.6",
+ "isInheritable": false,
+ "position": 30
+ }
+ ],
+ "format": "html",
+ "dataFileName": "23 - Saturday.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "cG0jN1I9tYPs",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "BkmGEUBkAvZC",
+ "cG0jN1I9tYPs"
+ ],
+ "title": "24 - Sunday - Christmas Eve!",
+ "notePosition": 70,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "relation",
+ "name": "template",
+ "value": "sINmXkCzncB4",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "label",
+ "name": "dateNote",
+ "value": "2021-12-24",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "label",
+ "name": "weight",
+ "value": "76.1",
+ "isInheritable": false,
+ "position": 30
+ }
+ ],
+ "format": "html",
+ "dataFileName": "24 - Sunday - Christmas Eve!.html",
+ "attachments": [],
+ "dirFileName": "24 - Sunday - Christmas Eve!",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "xybXfFXh4kbk",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "BkmGEUBkAvZC",
+ "cG0jN1I9tYPs",
+ "xybXfFXh4kbk"
+ ],
+ "title": "Buy a board game for Alice",
+ "notePosition": 0,
+ "prefix": "DONE",
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "task",
+ "value": "",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "label",
+ "name": "location",
+ "value": "mall",
+ "isInheritable": false,
+ "position": 30
+ },
+ {
+ "type": "label",
+ "name": "cssClass",
+ "value": "done",
+ "isInheritable": false,
+ "position": 40
+ },
+ {
+ "type": "label",
+ "name": "tag",
+ "value": "christmas",
+ "isInheritable": false,
+ "position": 50
+ },
+ {
+ "type": "label",
+ "name": "tag",
+ "value": "shopping",
+ "isInheritable": false,
+ "position": 60
+ },
+ {
+ "type": "label",
+ "name": "todoDate",
+ "value": "2021-12-20",
+ "isInheritable": false,
+ "position": 70
+ },
+ {
+ "type": "label",
+ "name": "doneDate",
+ "value": "2021-12-24",
+ "isInheritable": false,
+ "position": 80
+ }
+ ],
+ "format": "html",
+ "dataFileName": "DONE - Buy a board game for Al.html",
+ "attachments": [
+ {
+ "attachmentId": "pZ0Azmg2ivRC",
+ "title": "codenames.jpg",
+ "role": "image",
+ "mime": "image/jpg",
+ "position": 10,
+ "dataFileName": "DONE - Buy a board game fo.jpg"
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "HnU0m7ECI7G5",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "BkmGEUBkAvZC",
+ "cG0jN1I9tYPs",
+ "HnU0m7ECI7G5"
+ ],
+ "title": "Buy milk",
+ "notePosition": 10,
+ "prefix": "TODO",
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "task",
+ "value": "",
+ "isInheritable": false,
+ "position": 1
+ },
+ {
+ "type": "label",
+ "name": "location",
+ "value": "tesco",
+ "isInheritable": false,
+ "position": 3
+ },
+ {
+ "type": "label",
+ "name": "cssClass",
+ "value": "todo",
+ "isInheritable": false,
+ "position": 4
+ },
+ {
+ "type": "label",
+ "name": "cssClass",
+ "value": "todo",
+ "isInheritable": false,
+ "position": 4
+ },
+ {
+ "type": "label",
+ "name": "tag",
+ "value": "groceries",
+ "isInheritable": false,
+ "position": 5
+ },
+ {
+ "type": "label",
+ "name": "tag",
+ "value": "shopping",
+ "isInheritable": false,
+ "position": 7
+ },
+ {
+ "type": "label",
+ "name": "todoDate",
+ "value": "2021-12-24",
+ "isInheritable": false,
+ "position": 6
+ }
+ ],
+ "format": "html",
+ "dataFileName": "TODO - Buy milk.html",
+ "attachments": []
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "l0Hn9dXX4wJ7",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "BkmGEUBkAvZC",
+ "l0Hn9dXX4wJ7"
+ ],
+ "title": "30 - Thursday",
+ "notePosition": 80,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "relation",
+ "name": "template",
+ "value": "sINmXkCzncB4",
+ "isInheritable": false,
+ "position": 30
+ },
+ {
+ "type": "label",
+ "name": "dateNote",
+ "value": "2021-12-30",
+ "isInheritable": false,
+ "position": 31
+ }
+ ],
+ "format": "html",
+ "dataFileName": "30 - Thursday.html",
+ "attachments": []
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "2kH7aQSosO9C",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "2kH7aQSosO9C"
+ ],
+ "title": "Epics",
+ "notePosition": 30,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "Epics.html",
+ "attachments": [],
+ "dirFileName": "Epics",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "BH0WNWPyihkF",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "2kH7aQSosO9C",
+ "BH0WNWPyihkF"
+ ],
+ "title": "Christmas",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "Christmas.html",
+ "attachments": [],
+ "dirFileName": "Christmas",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "PDRNLWTHfOi0",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "2kH7aQSosO9C",
+ "BH0WNWPyihkF",
+ "PDRNLWTHfOi0"
+ ],
+ "title": "Vacation days",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "Vacation days.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "r45qXBox4mts",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "2kH7aQSosO9C",
+ "BH0WNWPyihkF",
+ "r45qXBox4mts"
+ ],
+ "title": "Christmas dinner",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "Christmas dinner.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "5t7iAUBdEndw",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "2kH7aQSosO9C",
+ "BH0WNWPyihkF",
+ "5t7iAUBdEndw"
+ ],
+ "title": "Shopping",
+ "notePosition": 20,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "attachments": [],
+ "dirFileName": "Shopping",
+ "children": [
+ {
+ "isClone": true,
+ "noteId": "RNf8bX9CdR1k",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "2kH7aQSosO9C",
+ "BH0WNWPyihkF",
+ "5t7iAUBdEndw",
+ "RNf8bX9CdR1k"
+ ],
+ "title": "Christmas gift ideas",
+ "prefix": "28. 11. 2017",
+ "dataFileName": "28. 11. 2017 - Christmas gift ideas.clone.html",
+ "type": "text",
+ "format": "html"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "2p3IczsCyfFH",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "3H4RMc45XIpI",
+ "2kH7aQSosO9C",
+ "2p3IczsCyfFH"
+ ],
+ "title": "Vacation",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "Vacation.html",
+ "attachments": []
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "sINmXkCzncB4",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "eYIqnBvdAmaE",
+ "sINmXkCzncB4"
+ ],
+ "title": "Day template",
+ "notePosition": 20,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "label:weight",
+ "value": "promoted,number,single,precision=1",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bx-notepad",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "label",
+ "name": "excludeFromNoteMap",
+ "value": "",
+ "isInheritable": false,
+ "position": 30
+ }
+ ],
+ "format": "html",
+ "dataFileName": "Day template.html",
+ "attachments": []
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "HGcABfDS6a51",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "HGcABfDS6a51"
+ ],
+ "title": "Tech",
+ "notePosition": 40,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bx-desktop",
+ "isInheritable": false,
+ "position": 10
+ }
+ ],
+ "format": "html",
+ "dataFileName": "Tech.html",
+ "attachments": [],
+ "dirFileName": "Tech",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "1wgEZXIXYS9H",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "HGcABfDS6a51",
+ "1wgEZXIXYS9H"
+ ],
+ "title": "Security",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bx-lock-alt",
+ "isInheritable": false,
+ "position": 10
+ }
+ ],
+ "format": "html",
+ "attachments": [],
+ "dirFileName": "Security",
+ "children": [
+ {
+ "isClone": true,
+ "noteId": "AaxrGGwyIPxO",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "HGcABfDS6a51",
+ "1wgEZXIXYS9H",
+ "AaxrGGwyIPxO"
+ ],
+ "title": "Trusted timestamping",
+ "prefix": null,
+ "dataFileName": "Trusted timestamping.clone.html",
+ "type": "text",
+ "format": "html"
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "7Sbzd7Qd7nSn",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "HGcABfDS6a51",
+ "7Sbzd7Qd7nSn"
+ ],
+ "title": "Linux",
+ "notePosition": 20,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bxl-tux",
+ "isInheritable": false,
+ "position": 10
+ }
+ ],
+ "format": "html",
+ "attachments": [],
+ "dirFileName": "Linux",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "zLD6PepcrYhv",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "HGcABfDS6a51",
+ "7Sbzd7Qd7nSn",
+ "zLD6PepcrYhv"
+ ],
+ "title": "History",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "History.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "rwXwXJUFWswH",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "HGcABfDS6a51",
+ "7Sbzd7Qd7nSn",
+ "rwXwXJUFWswH"
+ ],
+ "title": "Bash scripting",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "Bash scripting.html",
+ "attachments": [],
+ "dirFileName": "Bash scripting",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "F7QT7w1jFQ4S",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "HGcABfDS6a51",
+ "7Sbzd7Qd7nSn",
+ "rwXwXJUFWswH",
+ "F7QT7w1jFQ4S"
+ ],
+ "title": "While loop",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "While loop.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "Xllm9YiBRXqN",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "HGcABfDS6a51",
+ "7Sbzd7Qd7nSn",
+ "rwXwXJUFWswH",
+ "Xllm9YiBRXqN"
+ ],
+ "title": "Bash startup modes",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "Bash startup modes.html",
+ "attachments": []
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "E8inmLohu8XE",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "HGcABfDS6a51",
+ "7Sbzd7Qd7nSn",
+ "E8inmLohu8XE"
+ ],
+ "title": "Ubuntu",
+ "notePosition": 20,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "Ubuntu.html",
+ "attachments": [],
+ "dirFileName": "Ubuntu",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "elwY4igN6EGl",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "HGcABfDS6a51",
+ "7Sbzd7Qd7nSn",
+ "E8inmLohu8XE",
+ "elwY4igN6EGl"
+ ],
+ "title": "Unity shortcuts",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "Unity shortcuts.html",
+ "attachments": []
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "VpNAHIDDlcLh",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "HGcABfDS6a51",
+ "VpNAHIDDlcLh"
+ ],
+ "title": "Programming",
+ "notePosition": 30,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bx-code-alt",
+ "isInheritable": false,
+ "position": 10
+ }
+ ],
+ "format": "html",
+ "attachments": [],
+ "dirFileName": "Programming",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "penrSU9H9j0z",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "HGcABfDS6a51",
+ "VpNAHIDDlcLh",
+ "penrSU9H9j0z"
+ ],
+ "title": "Java",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bxl-java",
+ "isInheritable": false,
+ "position": 10
+ }
+ ],
+ "format": "html",
+ "dataFileName": "Java.html",
+ "attachments": []
+ },
+ {
+ "isClone": true,
+ "noteId": "rwXwXJUFWswH",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "HGcABfDS6a51",
+ "VpNAHIDDlcLh",
+ "rwXwXJUFWswH"
+ ],
+ "title": "Bash scripting",
+ "prefix": null,
+ "dataFileName": "Bash scripting.clone.html",
+ "type": "text",
+ "format": "html"
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "B16t4MPcxaAs",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "HGcABfDS6a51",
+ "B16t4MPcxaAs"
+ ],
+ "title": "Node.js",
+ "notePosition": 40,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "book",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bxl-nodejs",
+ "isInheritable": false,
+ "position": 10
+ }
+ ],
+ "attachments": [],
+ "dirFileName": "Node.js",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "UDLLOhsgyVLk",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "HGcABfDS6a51",
+ "B16t4MPcxaAs",
+ "UDLLOhsgyVLk"
+ ],
+ "title": "Intro",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "Intro.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "LWpxsRzR1WbA",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "HGcABfDS6a51",
+ "B16t4MPcxaAs",
+ "LWpxsRzR1WbA"
+ ],
+ "title": "Overview",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "Overview.html",
+ "attachments": [],
+ "dirFileName": "Overview",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "PHD3wfCknzIJ",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "HGcABfDS6a51",
+ "B16t4MPcxaAs",
+ "LWpxsRzR1WbA",
+ "PHD3wfCknzIJ"
+ ],
+ "title": "History",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "History.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "ZBPDxGMrNx7O",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "HGcABfDS6a51",
+ "B16t4MPcxaAs",
+ "LWpxsRzR1WbA",
+ "ZBPDxGMrNx7O"
+ ],
+ "title": "Platform architecture",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "Platform architecture.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "dXjFj3SB4m1I",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "HGcABfDS6a51",
+ "B16t4MPcxaAs",
+ "LWpxsRzR1WbA",
+ "dXjFj3SB4m1I"
+ ],
+ "title": "Industry support",
+ "notePosition": 20,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "Industry support.html",
+ "attachments": []
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "TRT99FK2qOzt",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "HGcABfDS6a51",
+ "B16t4MPcxaAs",
+ "TRT99FK2qOzt"
+ ],
+ "title": "Releases",
+ "notePosition": 20,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "Releases.html",
+ "attachments": []
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "k7rcoITZRsi6",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "k7rcoITZRsi6"
+ ],
+ "title": "Note Types",
+ "notePosition": 60,
+ "prefix": null,
+ "isExpanded": true,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bx-file",
+ "isInheritable": false,
+ "position": 10
+ }
+ ],
+ "format": "html",
+ "attachments": [],
+ "dirFileName": "Note Types",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "P1OnNHRhFn9u",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "k7rcoITZRsi6",
+ "P1OnNHRhFn9u"
+ ],
+ "title": "Canvas",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": true,
+ "type": "canvas",
+ "mime": "application/json",
+ "attributes": [],
+ "dataFileName": "Canvas.json",
+ "attachments": [
+ {
+ "attachmentId": "LrYmWTdvBYpX",
+ "title": "canvas-export.svg",
+ "role": "image",
+ "mime": "image/svg+xml",
+ "position": 0,
+ "dataFileName": "Canvas_canvas-export.svg"
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "lZlMer9EkwF8",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "k7rcoITZRsi6",
+ "lZlMer9EkwF8"
+ ],
+ "title": "Mermaid Diagrams",
+ "notePosition": 20,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "book",
+ "mime": "",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bx-selection",
+ "isInheritable": false,
+ "position": 10
+ }
+ ],
+ "attachments": [],
+ "dirFileName": "Mermaid Diagrams",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "DALQSU4fng4F",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "k7rcoITZRsi6",
+ "lZlMer9EkwF8",
+ "DALQSU4fng4F"
+ ],
+ "title": "Flow",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "mermaid",
+ "mime": "text/mermaid",
+ "attributes": [],
+ "dataFileName": "Flow.txt",
+ "attachments": [
+ {
+ "attachmentId": "6u2TW8zweuBN",
+ "title": "mermaid-export.svg",
+ "role": "image",
+ "mime": "image/svg+xml",
+ "position": 10,
+ "dataFileName": "Flow_mermaid-export.svg"
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "g7rjYwoleBlR",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "k7rcoITZRsi6",
+ "lZlMer9EkwF8",
+ "g7rjYwoleBlR"
+ ],
+ "title": "Flow (ELK)",
+ "notePosition": 11,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "mermaid",
+ "mime": "text/mermaid",
+ "attributes": [],
+ "dataFileName": "Flow (ELK).txt",
+ "attachments": [
+ {
+ "attachmentId": "9TKNS3IHYYQq",
+ "title": "mermaid-export.svg",
+ "role": "image",
+ "mime": "image/svg+xml",
+ "position": 10,
+ "dataFileName": "Flow (ELK)_mermaid-export.svg"
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "t73XNJNTTwQp",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "k7rcoITZRsi6",
+ "lZlMer9EkwF8",
+ "t73XNJNTTwQp"
+ ],
+ "title": "Sequence",
+ "notePosition": 20,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "mermaid",
+ "mime": "text/mermaid",
+ "attributes": [],
+ "dataFileName": "Sequence.txt",
+ "attachments": [
+ {
+ "attachmentId": "XfWi1TqleVbL",
+ "title": "mermaid-export.svg",
+ "role": "image",
+ "mime": "image/svg+xml",
+ "position": 10,
+ "dataFileName": "Sequence_mermaid-export.svg"
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "6wdYxWSVuXof",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "k7rcoITZRsi6",
+ "lZlMer9EkwF8",
+ "6wdYxWSVuXof"
+ ],
+ "title": "Gantt",
+ "notePosition": 30,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "mermaid",
+ "mime": "text/plain",
+ "attributes": [],
+ "dataFileName": "Gantt.txt",
+ "attachments": [
+ {
+ "attachmentId": "zCjOBL5UP9ii",
+ "title": "mermaid-export.svg",
+ "role": "image",
+ "mime": "image/svg+xml",
+ "position": 10,
+ "dataFileName": "Gantt_mermaid-export.svg"
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "WKL3yssKyoth",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "k7rcoITZRsi6",
+ "lZlMer9EkwF8",
+ "WKL3yssKyoth"
+ ],
+ "title": "Class",
+ "notePosition": 40,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "mermaid",
+ "mime": "text/plain",
+ "attributes": [],
+ "dataFileName": "Class.txt",
+ "attachments": [
+ {
+ "attachmentId": "sRADq0QJpaYr",
+ "title": "mermaid-export.svg",
+ "role": "image",
+ "mime": "image/svg+xml",
+ "position": 10,
+ "dataFileName": "Class_mermaid-export.svg"
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "v9TM7cCXBILP",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "k7rcoITZRsi6",
+ "lZlMer9EkwF8",
+ "v9TM7cCXBILP"
+ ],
+ "title": "State",
+ "notePosition": 50,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "mermaid",
+ "mime": "text/plain",
+ "attributes": [],
+ "dataFileName": "State.txt",
+ "attachments": [
+ {
+ "attachmentId": "NhPv2lQln1g4",
+ "title": "mermaid-export.svg",
+ "role": "image",
+ "mime": "image/svg+xml",
+ "position": 10,
+ "dataFileName": "State_mermaid-export.svg"
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "1EDhd9QJyulq",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "k7rcoITZRsi6",
+ "lZlMer9EkwF8",
+ "1EDhd9QJyulq"
+ ],
+ "title": "Mind Map",
+ "notePosition": 60,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "mermaid",
+ "mime": "text/mermaid",
+ "attributes": [],
+ "dataFileName": "Mind Map.txt",
+ "attachments": [
+ {
+ "attachmentId": "Q8EircLk65HH",
+ "title": "mermaid-export.svg",
+ "role": "image",
+ "mime": "image/svg+xml",
+ "position": 10,
+ "dataFileName": "Mind Map_mermaid-export.svg"
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "n32hpxSA2fP8",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "k7rcoITZRsi6",
+ "lZlMer9EkwF8",
+ "n32hpxSA2fP8"
+ ],
+ "title": "Pie",
+ "notePosition": 70,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "mermaid",
+ "mime": "text/plain",
+ "attributes": [],
+ "dataFileName": "Pie.txt",
+ "attachments": [
+ {
+ "attachmentId": "6xhRWdFidyIg",
+ "title": "mermaid-export.svg",
+ "role": "image",
+ "mime": "image/svg+xml",
+ "position": 10,
+ "dataFileName": "Pie_mermaid-export.svg"
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "T0QEYaEv7PmE",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "k7rcoITZRsi6",
+ "lZlMer9EkwF8",
+ "T0QEYaEv7PmE"
+ ],
+ "title": "Journey",
+ "notePosition": 80,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "mermaid",
+ "mime": "text/plain",
+ "attributes": [],
+ "dataFileName": "Journey.txt",
+ "attachments": [
+ {
+ "attachmentId": "sxLqDNmjlbK4",
+ "title": "mermaid-export.svg",
+ "role": "image",
+ "mime": "image/svg+xml",
+ "position": 10,
+ "dataFileName": "Journey_mermaid-export.svg"
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "P9QvwWzLZnXJ",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "k7rcoITZRsi6",
+ "lZlMer9EkwF8",
+ "P9QvwWzLZnXJ"
+ ],
+ "title": "Git",
+ "notePosition": 90,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "mermaid",
+ "mime": "text/plain",
+ "attributes": [],
+ "dataFileName": "Git.txt",
+ "attachments": [
+ {
+ "attachmentId": "tIoCBIaY50Jm",
+ "title": "mermaid-export.svg",
+ "role": "image",
+ "mime": "image/svg+xml",
+ "position": 10,
+ "dataFileName": "Git_mermaid-export.svg"
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "19O4nsY7dkPt",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "k7rcoITZRsi6",
+ "lZlMer9EkwF8",
+ "19O4nsY7dkPt"
+ ],
+ "title": "Entity Relationship",
+ "notePosition": 100,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "mermaid",
+ "mime": "text/plain",
+ "attributes": [],
+ "dataFileName": "Entity Relationship.txt",
+ "attachments": [
+ {
+ "attachmentId": "AyKZhKQIE5w9",
+ "title": "mermaid-export.svg",
+ "role": "image",
+ "mime": "image/svg+xml",
+ "position": 10,
+ "dataFileName": "Entity Relationship_mermai.svg"
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "2izpY6SPbmhp",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "k7rcoITZRsi6",
+ "lZlMer9EkwF8",
+ "2izpY6SPbmhp"
+ ],
+ "title": "Bar chart",
+ "notePosition": 110,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "mermaid",
+ "mime": "text/mermaid",
+ "attributes": [],
+ "dataFileName": "Bar chart.txt",
+ "attachments": [
+ {
+ "attachmentId": "r1wMURlU52l8",
+ "title": "mermaid-export.svg",
+ "role": "image",
+ "mime": "image/svg+xml",
+ "position": 10,
+ "dataFileName": "Bar chart_mermaid-export.svg"
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "hwx0dffwqIGg",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "k7rcoITZRsi6",
+ "lZlMer9EkwF8",
+ "hwx0dffwqIGg"
+ ],
+ "title": "C4",
+ "notePosition": 120,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "mermaid",
+ "mime": "text/plain",
+ "attributes": [],
+ "dataFileName": "C4.txt",
+ "attachments": [
+ {
+ "attachmentId": "6v2qO6zsygVC",
+ "title": "mermaid-export.svg",
+ "role": "image",
+ "mime": "image/svg+xml",
+ "position": 10,
+ "dataFileName": "C4_mermaid-export.svg"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "CN3CCLggUqf4",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "k7rcoITZRsi6",
+ "CN3CCLggUqf4"
+ ],
+ "title": "Mind Map",
+ "notePosition": 30,
+ "prefix": null,
+ "isExpanded": true,
+ "type": "mindMap",
+ "mime": "application/json",
+ "attributes": [],
+ "dataFileName": "Mind Map.json",
+ "attachments": [
+ {
+ "attachmentId": "xKxyCN02w5d2",
+ "title": "mindmap-export.svg",
+ "role": "image",
+ "mime": "image/svg+xml",
+ "position": 0,
+ "dataFileName": "Mind Map_mindmap-export.svg"
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "OdCVNGzsvWuv",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "k7rcoITZRsi6",
+ "OdCVNGzsvWuv"
+ ],
+ "title": "Geo Map (The Seven Wonders of the World)",
+ "notePosition": 40,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "geoMap",
+ "mime": "application/json",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "label:geolocation",
+ "value": "promoted,alias=Geolocation,single,text",
+ "isInheritable": true,
+ "position": 10
+ },
+ {
+ "type": "label",
+ "name": "hidePromotedAttributes",
+ "value": "",
+ "isInheritable": false,
+ "position": 20
+ }
+ ],
+ "dataFileName": "Geo Map (The Seven Wonders of .json",
+ "attachments": [],
+ "dirFileName": "Geo Map (The Seven Wonders of the World)",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "IdHyf4rlLmlO",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "k7rcoITZRsi6",
+ "OdCVNGzsvWuv",
+ "IdHyf4rlLmlO"
+ ],
+ "title": "The Colosseum, Rome, Italy",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "geolocation",
+ "value": "41.89024211851462, 12.492263083403595",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bx-circle",
+ "isInheritable": false,
+ "position": 30
+ }
+ ],
+ "format": "html",
+ "dataFileName": "The Colosseum, Rome, Italy.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "Wyp6vjVo0vuV",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "k7rcoITZRsi6",
+ "OdCVNGzsvWuv",
+ "Wyp6vjVo0vuV"
+ ],
+ "title": "The Great Wall of China",
+ "notePosition": 20,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "geolocation",
+ "value": "40.431907671437244, 116.57035343915216",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bx-selection",
+ "isInheritable": false,
+ "position": 30
+ }
+ ],
+ "format": "html",
+ "dataFileName": "The Great Wall of China.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "VsO5E97Y2mPy",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "k7rcoITZRsi6",
+ "OdCVNGzsvWuv",
+ "VsO5E97Y2mPy"
+ ],
+ "title": "The Taj Mahal, India",
+ "notePosition": 30,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "geolocation",
+ "value": "27.175173410074475, 78.04213146744753",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bx-arch",
+ "isInheritable": false,
+ "position": 30
+ }
+ ],
+ "format": "html",
+ "dataFileName": "The Taj Mahal, India.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "8nRYOMoDdWs3",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "k7rcoITZRsi6",
+ "OdCVNGzsvWuv",
+ "8nRYOMoDdWs3"
+ ],
+ "title": "Christ the Redeemer, Brazil",
+ "notePosition": 40,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "geolocation",
+ "value": "-22.951993968508837, -43.21044464113274",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bx-church",
+ "isInheritable": false,
+ "position": 30
+ }
+ ],
+ "format": "html",
+ "dataFileName": "Christ the Redeemer, Brazil.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "nZxMTxkP8AQ4",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "k7rcoITZRsi6",
+ "OdCVNGzsvWuv",
+ "nZxMTxkP8AQ4"
+ ],
+ "title": "Machu Picchu, Peru",
+ "notePosition": 50,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "geolocation",
+ "value": "-13.163198787170078, -72.54528356174288",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bxs-castle",
+ "isInheritable": false,
+ "position": 30
+ }
+ ],
+ "format": "html",
+ "dataFileName": "Machu Picchu, Peru.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "DtMcvaYKen9C",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "k7rcoITZRsi6",
+ "OdCVNGzsvWuv",
+ "DtMcvaYKen9C"
+ ],
+ "title": "Chichén Itzá, Mexico",
+ "notePosition": 60,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "geolocation",
+ "value": "20.678882007143176, -88.56836961554815",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bxs-component",
+ "isInheritable": false,
+ "position": 30
+ }
+ ],
+ "format": "html",
+ "dataFileName": "Chichén Itzá, Mexico.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "ZkR3GvsSQ0Xe",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "k7rcoITZRsi6",
+ "OdCVNGzsvWuv",
+ "ZkR3GvsSQ0Xe"
+ ],
+ "title": "Petra, Jordan",
+ "notePosition": 70,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "geolocation",
+ "value": "30.32084750671952, 35.481009100454926",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bxs-castle",
+ "isInheritable": false,
+ "position": 30
+ }
+ ],
+ "format": "html",
+ "dataFileName": "Petra, Jordan.html",
+ "attachments": []
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "L2NrzQACw0in",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "L2NrzQACw0in"
+ ],
+ "title": "Books",
+ "notePosition": 130,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "relation",
+ "name": "child:template",
+ "value": "ODEzxhfMalvQ",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "label",
+ "name": "wordCount",
+ "value": "",
+ "isInheritable": true,
+ "position": 20
+ },
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bx-book-open",
+ "isInheritable": false,
+ "position": 21
+ }
+ ],
+ "format": "html",
+ "attachments": [],
+ "dirFileName": "Books",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "Mzby9GxzBFl1",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "L2NrzQACw0in",
+ "Mzby9GxzBFl1"
+ ],
+ "title": "To read",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "To read.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "ODEzxhfMalvQ",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "L2NrzQACw0in",
+ "ODEzxhfMalvQ"
+ ],
+ "title": "Book template",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bx-book-reader",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "label",
+ "name": "label:readingEnd",
+ "value": "promoted,single,date",
+ "isInheritable": false,
+ "position": 30
+ },
+ {
+ "type": "label",
+ "name": "label:readingStart",
+ "value": "promoted,single,date",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "label",
+ "name": "label:author",
+ "value": "promoted,single,text",
+ "isInheritable": false,
+ "position": 50
+ },
+ {
+ "type": "label",
+ "name": "template",
+ "value": "",
+ "isInheritable": false,
+ "position": 60
+ },
+ {
+ "type": "label",
+ "name": "label:link",
+ "value": "promoted,single,url",
+ "isInheritable": false,
+ "position": 40
+ }
+ ],
+ "format": "html",
+ "dataFileName": "Book template.html",
+ "attachments": [],
+ "dirFileName": "Book template",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "MFVR8MlrXQDQ",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "L2NrzQACw0in",
+ "ODEzxhfMalvQ",
+ "MFVR8MlrXQDQ"
+ ],
+ "title": "Highlights",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "Highlights.html",
+ "attachments": []
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "IWFmoH3KgkH2",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "L2NrzQACw0in",
+ "IWFmoH3KgkH2"
+ ],
+ "title": "Reviews",
+ "notePosition": 20,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "relation",
+ "name": "child:template",
+ "value": "ODEzxhfMalvQ",
+ "isInheritable": false,
+ "position": 10
+ }
+ ],
+ "format": "html",
+ "attachments": [],
+ "dirFileName": "Reviews",
+ "children": [
+ {
+ "isClone": true,
+ "noteId": "NhSSbIObzEsM",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "L2NrzQACw0in",
+ "IWFmoH3KgkH2",
+ "NhSSbIObzEsM"
+ ],
+ "title": "The Mechanical",
+ "prefix": null,
+ "dataFileName": "The Mechanical.clone.html",
+ "type": "text",
+ "format": "html"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "EBROzsTV1jh4",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "EBROzsTV1jh4"
+ ],
+ "title": "Work",
+ "notePosition": 150,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bx-briefcase-alt",
+ "isInheritable": false,
+ "position": 10
+ }
+ ],
+ "format": "html",
+ "attachments": [],
+ "dirFileName": "Work",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "WgVZEuZC0Hv8",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "EBROzsTV1jh4",
+ "WgVZEuZC0Hv8"
+ ],
+ "title": "HR",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "HR.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "oHu27s9uc20i",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "EBROzsTV1jh4",
+ "oHu27s9uc20i"
+ ],
+ "title": "Processes",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": true,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "Processes.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "mrSqOUvKrvVS",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "EBROzsTV1jh4",
+ "mrSqOUvKrvVS"
+ ],
+ "title": "Projects",
+ "notePosition": 20,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "Projects.html",
+ "attachments": []
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "6RKJSJ65qIn5",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "6RKJSJ65qIn5"
+ ],
+ "title": "Steel Blue",
+ "notePosition": 160,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "code",
+ "mime": "text/css",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "appTheme",
+ "value": "steel-blue",
+ "isInheritable": false,
+ "position": 0
+ }
+ ],
+ "dataFileName": "Steel Blue.css",
+ "attachments": [],
+ "dirFileName": "Steel Blue",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "83Ywz5JXl9pw",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "6RKJSJ65qIn5",
+ "83Ywz5JXl9pw"
+ ],
+ "title": "eb-garamond-v9-latin-regular.woff2",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "file",
+ "mime": "application/octet-stream",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "originalFileName",
+ "value": "eb-garamond-v9-latin-regular.woff2",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "label",
+ "name": "fileSize",
+ "value": "27608",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "label",
+ "name": "customResourceProvider",
+ "value": "fonts/garamond.woff2",
+ "isInheritable": false,
+ "position": 30
+ }
+ ],
+ "dataFileName": "eb-garamond-v9-latin-reg.woff2",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "K2IK5OccY70o",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "6RKJSJ65qIn5",
+ "K2IK5OccY70o"
+ ],
+ "title": "raleway-v12-latin-regular.woff2",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "file",
+ "mime": "application/octet-stream",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "originalFileName",
+ "value": "raleway-v12-latin-regular.woff2",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "label",
+ "name": "fileSize",
+ "value": "20444",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "label",
+ "name": "customResourceProvider",
+ "value": "fonts/raleway.woff2",
+ "isInheritable": false,
+ "position": 30
+ }
+ ],
+ "dataFileName": "raleway-v12-latin-regula.woff2",
+ "attachments": []
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "G8k9CPUVtDeE",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE"
+ ],
+ "title": "Scripting examples",
+ "notePosition": 350,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bxl-javascript",
+ "isInheritable": false,
+ "position": 1
+ }
+ ],
+ "format": "html",
+ "attachments": [],
+ "dirFileName": "Scripting examples",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "zQpMt8tYmYPL",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL"
+ ],
+ "title": "Task manager",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bx-task",
+ "isInheritable": false,
+ "position": 10
+ }
+ ],
+ "format": "html",
+ "dataFileName": "Task manager.html",
+ "attachments": [],
+ "dirFileName": "Task manager",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "749vDoR12ulD",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "749vDoR12ulD"
+ ],
+ "title": "Locations",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": true,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "taskLocationRoot",
+ "value": "",
+ "isInheritable": false,
+ "position": 0
+ },
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bx-map",
+ "isInheritable": false,
+ "position": 1
+ }
+ ],
+ "format": "html",
+ "attachments": [],
+ "dirFileName": "Locations",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "ps7IPoCpurK3",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "749vDoR12ulD",
+ "ps7IPoCpurK3"
+ ],
+ "title": "gym",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "taskLocationNote",
+ "value": "gym",
+ "isInheritable": false,
+ "position": 1
+ }
+ ],
+ "format": "html",
+ "dataFileName": "gym.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "gvgFDSKxYYRr",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "749vDoR12ulD",
+ "gvgFDSKxYYRr"
+ ],
+ "title": "work",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "taskLocationNote",
+ "value": "work",
+ "isInheritable": false,
+ "position": 1
+ }
+ ],
+ "format": "html",
+ "attachments": [],
+ "dirFileName": "work",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "Evz7c4Npu4PO",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "749vDoR12ulD",
+ "gvgFDSKxYYRr",
+ "Evz7c4Npu4PO"
+ ],
+ "title": "Send invites for christmas party",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "task",
+ "value": "",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "relation",
+ "name": "template",
+ "value": "7qiHS46jApK2",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "label",
+ "name": "location",
+ "value": "work",
+ "isInheritable": false,
+ "position": 30
+ },
+ {
+ "type": "label",
+ "name": "cssClass",
+ "value": "todo",
+ "isInheritable": false,
+ "position": 40
+ },
+ {
+ "type": "label",
+ "name": "cssClass",
+ "value": "todo",
+ "isInheritable": false,
+ "position": 50
+ },
+ {
+ "type": "label",
+ "name": "todoDate",
+ "value": "2021-12-18",
+ "isInheritable": false,
+ "position": 60
+ }
+ ],
+ "format": "html",
+ "dataFileName": "Send invites for christmas par.html",
+ "attachments": []
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "druYfHaAacBo",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "749vDoR12ulD",
+ "druYfHaAacBo"
+ ],
+ "title": "tesco",
+ "notePosition": 20,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "taskLocationNote",
+ "value": "tesco",
+ "isInheritable": false,
+ "position": 1
+ }
+ ],
+ "format": "html",
+ "attachments": [],
+ "dirFileName": "tesco",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "hu6fwfUGqnZR",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "749vDoR12ulD",
+ "druYfHaAacBo",
+ "hu6fwfUGqnZR"
+ ],
+ "title": "Buy milk",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "task",
+ "value": "",
+ "isInheritable": false,
+ "position": 1
+ },
+ {
+ "type": "relation",
+ "name": "template",
+ "value": "7qiHS46jApK2",
+ "isInheritable": false,
+ "position": 2
+ },
+ {
+ "type": "label",
+ "name": "location",
+ "value": "tesco",
+ "isInheritable": false,
+ "position": 3
+ },
+ {
+ "type": "label",
+ "name": "cssClass",
+ "value": "todo",
+ "isInheritable": false,
+ "position": 4
+ },
+ {
+ "type": "label",
+ "name": "cssClass",
+ "value": "todo",
+ "isInheritable": false,
+ "position": 4
+ },
+ {
+ "type": "label",
+ "name": "tag",
+ "value": "groceries",
+ "isInheritable": false,
+ "position": 5
+ },
+ {
+ "type": "label",
+ "name": "tag",
+ "value": "shopping",
+ "isInheritable": false,
+ "position": 7
+ },
+ {
+ "type": "label",
+ "name": "todoDate",
+ "value": "2021-12-24",
+ "isInheritable": false,
+ "position": 6
+ }
+ ],
+ "format": "html",
+ "dataFileName": "Buy milk.html",
+ "attachments": []
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "GrPlXB0Xk9k0",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "749vDoR12ulD",
+ "GrPlXB0Xk9k0"
+ ],
+ "title": "mall",
+ "notePosition": 30,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "taskLocationNote",
+ "value": "mall",
+ "isInheritable": false,
+ "position": 1
+ }
+ ],
+ "format": "html",
+ "attachments": [],
+ "dirFileName": "mall",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "4uh4j70LaKiG",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "749vDoR12ulD",
+ "GrPlXB0Xk9k0",
+ "4uh4j70LaKiG"
+ ],
+ "title": "Buy some book for Bob",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "task",
+ "value": "",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "relation",
+ "name": "template",
+ "value": "7qiHS46jApK2",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "label",
+ "name": "location",
+ "value": "mall",
+ "isInheritable": false,
+ "position": 30
+ },
+ {
+ "type": "label",
+ "name": "cssClass",
+ "value": "todo",
+ "isInheritable": false,
+ "position": 40
+ },
+ {
+ "type": "label",
+ "name": "cssClass",
+ "value": "todo",
+ "isInheritable": false,
+ "position": 50
+ },
+ {
+ "type": "label",
+ "name": "tag",
+ "value": "christmas",
+ "isInheritable": false,
+ "position": 60
+ },
+ {
+ "type": "label",
+ "name": "todoDate",
+ "value": "",
+ "isInheritable": false,
+ "position": 70
+ },
+ {
+ "type": "label",
+ "name": "tag",
+ "value": "shopping",
+ "isInheritable": false,
+ "position": 80
+ }
+ ],
+ "format": "html",
+ "dataFileName": "Buy some book for Bob.html",
+ "attachments": [],
+ "dirFileName": "Buy some book for Bob",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "DWjd4cV0s4YG",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "749vDoR12ulD",
+ "GrPlXB0Xk9k0",
+ "4uh4j70LaKiG",
+ "DWjd4cV0s4YG"
+ ],
+ "title": "Maybe Black Swan?",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [],
+ "format": "html",
+ "dataFileName": "Maybe Black Swan.html",
+ "attachments": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "74H7PQ7nSsUf",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "74H7PQ7nSsUf"
+ ],
+ "title": "Done",
+ "notePosition": 20,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "taskDoneRoot",
+ "value": "",
+ "isInheritable": false,
+ "position": 0
+ },
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bx-check-square",
+ "isInheritable": false,
+ "position": 1
+ }
+ ],
+ "format": "html",
+ "attachments": [],
+ "dirFileName": "Done",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "PbOr6Ka8Q1pu",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "74H7PQ7nSsUf",
+ "PbOr6Ka8Q1pu"
+ ],
+ "title": "Buy a board game for Alice",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "task",
+ "value": "",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "relation",
+ "name": "template",
+ "value": "7qiHS46jApK2",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "label",
+ "name": "location",
+ "value": "mall",
+ "isInheritable": false,
+ "position": 30
+ },
+ {
+ "type": "label",
+ "name": "cssClass",
+ "value": "done",
+ "isInheritable": false,
+ "position": 40
+ },
+ {
+ "type": "label",
+ "name": "tag",
+ "value": "christmas",
+ "isInheritable": false,
+ "position": 50
+ },
+ {
+ "type": "label",
+ "name": "tag",
+ "value": "shopping",
+ "isInheritable": false,
+ "position": 60
+ },
+ {
+ "type": "label",
+ "name": "todoDate",
+ "value": "2021-12-20",
+ "isInheritable": false,
+ "position": 70
+ },
+ {
+ "type": "label",
+ "name": "doneDate",
+ "value": "2021-12-24",
+ "isInheritable": false,
+ "position": 80
+ }
+ ],
+ "format": "html",
+ "dataFileName": "Buy a board game for Alice.html",
+ "attachments": [
+ {
+ "attachmentId": "gQqtPMhL3mA0",
+ "title": "codenames.jpg",
+ "role": "image",
+ "mime": "image/jpg",
+ "position": 10,
+ "dataFileName": "Buy a board game for Alice.jpg"
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "oLis5ntGu1GE",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "74H7PQ7nSsUf",
+ "oLis5ntGu1GE"
+ ],
+ "title": "Dentist appointment",
+ "notePosition": 20,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "task",
+ "value": "",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "relation",
+ "name": "template",
+ "value": "7qiHS46jApK2",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "label",
+ "name": "tag",
+ "value": "health",
+ "isInheritable": false,
+ "position": 30
+ },
+ {
+ "type": "label",
+ "name": "cssClass",
+ "value": "done",
+ "isInheritable": false,
+ "position": 40
+ },
+ {
+ "type": "label",
+ "name": "todoDate",
+ "value": "2021-12-19",
+ "isInheritable": false,
+ "position": 50
+ },
+ {
+ "type": "label",
+ "name": "doneDate",
+ "value": "2021-12-19",
+ "isInheritable": false,
+ "position": 60
+ }
+ ],
+ "format": "html",
+ "dataFileName": "Dentist appointment.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "MkD3XMHCTSOr",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "74H7PQ7nSsUf",
+ "MkD3XMHCTSOr"
+ ],
+ "title": "Get a gym membership",
+ "notePosition": 20,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "task",
+ "value": "",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "relation",
+ "name": "template",
+ "value": "7qiHS46jApK2",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "label",
+ "name": "location",
+ "value": "gym",
+ "isInheritable": false,
+ "position": 30
+ },
+ {
+ "type": "label",
+ "name": "cssClass",
+ "value": "done",
+ "isInheritable": false,
+ "position": 40
+ },
+ {
+ "type": "label",
+ "name": "todoDate",
+ "value": "2021-12-28",
+ "isInheritable": false,
+ "position": 50
+ },
+ {
+ "type": "label",
+ "name": "doneDate",
+ "value": "2021-12-30",
+ "isInheritable": false,
+ "position": 60
+ }
+ ],
+ "format": "html",
+ "dataFileName": "Get a gym membership.html",
+ "attachments": []
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "o1sKXDXzZRwS",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "o1sKXDXzZRwS"
+ ],
+ "title": "TODO",
+ "notePosition": 30,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "taskTodoRoot",
+ "value": "",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "label",
+ "name": "child:task",
+ "value": "",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "relation",
+ "name": "child:template",
+ "value": "7qiHS46jApK2",
+ "isInheritable": false,
+ "position": 30
+ },
+ {
+ "type": "label",
+ "name": "child:cssClass",
+ "value": "todo",
+ "isInheritable": false,
+ "position": 40
+ },
+ {
+ "type": "label",
+ "name": "bookmarkFolder",
+ "value": "",
+ "isInheritable": false,
+ "position": 50
+ },
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bxs-plane-take-off",
+ "isInheritable": false,
+ "position": 51
+ }
+ ],
+ "format": "html",
+ "attachments": [],
+ "dirFileName": "TODO",
+ "children": [
+ {
+ "isClone": true,
+ "noteId": "Evz7c4Npu4PO",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "o1sKXDXzZRwS",
+ "Evz7c4Npu4PO"
+ ],
+ "title": "Send invites for christmas party",
+ "prefix": null,
+ "dataFileName": "Send invites for christmas party.clone.html",
+ "type": "text",
+ "format": "html"
+ },
+ {
+ "isClone": true,
+ "noteId": "hu6fwfUGqnZR",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "o1sKXDXzZRwS",
+ "hu6fwfUGqnZR"
+ ],
+ "title": "Buy milk",
+ "prefix": null,
+ "dataFileName": "Buy milk.clone.html",
+ "type": "text",
+ "format": "html"
+ },
+ {
+ "isClone": true,
+ "noteId": "4uh4j70LaKiG",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "o1sKXDXzZRwS",
+ "4uh4j70LaKiG"
+ ],
+ "title": "Buy some book for Bob",
+ "prefix": null,
+ "dataFileName": "Buy some book for Bob.clone.html",
+ "type": "text",
+ "format": "html"
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "8fyQ8ULFg2w5",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "8fyQ8ULFg2w5"
+ ],
+ "title": "Implementation",
+ "notePosition": 40,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bx-code-alt",
+ "isInheritable": false,
+ "position": 1
+ }
+ ],
+ "format": "html",
+ "attachments": [],
+ "dirFileName": "Implementation",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "FvShZ1dQD0WH",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "8fyQ8ULFg2w5",
+ "FvShZ1dQD0WH"
+ ],
+ "title": "attribute changed",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "code",
+ "mime": "application/javascript;env=backend",
+ "attributes": [],
+ "dataFileName": "attribute changed.js",
+ "attachments": [],
+ "dirFileName": "attribute changed",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "g3wKmIEgGR9n",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "8fyQ8ULFg2w5",
+ "FvShZ1dQD0WH",
+ "g3wKmIEgGR9n"
+ ],
+ "title": "reconcileAssignments",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "code",
+ "mime": "application/javascript;env=backend",
+ "attributes": [],
+ "dataFileName": "reconcileAssignments.js",
+ "attachments": []
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "g4vuWDH3pfQB",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "8fyQ8ULFg2w5",
+ "g4vuWDH3pfQB"
+ ],
+ "title": "CSS",
+ "notePosition": 20,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "code",
+ "mime": "text/css",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "appCss",
+ "value": "",
+ "isInheritable": false,
+ "position": 0
+ }
+ ],
+ "dataFileName": "CSS.css",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "7qiHS46jApK2",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "8fyQ8ULFg2w5",
+ "7qiHS46jApK2"
+ ],
+ "title": "task template",
+ "notePosition": 30,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "label:location",
+ "value": "promoted,text,single",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "label",
+ "name": "cssClass",
+ "value": "todo",
+ "isInheritable": false,
+ "position": 30
+ },
+ {
+ "type": "label",
+ "name": "label:tag",
+ "value": "promoted,text,multi",
+ "isInheritable": false,
+ "position": 40
+ },
+ {
+ "type": "label",
+ "name": "label:todoDate",
+ "value": "promoted,date,single",
+ "isInheritable": false,
+ "position": 50
+ },
+ {
+ "type": "label",
+ "name": "label:doneDate",
+ "value": "promoted,date,single",
+ "isInheritable": false,
+ "position": 60
+ },
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bx-task",
+ "isInheritable": false,
+ "position": 70
+ },
+ {
+ "type": "label",
+ "name": "task",
+ "value": "",
+ "isInheritable": false,
+ "position": 80
+ },
+ {
+ "type": "relation",
+ "name": "runOnAttributeChange",
+ "value": "FvShZ1dQD0WH",
+ "isInheritable": false,
+ "position": 10
+ }
+ ],
+ "format": "html",
+ "dataFileName": "task template.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "SI8AwI2KJqip",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "8fyQ8ULFg2w5",
+ "SI8AwI2KJqip"
+ ],
+ "title": "createNewTask",
+ "notePosition": 40,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "code",
+ "mime": "application/javascript;env=frontend",
+ "attributes": [],
+ "dataFileName": "createNewTask.js",
+ "attachments": []
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "ZLW5vUDmnj7c",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "ZLW5vUDmnj7c"
+ ],
+ "title": "Tags",
+ "notePosition": 50,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "taskTagRoot",
+ "value": "",
+ "isInheritable": false,
+ "position": 0
+ },
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bx-purchase-tag",
+ "isInheritable": false,
+ "position": 1
+ }
+ ],
+ "format": "html",
+ "attachments": [],
+ "dirFileName": "Tags",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "L1NgccjlH70Q",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "ZLW5vUDmnj7c",
+ "L1NgccjlH70Q"
+ ],
+ "title": "health",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "taskTagNote",
+ "value": "health",
+ "isInheritable": false,
+ "position": 1
+ }
+ ],
+ "format": "html",
+ "dataFileName": "health.html",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "bRwEJbMouAJh",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "ZLW5vUDmnj7c",
+ "bRwEJbMouAJh"
+ ],
+ "title": "shopping",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "taskTagNote",
+ "value": "shopping",
+ "isInheritable": false,
+ "position": 1
+ }
+ ],
+ "format": "html",
+ "attachments": [],
+ "dirFileName": "shopping",
+ "children": [
+ {
+ "isClone": true,
+ "noteId": "4uh4j70LaKiG",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "ZLW5vUDmnj7c",
+ "bRwEJbMouAJh",
+ "4uh4j70LaKiG"
+ ],
+ "title": "Buy some book for Bob",
+ "prefix": null,
+ "dataFileName": "Buy some book for Bob.clone.html",
+ "type": "text",
+ "format": "html"
+ },
+ {
+ "isClone": true,
+ "noteId": "hu6fwfUGqnZR",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "ZLW5vUDmnj7c",
+ "bRwEJbMouAJh",
+ "hu6fwfUGqnZR"
+ ],
+ "title": "Buy milk",
+ "prefix": null,
+ "dataFileName": "Buy milk.clone.html",
+ "type": "text",
+ "format": "html"
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "wxvh8gxBAFTr",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "ZLW5vUDmnj7c",
+ "wxvh8gxBAFTr"
+ ],
+ "title": "groceries",
+ "notePosition": 20,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "taskTagNote",
+ "value": "groceries",
+ "isInheritable": false,
+ "position": 1
+ }
+ ],
+ "format": "html",
+ "attachments": [],
+ "dirFileName": "groceries",
+ "children": [
+ {
+ "isClone": true,
+ "noteId": "hu6fwfUGqnZR",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "ZLW5vUDmnj7c",
+ "wxvh8gxBAFTr",
+ "hu6fwfUGqnZR"
+ ],
+ "title": "Buy milk",
+ "prefix": null,
+ "dataFileName": "Buy milk.clone.html",
+ "type": "text",
+ "format": "html"
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "H8AbesQ2DsJV",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "ZLW5vUDmnj7c",
+ "H8AbesQ2DsJV"
+ ],
+ "title": "christmas",
+ "notePosition": 30,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "text",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "taskTagNote",
+ "value": "christmas",
+ "isInheritable": false,
+ "position": 1
+ }
+ ],
+ "format": "html",
+ "attachments": [],
+ "dirFileName": "christmas",
+ "children": [
+ {
+ "isClone": true,
+ "noteId": "4uh4j70LaKiG",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "ZLW5vUDmnj7c",
+ "H8AbesQ2DsJV",
+ "4uh4j70LaKiG"
+ ],
+ "title": "Buy some book for Bob",
+ "prefix": null,
+ "dataFileName": "Buy some book for Bob.clone.html",
+ "type": "text",
+ "format": "html"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "qv7UJuErc16Q",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "zQpMt8tYmYPL",
+ "qv7UJuErc16Q"
+ ],
+ "title": "Create Launcher",
+ "notePosition": 60,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "code",
+ "mime": "application/javascript;env=backend",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bx-sidebar",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "relation",
+ "name": "createNewTask",
+ "value": "SI8AwI2KJqip",
+ "isInheritable": false,
+ "position": 20
+ },
+ {
+ "type": "label",
+ "name": "executeButton",
+ "value": "Create Launcher",
+ "isInheritable": false,
+ "position": 30
+ },
+ {
+ "type": "label",
+ "name": "executeDescription",
+ "value": "This script creates a launcher on the left side bar which can be used to quickly create a new task",
+ "isInheritable": false,
+ "position": 40
+ }
+ ],
+ "dataFileName": "Create Launcher.js",
+ "attachments": []
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "uEhizdFWgTIC",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "uEhizdFWgTIC"
+ ],
+ "title": "Word count widget",
+ "notePosition": 20,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "code",
+ "mime": "application/javascript;env=frontend",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "widget",
+ "value": "",
+ "isInheritable": false,
+ "position": 10
+ }
+ ],
+ "dataFileName": "Word count widget.js",
+ "attachments": []
+ },
+ {
+ "isClone": false,
+ "noteId": "IYO5iEWuPCbj",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "IYO5iEWuPCbj"
+ ],
+ "title": "Weight Tracker",
+ "notePosition": 40,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "render",
+ "mime": "text/html",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "hideChildrenOverview",
+ "value": "",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "label",
+ "name": "bookmarked",
+ "value": "",
+ "isInheritable": false,
+ "position": 30
+ },
+ {
+ "type": "label",
+ "name": "iconClass",
+ "value": "bx bx-tachometer",
+ "isInheritable": false,
+ "position": 40
+ },
+ {
+ "type": "relation",
+ "name": "renderNote",
+ "value": "iFlQcEYLIVWB",
+ "isInheritable": false,
+ "position": 20
+ }
+ ],
+ "attachments": [],
+ "dirFileName": "Weight Tracker",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "iFlQcEYLIVWB",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "IYO5iEWuPCbj",
+ "iFlQcEYLIVWB"
+ ],
+ "title": "Implementation",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "code",
+ "mime": "text/html",
+ "attributes": [],
+ "dataFileName": "Implementation.html",
+ "attachments": [],
+ "dirFileName": "Implementation",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "fdpRmy4olJ9D",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "IYO5iEWuPCbj",
+ "iFlQcEYLIVWB",
+ "fdpRmy4olJ9D"
+ ],
+ "title": "JS code",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "code",
+ "mime": "application/javascript;env=frontend",
+ "attributes": [],
+ "dataFileName": "JS code.js",
+ "attachments": [],
+ "dirFileName": "JS code",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "iS5BBNx0i74J",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "IYO5iEWuPCbj",
+ "iFlQcEYLIVWB",
+ "fdpRmy4olJ9D",
+ "iS5BBNx0i74J"
+ ],
+ "title": "chart.js",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "file",
+ "mime": "text/javascript",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "originalFileName",
+ "value": "chart.min.js",
+ "isInheritable": false,
+ "position": 1
+ }
+ ],
+ "dataFileName": "chart.js",
+ "attachments": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "uK5ckLvFPUUX",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "uK5ckLvFPUUX"
+ ],
+ "title": "Statistics",
+ "notePosition": 60,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "book",
+ "mime": "",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "bookZoomLevel",
+ "value": "2",
+ "isInheritable": false,
+ "position": 10
+ }
+ ],
+ "attachments": [],
+ "dirFileName": "Statistics",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "BsUewm6yHngC",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "uK5ckLvFPUUX",
+ "BsUewm6yHngC"
+ ],
+ "title": "Attribute count",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "render",
+ "mime": "",
+ "attributes": [
+ {
+ "type": "relation",
+ "name": "renderNote",
+ "value": "AiKGUNbMJeOi",
+ "isInheritable": false,
+ "position": 10
+ }
+ ],
+ "attachments": [],
+ "dirFileName": "Attribute count",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "AiKGUNbMJeOi",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "uK5ckLvFPUUX",
+ "BsUewm6yHngC",
+ "AiKGUNbMJeOi"
+ ],
+ "title": "template",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "code",
+ "mime": "text/html",
+ "attributes": [],
+ "dataFileName": "template.html",
+ "attachments": [],
+ "dirFileName": "template",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "fYAbi7MctpJ1",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "uK5ckLvFPUUX",
+ "BsUewm6yHngC",
+ "AiKGUNbMJeOi",
+ "fYAbi7MctpJ1"
+ ],
+ "title": "js",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "code",
+ "mime": "application/javascript;env=frontend",
+ "attributes": [],
+ "dataFileName": "js.js",
+ "attachments": [],
+ "dirFileName": "js",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "TsdykeHU5RJ9",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "uK5ckLvFPUUX",
+ "BsUewm6yHngC",
+ "AiKGUNbMJeOi",
+ "fYAbi7MctpJ1",
+ "TsdykeHU5RJ9"
+ ],
+ "title": "renderPieChart",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "code",
+ "mime": "application/javascript;env=frontend",
+ "attributes": [],
+ "dataFileName": "renderPieChart.js",
+ "attachments": [],
+ "dirFileName": "renderPieChart",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "AQV0tCouCZpT",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "uK5ckLvFPUUX",
+ "BsUewm6yHngC",
+ "AiKGUNbMJeOi",
+ "fYAbi7MctpJ1",
+ "TsdykeHU5RJ9",
+ "AQV0tCouCZpT"
+ ],
+ "title": "chartjs-plugin-datalabels.min.js",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "file",
+ "mime": "text/javascript",
+ "attributes": [
+ {
+ "type": "label",
+ "name": "originalFileName",
+ "value": "chartjs-plugin-datalabels.min.js",
+ "isInheritable": false,
+ "position": 1
+ }
+ ],
+ "dataFileName": "chartjs-plugin-datalabe.min.js",
+ "attachments": [],
+ "dirFileName": "chartjs-plugin-datalabels.min.js",
+ "children": [
+ {
+ "isClone": true,
+ "noteId": "iS5BBNx0i74J",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "uK5ckLvFPUUX",
+ "BsUewm6yHngC",
+ "AiKGUNbMJeOi",
+ "fYAbi7MctpJ1",
+ "TsdykeHU5RJ9",
+ "AQV0tCouCZpT",
+ "iS5BBNx0i74J"
+ ],
+ "title": "chart.js",
+ "prefix": null,
+ "dataFileName": "chart.js.clone.html",
+ "type": "text",
+ "format": "html"
+ }
+ ]
+ },
+ {
+ "isClone": true,
+ "noteId": "iS5BBNx0i74J",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "uK5ckLvFPUUX",
+ "BsUewm6yHngC",
+ "AiKGUNbMJeOi",
+ "fYAbi7MctpJ1",
+ "TsdykeHU5RJ9",
+ "iS5BBNx0i74J"
+ ],
+ "title": "chart.js",
+ "prefix": null,
+ "dataFileName": "chart.js.clone.html",
+ "type": "text",
+ "format": "html"
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "hfRME6bdRU2R",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "uK5ckLvFPUUX",
+ "BsUewm6yHngC",
+ "AiKGUNbMJeOi",
+ "fYAbi7MctpJ1",
+ "hfRME6bdRU2R"
+ ],
+ "title": "renderTable",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "code",
+ "mime": "application/javascript;env=frontend",
+ "attributes": [],
+ "dataFileName": "renderTable.js",
+ "attachments": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "H0nm1lyI4jCY",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "uK5ckLvFPUUX",
+ "H0nm1lyI4jCY"
+ ],
+ "title": "Largest notes",
+ "notePosition": 20,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "render",
+ "mime": "",
+ "attributes": [
+ {
+ "type": "relation",
+ "name": "renderNote",
+ "value": "1ZUtxvW1qeyZ",
+ "isInheritable": false,
+ "position": 10
+ }
+ ],
+ "attachments": [],
+ "dirFileName": "Largest notes",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "1ZUtxvW1qeyZ",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "uK5ckLvFPUUX",
+ "H0nm1lyI4jCY",
+ "1ZUtxvW1qeyZ"
+ ],
+ "title": "template",
+ "notePosition": 10,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "code",
+ "mime": "text/html",
+ "attributes": [],
+ "dataFileName": "template.html",
+ "attachments": [],
+ "dirFileName": "template",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "jsM6edxHyM0C",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "uK5ckLvFPUUX",
+ "H0nm1lyI4jCY",
+ "1ZUtxvW1qeyZ",
+ "jsM6edxHyM0C"
+ ],
+ "title": "js",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "code",
+ "mime": "application/javascript;env=frontend",
+ "attributes": [],
+ "dataFileName": "js.js",
+ "attachments": []
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "AJ2eejoELNhk",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "uK5ckLvFPUUX",
+ "AJ2eejoELNhk"
+ ],
+ "title": "Most edited notes",
+ "notePosition": 30,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "render",
+ "mime": "",
+ "attributes": [
+ {
+ "type": "relation",
+ "name": "renderNote",
+ "value": "VNUKOvrPKC76",
+ "isInheritable": false,
+ "position": 10
+ }
+ ],
+ "attachments": [],
+ "dirFileName": "Most edited notes",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "VNUKOvrPKC76",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "uK5ckLvFPUUX",
+ "AJ2eejoELNhk",
+ "VNUKOvrPKC76"
+ ],
+ "title": "template",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "code",
+ "mime": "text/html",
+ "attributes": [],
+ "dataFileName": "template.html",
+ "attachments": [],
+ "dirFileName": "template",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "JJyoW0AUEa3E",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "uK5ckLvFPUUX",
+ "AJ2eejoELNhk",
+ "VNUKOvrPKC76",
+ "JJyoW0AUEa3E"
+ ],
+ "title": "js",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "code",
+ "mime": "application/javascript;env=frontend",
+ "attributes": [],
+ "dataFileName": "js.js",
+ "attachments": []
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "7W53TQFpBujr",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "uK5ckLvFPUUX",
+ "7W53TQFpBujr"
+ ],
+ "title": "Most linked notes",
+ "notePosition": 40,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "render",
+ "mime": "",
+ "attributes": [
+ {
+ "type": "relation",
+ "name": "renderNote",
+ "value": "1zt0MOCyJEVI",
+ "isInheritable": false,
+ "position": 10
+ }
+ ],
+ "attachments": [],
+ "dirFileName": "Most linked notes",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "1zt0MOCyJEVI",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "uK5ckLvFPUUX",
+ "7W53TQFpBujr",
+ "1zt0MOCyJEVI"
+ ],
+ "title": "template",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "code",
+ "mime": "text/html",
+ "attributes": [],
+ "dataFileName": "template.html",
+ "attachments": [],
+ "dirFileName": "template",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "76s2u6NeK7IE",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "uK5ckLvFPUUX",
+ "7W53TQFpBujr",
+ "1zt0MOCyJEVI",
+ "76s2u6NeK7IE"
+ ],
+ "title": "js",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "code",
+ "mime": "application/javascript;env=frontend",
+ "attributes": [],
+ "dataFileName": "js.js",
+ "attachments": []
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "5xtL10PYc4bf",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "uK5ckLvFPUUX",
+ "5xtL10PYc4bf"
+ ],
+ "title": "Note type count",
+ "notePosition": 50,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "render",
+ "mime": "",
+ "attributes": [
+ {
+ "type": "relation",
+ "name": "renderNote",
+ "value": "fmbJsCyc7oOc",
+ "isInheritable": false,
+ "position": 10
+ }
+ ],
+ "attachments": [],
+ "dirFileName": "Note type count",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "fmbJsCyc7oOc",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "uK5ckLvFPUUX",
+ "5xtL10PYc4bf",
+ "fmbJsCyc7oOc"
+ ],
+ "title": "template",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "code",
+ "mime": "text/html",
+ "attributes": [],
+ "dataFileName": "template.html",
+ "attachments": [],
+ "dirFileName": "template",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "fqsDkKujJc3w",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "uK5ckLvFPUUX",
+ "5xtL10PYc4bf",
+ "fmbJsCyc7oOc",
+ "fqsDkKujJc3w"
+ ],
+ "title": "js",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "code",
+ "mime": "application/javascript;env=frontend",
+ "attributes": [],
+ "dataFileName": "js.js",
+ "attachments": [],
+ "dirFileName": "js",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "iStjuccma54t",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "uK5ckLvFPUUX",
+ "5xtL10PYc4bf",
+ "fmbJsCyc7oOc",
+ "fqsDkKujJc3w",
+ "iStjuccma54t"
+ ],
+ "title": "renderTable",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "code",
+ "mime": "application/javascript;env=frontend",
+ "attributes": [],
+ "dataFileName": "renderTable.js",
+ "attachments": []
+ },
+ {
+ "isClone": true,
+ "noteId": "TsdykeHU5RJ9",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "uK5ckLvFPUUX",
+ "5xtL10PYc4bf",
+ "fmbJsCyc7oOc",
+ "fqsDkKujJc3w",
+ "TsdykeHU5RJ9"
+ ],
+ "title": "renderPieChart",
+ "prefix": null,
+ "dataFileName": "renderPieChart.clone.html",
+ "type": "text",
+ "format": "html"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "JkMXQ0r5bRnI",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "uK5ckLvFPUUX",
+ "JkMXQ0r5bRnI"
+ ],
+ "title": "Most cloned notes",
+ "notePosition": 60,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "render",
+ "mime": "",
+ "attributes": [
+ {
+ "type": "relation",
+ "name": "renderNote",
+ "value": "VeQJSgKIkaUQ",
+ "isInheritable": false,
+ "position": 10
+ }
+ ],
+ "attachments": [],
+ "dirFileName": "Most cloned notes",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "VeQJSgKIkaUQ",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "uK5ckLvFPUUX",
+ "JkMXQ0r5bRnI",
+ "VeQJSgKIkaUQ"
+ ],
+ "title": "template",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "code",
+ "mime": "text/html",
+ "attributes": [],
+ "dataFileName": "template.html",
+ "attachments": [],
+ "dirFileName": "template",
+ "children": [
+ {
+ "isClone": false,
+ "noteId": "NI8zZ7IznTZT",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "uK5ckLvFPUUX",
+ "JkMXQ0r5bRnI",
+ "VeQJSgKIkaUQ",
+ "NI8zZ7IznTZT"
+ ],
+ "title": "js",
+ "notePosition": 0,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "code",
+ "mime": "application/javascript;env=frontend",
+ "attributes": [],
+ "dataFileName": "js.js",
+ "attachments": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "isClone": false,
+ "noteId": "IPifAXM3cyRS",
+ "notePath": [
+ "root",
+ "Fb7eMY46lT6k",
+ "G8k9CPUVtDeE",
+ "IPifAXM3cyRS"
+ ],
+ "title": "Custom request handler",
+ "notePosition": 90,
+ "prefix": null,
+ "isExpanded": false,
+ "type": "code",
+ "mime": "application/javascript;env=backend",
+ "attributes": [
+ {
+ "type": "relation",
+ "name": "targetNote",
+ "value": "B08ZaJdYTK5v",
+ "isInheritable": false,
+ "position": 10
+ },
+ {
+ "type": "label",
+ "name": "customRequestHandler",
+ "value": "create-note",
+ "isInheritable": false,
+ "position": 20
+ }
+ ],
+ "dataFileName": "Custom request handler.js",
+ "attachments": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "noImport": true,
+ "dataFileName": "navigation.html"
+ },
+ {
+ "noImport": true,
+ "dataFileName": "index.html"
+ },
+ {
+ "noImport": true,
+ "dataFileName": "style.css"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/public/app/doc_notes/en/User Guide/index.html b/demo/index.html
similarity index 81%
rename from src/public/app/doc_notes/en/User Guide/index.html
rename to demo/index.html
index c5c17da96..638b4e3bf 100644
--- a/src/public/app/doc_notes/en/User Guide/index.html
+++ b/demo/index.html
@@ -6,6 +6,6 @@