mirror of
https://github.com/zadam/trilium.git
synced 2025-12-19 22:59:53 +01:00
Compare commits
2 Commits
stable
...
v0.91.3-be
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5dc546605b | ||
|
|
62cda1bd24 |
10
.dockerignore
Normal file
10
.dockerignore
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
.git
|
||||||
|
.idea
|
||||||
|
/bin
|
||||||
|
/dist
|
||||||
|
/docs
|
||||||
|
/npm-debug.log
|
||||||
|
node_modules
|
||||||
|
|
||||||
|
src/**/*.ts
|
||||||
|
!src/services/asset_path.ts
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
root = true
|
root = true
|
||||||
|
|
||||||
[*.{js,ts,tsx}]
|
[*.{js,ts}]
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
end_of_line = lf
|
end_of_line = lf
|
||||||
indent_size = 4
|
indent_size = 4
|
||||||
@@ -8,9 +8,6 @@ indent_style = space
|
|||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
[*.sh]
|
|
||||||
end_of_line = lf
|
|
||||||
|
|
||||||
[{server,translation}.json]
|
[{server,translation}.json]
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
end_of_line = lf
|
end_of_line = lf
|
||||||
@@ -18,9 +15,3 @@ indent_size = 2
|
|||||||
indent_style = space
|
indent_style = space
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
[*.yml]
|
|
||||||
indent_size = 2
|
|
||||||
indent_style = space
|
|
||||||
insert_final_newline = true
|
|
||||||
trim_trailing_whitespace = true
|
|
||||||
19
.gitattributes
vendored
19
.gitattributes
vendored
@@ -1,21 +1,2 @@
|
|||||||
# Mark files as auto-generated to simplify reviews.
|
|
||||||
package-lock.json linguist-generated=true
|
package-lock.json linguist-generated=true
|
||||||
**/package-lock.json linguist-generated=true
|
**/package-lock.json linguist-generated=true
|
||||||
apps/server/src/assets/doc_notes/en/User[[:space:]]Guide/** linguist-generated
|
|
||||||
|
|
||||||
# Ignore from GitHub language stats.
|
|
||||||
apps/server/src/assets/doc_notes/en/User[[:space:]]Guide/**/*.html eol=lf
|
|
||||||
apps/server/src/assets/doc_notes/** linguist-vendored=true
|
|
||||||
apps/edit-docs/demo/** linguist-vendored=true
|
|
||||||
docs/** linguist-vendored=true
|
|
||||||
|
|
||||||
# Normalize line endings.
|
|
||||||
docs/**/*.md eol=lf
|
|
||||||
docs/**/*.json 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
|
|
||||||
*.sh eol=lf
|
|
||||||
|
|||||||
6
.github/FUNDING.yml
vendored
6
.github/FUNDING.yml
vendored
@@ -1,6 +1,4 @@
|
|||||||
# These are supported funding model platforms
|
# These are supported funding model platforms
|
||||||
|
|
||||||
github: [eliandoran]
|
github: [zadam]
|
||||||
custom: ["https://paypal.me/eliandoran"]
|
custom: ["https://paypal.me/za4am"]
|
||||||
liberapay: ElianDoran
|
|
||||||
buy_me_a_coffee: eliandoran
|
|
||||||
|
|||||||
3
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
3
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -1,6 +1,7 @@
|
|||||||
name: Bug Report
|
name: Bug Report
|
||||||
description: Report a bug
|
description: Report a bug
|
||||||
type: "Bug"
|
title: "(Bug report) "
|
||||||
|
labels: "Type: Bug"
|
||||||
body:
|
body:
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
|
|||||||
5
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
5
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
@@ -1,11 +1,12 @@
|
|||||||
name: Feature Request
|
name: Feature Request
|
||||||
description: Ask for a new feature to be added
|
description: Ask for a new feature to be added
|
||||||
type: "Feature"
|
title: "(Feature request) "
|
||||||
|
labels: "Type: Enhancement"
|
||||||
body:
|
body:
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: Describe feature
|
label: Describe feature
|
||||||
description: A clear and concise description of what you want to be added.
|
description: A clear and concise description of what you want to be added..
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
|
|||||||
10
.github/ISSUE_TEMPLATE/task.yml
vendored
10
.github/ISSUE_TEMPLATE/task.yml
vendored
@@ -1,10 +0,0 @@
|
|||||||
name: Task
|
|
||||||
description: Create a new Task
|
|
||||||
type: "Task"
|
|
||||||
body:
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Describe Task
|
|
||||||
description: A clear and concise description of what the task is about.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
187
.github/actions/build-electron/action.yml
vendored
187
.github/actions/build-electron/action.yml
vendored
@@ -1,187 +0,0 @@
|
|||||||
name: "Build Electron App"
|
|
||||||
description: "Builds and packages the Electron app for different platforms"
|
|
||||||
|
|
||||||
inputs:
|
|
||||||
os:
|
|
||||||
description: "One of the supported platforms: macos, linux, windows"
|
|
||||||
required: true
|
|
||||||
arch:
|
|
||||||
description: "The architecture to build for: x64, arm64"
|
|
||||||
required: true
|
|
||||||
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@v5
|
|
||||||
with:
|
|
||||||
p12-file-base64: ${{ env.APPLE_APP_CERTIFICATE_BASE64 }}
|
|
||||||
p12-password: ${{ env.APPLE_APP_CERTIFICATE_PASSWORD }}
|
|
||||||
keychain: build-app-${{ github.run_id }}
|
|
||||||
keychain-password: ${{ github.run_id }}
|
|
||||||
|
|
||||||
- name: Install Installer certificate
|
|
||||||
if: inputs.os == 'macos'
|
|
||||||
uses: apple-actions/import-codesign-certs@v5
|
|
||||||
with:
|
|
||||||
p12-file-base64: ${{ env.APPLE_INSTALLER_CERTIFICATE_BASE64 }}
|
|
||||||
p12-password: ${{ env.APPLE_INSTALLER_CERTIFICATE_PASSWORD }}
|
|
||||||
keychain: build-installer-${{ github.run_id }}
|
|
||||||
keychain-password: ${{ github.run_id }}
|
|
||||||
|
|
||||||
- name: Verify certificates
|
|
||||||
if: inputs.os == 'macos'
|
|
||||||
shell: ${{ inputs.shell }}
|
|
||||||
run: |
|
|
||||||
echo "Available signing identities in app keychain:"
|
|
||||||
security find-identity -v -p codesigning build-app-${{ github.run_id }}.keychain
|
|
||||||
|
|
||||||
echo "Available signing identities in installer keychain:"
|
|
||||||
security find-identity -v -p codesigning build-installer-${{ github.run_id }}.keychain
|
|
||||||
|
|
||||||
# Make the keychains searchable
|
|
||||||
security list-keychains -d user -s build-app-${{ github.run_id }}.keychain build-installer-${{ github.run_id }}.keychain $(security list-keychains -d user | tr -d '"')
|
|
||||||
security default-keychain -s build-app-${{ github.run_id }}.keychain
|
|
||||||
security unlock-keychain -p ${{ github.run_id }} build-app-${{ github.run_id }}.keychain
|
|
||||||
security unlock-keychain -p ${{ github.run_id }} build-installer-${{ github.run_id }}.keychain
|
|
||||||
security set-keychain-settings -t 3600 -l build-app-${{ github.run_id }}.keychain
|
|
||||||
security set-keychain-settings -t 3600 -l build-installer-${{ github.run_id }}.keychain
|
|
||||||
|
|
||||||
- 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: ${{ 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
|
|
||||||
|
|
||||||
- name: Update build info
|
|
||||||
shell: ${{ inputs.shell }}
|
|
||||||
run: pnpm run chore:update-build-info
|
|
||||||
|
|
||||||
# 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: TriliumNotes-${{ github.ref_name }}-${{ inputs.os }}-${{ inputs.arch }}
|
|
||||||
TARGET_ARCH: ${{ inputs.arch }}
|
|
||||||
run: pnpm run --filter desktop electron-forge:make --arch=${{ inputs.arch }} --platform=${{ inputs.forge_platform }}
|
|
||||||
|
|
||||||
# Add DMG signing step
|
|
||||||
- name: Sign DMG
|
|
||||||
if: inputs.os == 'macos'
|
|
||||||
shell: ${{ inputs.shell }}
|
|
||||||
run: |
|
|
||||||
echo "Signing DMG file..."
|
|
||||||
dmg_file=$(find ./apps/desktop/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-app-${{ github.run_id }}.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
|
|
||||||
|
|
||||||
- name: Verify code signing
|
|
||||||
if: inputs.os == 'macos'
|
|
||||||
shell: ${{ inputs.shell }}
|
|
||||||
run: |
|
|
||||||
echo "Verifying code signing for all artifacts..."
|
|
||||||
|
|
||||||
# First check the .app bundle
|
|
||||||
echo "Looking for .app bundle..."
|
|
||||||
app_bundle=$(find ./apps/desktop/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"
|
|
||||||
|
|
||||||
echo "Checking entitlements..."
|
|
||||||
codesign --display --entitlements :- "$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
|
|
||||||
|
|
||||||
# Then check DMG if it exists
|
|
||||||
echo "Looking for DMG..."
|
|
||||||
dmg_file=$(find ./apps/desktop/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 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 ./apps/desktop/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
|
|
||||||
|
|
||||||
- name: Sign the RPM
|
|
||||||
if: inputs.os == 'linux'
|
|
||||||
shell: ${{ inputs.shell }}
|
|
||||||
run: |
|
|
||||||
echo -n "$GPG_SIGNING_KEY" | base64 --decode | gpg --import
|
|
||||||
|
|
||||||
# Import the key into RPM for verification
|
|
||||||
gpg --export -a > pubkey
|
|
||||||
rpm --import pubkey
|
|
||||||
rm pubkey
|
|
||||||
|
|
||||||
# Sign the RPM
|
|
||||||
rpm_file=$(find ./apps/desktop/upload -name "*.rpm" -print -quit)
|
|
||||||
rpmsign --define "_gpg_name Trilium Notes Signing Key <triliumnotes@outlook.com>" --addsign "$rpm_file"
|
|
||||||
rpm -Kv "$rpm_file"
|
|
||||||
|
|
||||||
# Validate code signing
|
|
||||||
if ! rpm -K "$rpm_file" | grep -q "digests signatures OK"; then
|
|
||||||
echo .rpm file not signed
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
33
.github/actions/build-server/action.yml
vendored
33
.github/actions/build-server/action.yml
vendored
@@ -1,33 +0,0 @@
|
|||||||
inputs:
|
|
||||||
os:
|
|
||||||
description: "One of the supported platforms: windows"
|
|
||||||
required: true
|
|
||||||
arch:
|
|
||||||
description: "The architecture to build for: x64, arm64"
|
|
||||||
required: true
|
|
||||||
runs:
|
|
||||||
using: composite
|
|
||||||
steps:
|
|
||||||
- uses: pnpm/action-setup@v4
|
|
||||||
- name: Set up node & dependencies
|
|
||||||
uses: actions/setup-node@v6
|
|
||||||
with:
|
|
||||||
node-version: 24
|
|
||||||
cache: "pnpm"
|
|
||||||
- name: Install dependencies
|
|
||||||
shell: bash
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Run Linux server build
|
|
||||||
env:
|
|
||||||
MATRIX_ARCH: ${{ inputs.arch }}
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
pnpm run chore:update-build-info
|
|
||||||
pnpm run --filter server package
|
|
||||||
- name: Prepare artifacts
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
mkdir -p upload
|
|
||||||
file=$(find ./apps/server/out -name '*.tar.xz' -print -quit)
|
|
||||||
name=${{ github.ref_name }}
|
|
||||||
cp "$file" "upload/TriliumNotes-Server-${name//\//-}-${{ inputs.os }}-${{ inputs.arch }}.tar.xz"
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
name: "Deploy to Cloudflare Pages"
|
|
||||||
description: "Deploys to Cloudflare Pages on either a temporary branch with preview comment, or on the production version if on the main branch."
|
|
||||||
inputs:
|
|
||||||
project_name:
|
|
||||||
description: "CloudFlare Pages project name"
|
|
||||||
comment_body:
|
|
||||||
description: "The message to display when deployment is ready"
|
|
||||||
default: "Deployment is ready."
|
|
||||||
required: false
|
|
||||||
production_url:
|
|
||||||
description: "The URL to mention as the production URL."
|
|
||||||
required: true
|
|
||||||
deploy_dir:
|
|
||||||
description: "The directory from which to deploy."
|
|
||||||
required: true
|
|
||||||
cloudflare_api_token:
|
|
||||||
description: "The Cloudflare API token to use for deployment."
|
|
||||||
required: true
|
|
||||||
cloudflare_account_id:
|
|
||||||
description: "The Cloudflare account ID to use for deployment."
|
|
||||||
required: true
|
|
||||||
github_token:
|
|
||||||
description: "The GitHub token to use for posting PR comments."
|
|
||||||
required: true
|
|
||||||
runs:
|
|
||||||
using: composite
|
|
||||||
steps:
|
|
||||||
# Install wrangler globally to avoid workspace issues
|
|
||||||
- name: Install Wrangler
|
|
||||||
shell: bash
|
|
||||||
run: npm install -g wrangler
|
|
||||||
|
|
||||||
# Deploy using Wrangler (use pre-installed wrangler)
|
|
||||||
- name: Deploy to Cloudflare Pages
|
|
||||||
id: deploy
|
|
||||||
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
|
|
||||||
uses: cloudflare/wrangler-action@v3
|
|
||||||
with:
|
|
||||||
apiToken: ${{ inputs.cloudflare_api_token }}
|
|
||||||
accountId: ${{ inputs.cloudflare_account_id }}
|
|
||||||
command: pages deploy ${{ inputs.deploy_dir }} --project-name=${{ inputs.project_name}} --branch=${{ github.ref_name }}
|
|
||||||
wranglerVersion: '' # Use pre-installed version
|
|
||||||
|
|
||||||
# Deploy preview for PRs
|
|
||||||
- name: Deploy Preview to Cloudflare Pages
|
|
||||||
id: preview-deployment
|
|
||||||
if: github.event_name == 'pull_request'
|
|
||||||
uses: cloudflare/wrangler-action@v3
|
|
||||||
with:
|
|
||||||
apiToken: ${{ inputs.cloudflare_api_token }}
|
|
||||||
accountId: ${{ inputs.cloudflare_account_id }}
|
|
||||||
command: pages deploy ${{ inputs.deploy_dir }} --project-name=${{ inputs.project_name}} --branch=pr-${{ github.event.pull_request.number }}
|
|
||||||
wranglerVersion: '' # Use pre-installed version
|
|
||||||
|
|
||||||
# Post deployment URL as PR comment
|
|
||||||
- name: Comment PR with Preview URL
|
|
||||||
if: github.event_name == 'pull_request'
|
|
||||||
uses: actions/github-script@v8
|
|
||||||
env:
|
|
||||||
COMMENT_BODY: ${{ inputs.comment_body }}
|
|
||||||
PRODUCTION_URL: ${{ inputs.production_url }}
|
|
||||||
PROJECT_NAME: ${{ inputs.project_name }}
|
|
||||||
with:
|
|
||||||
github-token: ${{ inputs.github_token }}
|
|
||||||
script: |
|
|
||||||
const prNumber = context.issue.number;
|
|
||||||
// Construct preview URL based on Cloudflare Pages pattern
|
|
||||||
const projectName = process.env.PROJECT_NAME;
|
|
||||||
const previewUrl = `https://pr-${prNumber}.${projectName}.pages.dev`;
|
|
||||||
|
|
||||||
// Check if we already commented
|
|
||||||
const comments = await github.rest.issues.listComments({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
issue_number: prNumber
|
|
||||||
});
|
|
||||||
|
|
||||||
const customMessage = process.env.COMMENT_BODY;
|
|
||||||
const botComment = comments.data.find(comment =>
|
|
||||||
comment.user.type === 'Bot' &&
|
|
||||||
comment.body.includes(customMessage)
|
|
||||||
);
|
|
||||||
|
|
||||||
const mainUrl = process.env.PRODUCTION_URL;
|
|
||||||
const commentBody = `${customMessage}!\n\n🔗 Preview URL: ${previewUrl}\n📖 Production URL: ${mainUrl}\n\n✅ All checks passed\n\n_This preview will be updated automatically with new commits._`;
|
|
||||||
|
|
||||||
if (botComment) {
|
|
||||||
// Update existing comment
|
|
||||||
await github.rest.issues.updateComment({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
comment_id: botComment.id,
|
|
||||||
body: commentBody
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Create new comment
|
|
||||||
await github.rest.issues.createComment({
|
|
||||||
issue_number: prNumber,
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
body: commentBody
|
|
||||||
});
|
|
||||||
}
|
|
||||||
79
.github/actions/report-size/action.yml
vendored
79
.github/actions/report-size/action.yml
vendored
@@ -1,79 +0,0 @@
|
|||||||
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@v6
|
|
||||||
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 }}
|
|
||||||
334
.github/copilot-instructions.md
vendored
334
.github/copilot-instructions.md
vendored
@@ -1,334 +0,0 @@
|
|||||||
# Trilium Notes - AI Coding Agent Instructions
|
|
||||||
|
|
||||||
## Project Overview
|
|
||||||
|
|
||||||
Trilium Notes is a hierarchical note-taking application with advanced features like synchronization, scripting, and rich text editing. Built as a TypeScript monorepo using pnpm, it implements a three-layer caching architecture (Becca/Froca/Shaca) with a widget-based UI system and supports extensive user scripting capabilities.
|
|
||||||
|
|
||||||
## Essential Architecture Patterns
|
|
||||||
|
|
||||||
### Three-Layer Cache System (Critical to Understand)
|
|
||||||
- **Becca** (`apps/server/src/becca/`): Server-side entity cache, primary data source
|
|
||||||
- **Froca** (`apps/client/src/services/froca.ts`): Client-side mirror synchronized via WebSocket
|
|
||||||
- **Shaca** (`apps/server/src/share/`): Optimized cache for public/shared notes
|
|
||||||
|
|
||||||
**Key insight**: Never bypass these caches with direct DB queries. Always use `becca.notes[noteId]`, `froca.getNote()`, or equivalent cache methods.
|
|
||||||
|
|
||||||
### Entity Relationship Model
|
|
||||||
Notes use a **multi-parent tree** via branches:
|
|
||||||
- `BNote` - The note content and metadata
|
|
||||||
- `BBranch` - Tree relationships (one note can have multiple parents via cloning)
|
|
||||||
- `BAttribute` - Key-value metadata attached to notes (labels and relations)
|
|
||||||
|
|
||||||
### Entity Change System & Sync
|
|
||||||
Every entity modification (notes, branches, attributes) creates an `EntityChange` record that drives synchronization:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// Entity changes are automatically tracked
|
|
||||||
note.title = "New Title";
|
|
||||||
note.save(); // Creates EntityChange record with changeId
|
|
||||||
|
|
||||||
// Sync protocol via WebSocket
|
|
||||||
ws.sendMessage({ type: 'sync-pull-in-progress', ... });
|
|
||||||
```
|
|
||||||
|
|
||||||
**Critical**: This is why you must use Becca/Froca methods instead of direct DB writes - they create the change tracking records needed for sync.
|
|
||||||
|
|
||||||
### Entity Lifecycle & Events
|
|
||||||
The event system (`apps/server/src/services/events.ts`) broadcasts entity lifecycle events:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// Subscribe to events in widgets or services
|
|
||||||
eventService.subscribe('noteChanged', ({ noteId }) => {
|
|
||||||
// React to note changes
|
|
||||||
});
|
|
||||||
|
|
||||||
// Common events: noteChanged, branchChanged, attributeChanged, noteDeleted
|
|
||||||
// Widget method: entitiesReloadedEvent({loadResults}) for handling reloads
|
|
||||||
```
|
|
||||||
|
|
||||||
**Becca loader priorities**: Events are emitted in order (notes → branches → attributes) during initial load to ensure referential integrity.
|
|
||||||
|
|
||||||
### TaskContext for Long Operations
|
|
||||||
Use `TaskContext` for operations with progress reporting (imports, exports, bulk operations):
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
const taskContext = new TaskContext("task-id", "import", "Import Notes");
|
|
||||||
taskContext.increaseProgressCount();
|
|
||||||
|
|
||||||
// WebSocket messages: { type: 'taskProgressCount', taskId, taskType, data, progressCount }
|
|
||||||
|
|
||||||
**Pattern**: All long-running operations (delete note trees, export, import) use TaskContext to send WebSocket updates to the frontend.
|
|
||||||
|
|
||||||
### Protected Session Handling
|
|
||||||
Protected notes require an active encryption session:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// Always check before accessing protected content
|
|
||||||
if (note.isContentAvailable()) {
|
|
||||||
const content = note.getContent(); // Safe
|
|
||||||
} else {
|
|
||||||
const title = note.getTitleOrProtected(); // Returns "[protected]"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Protected session management
|
|
||||||
protectedSessionService.isProtectedSessionAvailable() // Check session
|
|
||||||
protectedSessionService.startProtectedSession() // After password entry
|
|
||||||
```
|
|
||||||
|
|
||||||
**Session timeout**: Protected sessions expire after inactivity. The encryption key is kept in memory only.
|
|
||||||
|
|
||||||
### Attribute Inheritance Patterns
|
|
||||||
Attributes can be inherited through three mechanisms:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// 1. Standard inheritance (#hidePromotedAttributes ~hidePromotedAttributes)
|
|
||||||
note.getInheritableAttributes() // Walks up parent tree
|
|
||||||
|
|
||||||
// 2. Child prefix inheritance (child:label copies to children)
|
|
||||||
parentNote.setLabel("child:icon", "book") // All children inherit this
|
|
||||||
|
|
||||||
// 3. Template relation inheritance (#template=templateNoteId)
|
|
||||||
note.setRelation("template", templateNoteId)
|
|
||||||
note.getInheritedAttributes() // Includes template's inheritable attributes
|
|
||||||
```
|
|
||||||
|
|
||||||
**Cycle prevention**: Inheritance tracking prevents infinite loops when notes reference each other.
|
|
||||||
|
|
||||||
### Widget-Based UI Architecture
|
|
||||||
All UI components extend from widget base classes (`apps/client/src/widgets/`):
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// Right panel widget (sidebar)
|
|
||||||
class MyWidget extends RightPanelWidget {
|
|
||||||
get position() { return 100; } // Order in panel
|
|
||||||
get parentWidget() { return 'right-pane'; }
|
|
||||||
isEnabled() { return this.note && this.note.hasLabel('myLabel'); }
|
|
||||||
async refreshWithNote(note) { /* Update UI */ }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note-aware widget (responds to note changes)
|
|
||||||
class MyNoteWidget extends NoteContextAwareWidget {
|
|
||||||
async refreshWithNote(note) { /* Refresh when note changes */ }
|
|
||||||
async entitiesReloadedEvent({loadResults}) { /* Handle entity updates */ }
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Important**: Widgets use jQuery (`this.$widget`) for DOM manipulation. Don't mix React patterns here.
|
|
||||||
|
|
||||||
## Development Workflow
|
|
||||||
|
|
||||||
### Running & Testing
|
|
||||||
```bash
|
|
||||||
# From root directory
|
|
||||||
pnpm install # Install dependencies
|
|
||||||
corepack enable # Enable pnpm if not available
|
|
||||||
pnpm server:start # Dev server (http://localhost:8080)
|
|
||||||
pnpm server:start-prod # Production mode server
|
|
||||||
pnpm desktop:start # Desktop app development
|
|
||||||
pnpm server:test spec/etapi/search.spec.ts # Run specific test
|
|
||||||
pnpm test:parallel # Client tests (can run parallel)
|
|
||||||
pnpm test:sequential # Server tests (sequential due to shared DB)
|
|
||||||
pnpm test:all # All tests (parallel + sequential)
|
|
||||||
pnpm coverage # Generate coverage reports
|
|
||||||
pnpm typecheck # Type check all projects
|
|
||||||
```
|
|
||||||
|
|
||||||
### Building
|
|
||||||
```bash
|
|
||||||
pnpm client:build # Build client application
|
|
||||||
pnpm server:build # Build server application
|
|
||||||
pnpm desktop:build # Build desktop application
|
|
||||||
```
|
|
||||||
|
|
||||||
### Test Organization
|
|
||||||
- **Server tests** (`apps/server/spec/`): Must run sequentially (shared database state)
|
|
||||||
- **Client tests** (`apps/client/src/`): Can run in parallel
|
|
||||||
- **E2E tests** (`apps/server-e2e/`): Use Playwright for integration testing
|
|
||||||
- **ETAPI tests** (`apps/server/spec/etapi/`): External API contract tests
|
|
||||||
|
|
||||||
**Pattern**: When adding new API endpoints, add tests in `spec/etapi/` following existing patterns (see `search.spec.ts`).
|
|
||||||
|
|
||||||
### Monorepo Navigation
|
|
||||||
```
|
|
||||||
apps/
|
|
||||||
client/ # Frontend (shared by server & desktop)
|
|
||||||
server/ # Node.js backend with REST API
|
|
||||||
desktop/ # Electron wrapper
|
|
||||||
web-clipper/ # Browser extension for saving web content
|
|
||||||
db-compare/ # Database comparison tool
|
|
||||||
dump-db/ # Database export utility
|
|
||||||
edit-docs/ # Documentation editing tools
|
|
||||||
packages/
|
|
||||||
commons/ # Shared types and utilities
|
|
||||||
ckeditor5/ # Custom rich text editor with Trilium-specific plugins
|
|
||||||
codemirror/ # Code editor integration
|
|
||||||
highlightjs/ # Syntax highlighting
|
|
||||||
share-theme/ # Theme for shared/published notes
|
|
||||||
ckeditor5-admonition/ # Admonition blocks plugin
|
|
||||||
ckeditor5-footnotes/ # Footnotes plugin
|
|
||||||
ckeditor5-math/ # Math equations plugin
|
|
||||||
ckeditor5-mermaid/ # Mermaid diagrams plugin
|
|
||||||
```
|
|
||||||
|
|
||||||
**Filter commands**: Use `pnpm --filter server test` to run commands in specific packages.
|
|
||||||
|
|
||||||
## Critical Code Patterns
|
|
||||||
|
|
||||||
### ETAPI Backwards Compatibility
|
|
||||||
When adding query parameters to ETAPI endpoints (`apps/server/src/etapi/`), maintain backwards compatibility by checking if new params exist before changing response format.
|
|
||||||
|
|
||||||
**Pattern**: ETAPI consumers expect specific response shapes. Always check for breaking changes.
|
|
||||||
|
|
||||||
### Frontend-Backend Communication
|
|
||||||
- **REST API**: `apps/server/src/routes/api/` - Internal endpoints (no auth required when `noAuthentication=true`)
|
|
||||||
- **ETAPI**: `apps/server/src/etapi/` - External API with authentication
|
|
||||||
- **WebSocket**: Real-time sync via `apps/server/src/services/ws.ts`
|
|
||||||
|
|
||||||
**Auth note**: ETAPI uses basic auth with tokens. Internal API endpoints trust the frontend.
|
|
||||||
|
|
||||||
### Database Migrations
|
|
||||||
- Add scripts in `apps/server/src/migrations/YYMMDD_HHMM__description.sql`
|
|
||||||
- Update schema in `apps/server/src/assets/db/schema.sql`
|
|
||||||
- Never bypass Becca cache after migrations
|
|
||||||
|
|
||||||
## Common Pitfalls
|
|
||||||
|
|
||||||
1. **Never bypass the cache layers** - Always use `becca.notes[noteId]`, `froca.getNote()`, or equivalent cache methods. Direct database queries will cause sync issues between Becca/Froca/Shaca and won't create EntityChange records needed for synchronization.
|
|
||||||
|
|
||||||
2. **Protected notes require session check** - Before accessing `note.title` or `note.getContent()` on protected notes, check `note.isContentAvailable()` or use `note.getTitleOrProtected()` which handles this automatically.
|
|
||||||
|
|
||||||
3. **Widget lifecycle matters** - Override `refreshWithNote()` for note changes, `doRenderBody()` for initial render, `entitiesReloadedEvent()` for entity updates. Widgets use jQuery (`this.$widget`) - don't mix React patterns.
|
|
||||||
|
|
||||||
4. **Tests run differently** - Server tests must run sequentially (shared database state), client tests can run in parallel. Use `pnpm test:sequential` for backend, `pnpm test:parallel` for frontend.
|
|
||||||
|
|
||||||
5. **ETAPI requires authentication** - ETAPI endpoints use basic auth with tokens. Internal API endpoints (`apps/server/src/routes/api/`) trust the frontend when `noAuthentication=true`.
|
|
||||||
|
|
||||||
6. **Search expressions are evaluated in memory** - The search service loads all matching notes, scores them in JavaScript, then sorts. You cannot add SQL-level LIMIT/OFFSET without losing scoring functionality.
|
|
||||||
|
|
||||||
7. **Documentation edits have rules** - `docs/Script API/` is auto-generated (never edit directly). `docs/User Guide/` should be edited via `pnpm edit-docs:edit-docs`, not manually. Only `docs/Developer Guide/` and `docs/Release Notes/` are safe for direct Markdown editing.
|
|
||||||
|
|
||||||
8. **pnpm workspace filtering** - Use `pnpm --filter server <command>` or shorthand `pnpm server:test` defined in root `package.json`. Note the `--filter` syntax, not `-F` or other shortcuts.
|
|
||||||
|
|
||||||
9. **Event subscription cleanup** - When subscribing to events in widgets, unsubscribe in `cleanup()` or `doDestroy()` to prevent memory leaks.
|
|
||||||
|
|
||||||
10. **Attribute inheritance can be complex** - When checking for labels/relations, use `note.getOwnedAttribute()` for direct attributes or `note.getAttribute()` for inherited ones. Don't assume attributes are directly on the note.
|
|
||||||
|
|
||||||
## TypeScript Configuration
|
|
||||||
|
|
||||||
- **Project references**: Monorepo uses TypeScript project references (`tsconfig.json`)
|
|
||||||
- **Path mapping**: Use relative imports, not path aliases
|
|
||||||
- **Build order**: `pnpm typecheck` builds all projects in dependency order
|
|
||||||
- **Build system**: Uses Vite for fast development, ESBuild for production optimization
|
|
||||||
- **Patches**: Custom patches in `patches/` directory for CKEditor and other dependencies
|
|
||||||
|
|
||||||
## Key Files for Context
|
|
||||||
|
|
||||||
- `apps/server/src/becca/entities/bnote.ts` - Note entity methods
|
|
||||||
- `apps/client/src/services/froca.ts` - Frontend cache API
|
|
||||||
- `apps/server/src/services/search/services/search.ts` - Search implementation
|
|
||||||
- `apps/server/src/routes/routes.ts` - API route registration
|
|
||||||
- `apps/client/src/widgets/basic_widget.ts` - Widget base class
|
|
||||||
- `apps/server/src/main.ts` - Server startup entry point
|
|
||||||
- `apps/client/src/desktop.ts` - Client initialization
|
|
||||||
- `apps/server/src/services/backend_script_api.ts` - Scripting API
|
|
||||||
- `apps/server/src/assets/db/schema.sql` - Database schema
|
|
||||||
|
|
||||||
## Note Types and Features
|
|
||||||
|
|
||||||
Trilium supports multiple note types with specialized widgets in `apps/client/src/widgets/type_widgets/`:
|
|
||||||
- **Text**: Rich text with CKEditor5 (markdown import/export)
|
|
||||||
- **Code**: Syntax-highlighted code editing with CodeMirror
|
|
||||||
- **File**: Binary file attachments
|
|
||||||
- **Image**: Image display with editing capabilities
|
|
||||||
- **Canvas**: Drawing/diagramming with Excalidraw
|
|
||||||
- **Mermaid**: Diagram generation
|
|
||||||
- **Relation Map**: Visual note relationship mapping
|
|
||||||
- **Web View**: Embedded web pages
|
|
||||||
- **Doc/Book**: Hierarchical documentation structure
|
|
||||||
|
|
||||||
### Collections
|
|
||||||
Notes can be marked with the `#collection` label to enable collection view modes. Collections support multiple view types:
|
|
||||||
- **List**: Standard list view
|
|
||||||
- **Grid**: Card/grid layout
|
|
||||||
- **Calendar**: Calendar-based view
|
|
||||||
- **Table**: Tabular data view
|
|
||||||
- **GeoMap**: Geographic map view
|
|
||||||
- **Board**: Kanban-style board
|
|
||||||
- **Presentation**: Slideshow presentation mode
|
|
||||||
|
|
||||||
View types are configured via `#viewType` label (e.g., `#viewType=table`). Each view mode stores its configuration in a separate attachment (e.g., `table.json`). Collections are organized separately from regular note type templates in the note creation menu.
|
|
||||||
|
|
||||||
## Common Development Tasks
|
|
||||||
|
|
||||||
### Adding New Note Types
|
|
||||||
1. Create widget in `apps/client/src/widgets/type_widgets/`
|
|
||||||
2. Register in `apps/client/src/services/note_types.ts`
|
|
||||||
3. Add backend handling in `apps/server/src/services/notes.ts`
|
|
||||||
|
|
||||||
### Extending Search
|
|
||||||
- Search expressions handled in `apps/server/src/services/search/`
|
|
||||||
- Add new search operators in search context files
|
|
||||||
- Remember: scoring happens in-memory, not at database level
|
|
||||||
|
|
||||||
### Custom CKEditor Plugins
|
|
||||||
- Create new package in `packages/` following existing plugin structure
|
|
||||||
- Register in `packages/ckeditor5/src/plugins.ts`
|
|
||||||
- See `ckeditor5-admonition`, `ckeditor5-footnotes`, `ckeditor5-math`, `ckeditor5-mermaid` for examples
|
|
||||||
|
|
||||||
### Database Migrations
|
|
||||||
- Add migration scripts in `apps/server/src/migrations/YYMMDD_HHMM__description.sql`
|
|
||||||
- Update schema in `apps/server/src/assets/db/schema.sql`
|
|
||||||
- Never bypass Becca cache after migrations
|
|
||||||
|
|
||||||
## Security & Features
|
|
||||||
|
|
||||||
### Security Considerations
|
|
||||||
- Per-note encryption with granular protected sessions
|
|
||||||
- CSRF protection for API endpoints
|
|
||||||
- OpenID and TOTP authentication support
|
|
||||||
- Sanitization of user-generated content
|
|
||||||
|
|
||||||
### Scripting System
|
|
||||||
Trilium provides powerful user scripting capabilities:
|
|
||||||
- **Frontend scripts**: Run in browser context with UI access
|
|
||||||
- **Backend scripts**: Run in Node.js context with full API access
|
|
||||||
- Script API documentation in `docs/Script API/`
|
|
||||||
- Backend API available via `api` object in script context
|
|
||||||
|
|
||||||
### Internationalization
|
|
||||||
- Translation files in `apps/client/src/translations/`
|
|
||||||
- Use translation system via `t()` function
|
|
||||||
- Automatic pluralization: Add `_other` suffix to translation keys (e.g., `item` and `item_other` for singular/plural)
|
|
||||||
|
|
||||||
## Testing Conventions
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// ETAPI test pattern
|
|
||||||
describe("etapi/feature", () => {
|
|
||||||
beforeAll(async () => {
|
|
||||||
config.General.noAuthentication = false;
|
|
||||||
app = await buildApp();
|
|
||||||
token = await login(app);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should test feature", async () => {
|
|
||||||
const response = await supertest(app)
|
|
||||||
.get("/etapi/notes?search=test")
|
|
||||||
.auth(USER, token, { type: "basic" })
|
|
||||||
.expect(200);
|
|
||||||
|
|
||||||
expect(response.body.results).toBeDefined();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
## Questions to Verify Understanding
|
|
||||||
|
|
||||||
Before implementing significant changes, confirm:
|
|
||||||
- Is this touching the cache layer? (Becca/Froca/Shaca must stay in sync via EntityChange records)
|
|
||||||
- Does this change API response shape? (Check backwards compatibility for ETAPI)
|
|
||||||
- Are you adding search features? (Understand expression-based architecture and in-memory scoring first)
|
|
||||||
- Is this a new widget? (Know which base class and lifecycle methods to use)
|
|
||||||
- Does this involve protected notes? (Check `isContentAvailable()` before accessing content)
|
|
||||||
- Is this a long-running operation? (Use TaskContext for progress reporting)
|
|
||||||
- Are you working with attributes? (Understand inheritance patterns: direct, child-prefix, template)
|
|
||||||
18
.github/workflows/checks.yml
vendored
18
.github/workflows/checks.yml
vendored
@@ -1,18 +0,0 @@
|
|||||||
name: Checks
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
pull_request_target:
|
|
||||||
types: [synchronize]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
main:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
steps:
|
|
||||||
- name: Check if PRs have conflicts
|
|
||||||
uses: eps1lon/actions-label-merge-conflict@v3
|
|
||||||
if: github.repository == ${{ vars.REPO_MAIN }}
|
|
||||||
with:
|
|
||||||
dirtyLabel: "merge-conflicts"
|
|
||||||
repoToken: "${{ secrets.MERGE_CONFLICT_LABEL_PAT }}"
|
|
||||||
100
.github/workflows/codeql.yml
vendored
100
.github/workflows/codeql.yml
vendored
@@ -1,100 +0,0 @@
|
|||||||
# 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: [ "main" ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ "main" ]
|
|
||||||
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@v6
|
|
||||||
|
|
||||||
# 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@v4
|
|
||||||
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@v4
|
|
||||||
with:
|
|
||||||
category: "/language:${{matrix.language}}"
|
|
||||||
78
.github/workflows/deploy-docs.yml
vendored
78
.github/workflows/deploy-docs.yml
vendored
@@ -1,78 +0,0 @@
|
|||||||
name: Deploy Documentation
|
|
||||||
|
|
||||||
on:
|
|
||||||
# Trigger on push to main branch
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
- master # Also support master branch
|
|
||||||
# Only run when docs files change
|
|
||||||
paths:
|
|
||||||
- 'docs/**'
|
|
||||||
- 'apps/edit-docs/**'
|
|
||||||
- 'apps/build-docs/**'
|
|
||||||
- 'packages/share-theme/**'
|
|
||||||
|
|
||||||
# Allow manual triggering from Actions tab
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
# Run on pull requests for preview deployments
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
- master
|
|
||||||
paths:
|
|
||||||
- 'docs/**'
|
|
||||||
- 'apps/edit-docs/**'
|
|
||||||
- 'apps/build-docs/**'
|
|
||||||
- 'packages/share-theme/**'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-and-deploy:
|
|
||||||
name: Build and Deploy Documentation
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 10
|
|
||||||
|
|
||||||
# Required permissions for deployment
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
deployments: write
|
|
||||||
pull-requests: write # For PR preview comments
|
|
||||||
id-token: write # For OIDC authentication (if needed)
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout Repository
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
|
|
||||||
- name: Setup pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: actions/setup-node@v6
|
|
||||||
with:
|
|
||||||
node-version: '24'
|
|
||||||
cache: 'pnpm'
|
|
||||||
|
|
||||||
- name: Install Dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
|
|
||||||
- name: Trigger build of documentation
|
|
||||||
run: pnpm docs:build
|
|
||||||
|
|
||||||
- name: Validate Built Site
|
|
||||||
run: |
|
|
||||||
test -f site/index.html || (echo "ERROR: site/index.html not found" && exit 1)
|
|
||||||
test -f site/developer-guide/index.html || (echo "ERROR: site/developer-guide/index.html not found" && exit 1)
|
|
||||||
echo "✓ User Guide and Developer Guide built successfully"
|
|
||||||
|
|
||||||
- name: Deploy
|
|
||||||
uses: ./.github/actions/deploy-to-cloudflare-pages
|
|
||||||
if: github.repository == ${{ vars.REPO_MAIN }}
|
|
||||||
with:
|
|
||||||
project_name: "trilium-docs"
|
|
||||||
comment_body: "📚 Documentation preview is ready"
|
|
||||||
production_url: "https://docs.triliumnotes.org"
|
|
||||||
deploy_dir: "site"
|
|
||||||
cloudflare_api_token: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
||||||
cloudflare_account_id: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
90
.github/workflows/dev.yml
vendored
90
.github/workflows/dev.yml
vendored
@@ -1,9 +1,9 @@
|
|||||||
name: Dev
|
name: Dev
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ main ]
|
branches-ignore:
|
||||||
pull_request:
|
- 'develop'
|
||||||
branches: [ main ]
|
- 'feature/update**'
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
@@ -12,11 +12,8 @@ concurrency:
|
|||||||
env:
|
env:
|
||||||
GHCR_REGISTRY: ghcr.io
|
GHCR_REGISTRY: ghcr.io
|
||||||
DOCKERHUB_REGISTRY: docker.io
|
DOCKERHUB_REGISTRY: docker.io
|
||||||
IMAGE_NAME: ${{ github.repository}}
|
IMAGE_NAME: ${{ github.repository_owner }}/notes
|
||||||
TEST_TAG: ${{ github.repository}}:test
|
TEST_TAG: ${{ github.repository_owner }}/notes:test
|
||||||
|
|
||||||
permissions:
|
|
||||||
pull-requests: write # for PR comments
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test_dev:
|
test_dev:
|
||||||
@@ -24,48 +21,39 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the repository
|
- name: Checkout the repository
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v4
|
|
||||||
- name: Set up node & dependencies
|
- name: Set up node & dependencies
|
||||||
uses: actions/setup-node@v6
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "npm"
|
||||||
- run: pnpm install --frozen-lockfile
|
|
||||||
|
|
||||||
- name: Typecheck
|
- run: npm ci
|
||||||
run: pnpm typecheck
|
|
||||||
|
|
||||||
- name: Run the unit tests
|
|
||||||
run: pnpm run test:all
|
|
||||||
|
|
||||||
|
- name: Run the TypeScript build
|
||||||
|
run: npx tsc
|
||||||
build_docker:
|
build_docker:
|
||||||
name: Build Docker image
|
name: Build Docker image
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs:
|
needs:
|
||||||
- test_dev
|
- test_dev
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v4
|
- name: Set up node & dependencies
|
||||||
- name: Install dependencies
|
uses: actions/setup-node@v4
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
- name: Update build info
|
|
||||||
run: pnpm run chore:update-build-info
|
|
||||||
- name: Trigger client build
|
|
||||||
run: pnpm client:build
|
|
||||||
- name: Send client bundle stats to RelativeCI
|
|
||||||
if: false
|
|
||||||
uses: relative-ci/agent-action@v3
|
|
||||||
with:
|
with:
|
||||||
webpackStatsFile: ./apps/client/dist/webpack-stats.json
|
node-version: 20
|
||||||
key: ${{ secrets.RELATIVE_CI_CLIENT_KEY }}
|
cache: "npm"
|
||||||
- name: Trigger server build
|
- run: npm ci
|
||||||
run: pnpm run server:build
|
- name: Run the TypeScript build
|
||||||
|
run: npx tsc
|
||||||
|
- name: Create server-package.json
|
||||||
|
run: cat package.json | grep -v electron > server-package.json
|
||||||
- uses: docker/setup-buildx-action@v3
|
- uses: docker/setup-buildx-action@v3
|
||||||
- uses: docker/build-push-action@v6
|
- uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: apps/server
|
context: .
|
||||||
cache-from: type=gha
|
cache-from: type=gha
|
||||||
cache-to: type=gha,mode=max
|
cache-to: type=gha,mode=max
|
||||||
test_docker:
|
test_docker:
|
||||||
@@ -80,16 +68,7 @@ jobs:
|
|||||||
- dockerfile: Dockerfile
|
- dockerfile: Dockerfile
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the repository
|
- name: Checkout the repository
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v4
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
|
|
||||||
- name: Update build info
|
|
||||||
run: pnpm run chore:update-build-info
|
|
||||||
- name: Trigger build
|
|
||||||
run: pnpm server:build
|
|
||||||
|
|
||||||
- name: Set IMAGE_NAME to lowercase
|
- name: Set IMAGE_NAME to lowercase
|
||||||
run: echo "IMAGE_NAME=${IMAGE_NAME,,}" >> $GITHUB_ENV
|
run: echo "IMAGE_NAME=${IMAGE_NAME,,}" >> $GITHUB_ENV
|
||||||
@@ -99,11 +78,25 @@ jobs:
|
|||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
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
|
- name: Build and export to Docker
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: apps/server
|
context: .
|
||||||
file: apps/server/${{ matrix.dockerfile }}
|
file: ${{ matrix.dockerfile }}
|
||||||
load: true
|
load: true
|
||||||
tags: ${{ env.TEST_TAG }}
|
tags: ${{ env.TEST_TAG }}
|
||||||
cache-from: type=gha
|
cache-from: type=gha
|
||||||
@@ -125,4 +118,5 @@ jobs:
|
|||||||
# Print the entire log of the container thus far, regardless if the healthcheck failed or succeeded
|
# Print the entire log of the container thus far, regardless if the healthcheck failed or succeeded
|
||||||
- name: Print entire log
|
- name: Print entire log
|
||||||
if: always()
|
if: always()
|
||||||
run: journalctl -u docker CONTAINER_NAME=trilium_local --no-pager
|
run: |
|
||||||
|
journalctl -u docker CONTAINER_NAME=trilium_local --no-pager
|
||||||
|
|||||||
115
.github/workflows/main-docker.yml
vendored
115
.github/workflows/main-docker.yml
vendored
@@ -1,7 +1,7 @@
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- "main"
|
- "develop"
|
||||||
- "feature/update**"
|
- "feature/update**"
|
||||||
- "feature/server_esm**"
|
- "feature/server_esm**"
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
@@ -14,8 +14,8 @@ on:
|
|||||||
env:
|
env:
|
||||||
GHCR_REGISTRY: ghcr.io
|
GHCR_REGISTRY: ghcr.io
|
||||||
DOCKERHUB_REGISTRY: docker.io
|
DOCKERHUB_REGISTRY: docker.io
|
||||||
IMAGE_NAME: ${{ github.repository}}
|
IMAGE_NAME: ${{ github.repository_owner }}/notes
|
||||||
TEST_TAG: ${{ github.repository}}:test
|
TEST_TAG: ${{ github.repository_owner }}/notes:test
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
@@ -32,7 +32,7 @@ jobs:
|
|||||||
- dockerfile: Dockerfile
|
- dockerfile: Dockerfile
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the repository
|
- name: Checkout the repository
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set IMAGE_NAME to lowercase
|
- name: Set IMAGE_NAME to lowercase
|
||||||
run: echo "IMAGE_NAME=${IMAGE_NAME,,}" >> $GITHUB_ENV
|
run: echo "IMAGE_NAME=${IMAGE_NAME,,}" >> $GITHUB_ENV
|
||||||
@@ -42,27 +42,29 @@ jobs:
|
|||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v4
|
|
||||||
- name: Set up node & dependencies
|
- name: Set up node & dependencies
|
||||||
uses: actions/setup-node@v6
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 20
|
||||||
cache: "pnpm"
|
cache: "npm"
|
||||||
|
|
||||||
- name: Install npm dependencies
|
- name: Install npm dependencies
|
||||||
run: pnpm install --frozen-lockfile
|
run: npm ci
|
||||||
|
|
||||||
- name: Install Playwright Browsers
|
- name: Install Playwright Browsers
|
||||||
run: pnpm exec playwright install --with-deps
|
run: npx playwright install --with-deps
|
||||||
|
|
||||||
- name: Run the TypeScript build
|
- name: Run the TypeScript build
|
||||||
run: pnpm run server: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
|
- name: Build and export to Docker
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: apps/server
|
context: .
|
||||||
file: apps/server/${{ matrix.dockerfile }}
|
file: ${{ matrix.dockerfile }}
|
||||||
load: true
|
load: true
|
||||||
tags: ${{ env.TEST_TAG }}
|
tags: ${{ env.TEST_TAG }}
|
||||||
cache-from: type=gha
|
cache-from: type=gha
|
||||||
@@ -70,7 +72,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Validate container run output
|
- name: Validate container run output
|
||||||
run: |
|
run: |
|
||||||
CONTAINER_ID=$(docker run -d --log-driver=journald --rm --network=host -e TRILIUM_PORT=8082 --volume ./apps/server/spec/db:/home/node/trilium-data --name trilium_local ${{ env.TEST_TAG }})
|
CONTAINER_ID=$(docker run -d --log-driver=journald --rm --network=host -e TRILIUM_PORT=8082 --volume ./integration-tests/db:/home/node/trilium-data --name trilium_local ${{ env.TEST_TAG }})
|
||||||
echo "Container ID: $CONTAINER_ID"
|
echo "Container ID: $CONTAINER_ID"
|
||||||
|
|
||||||
- name: Wait for the healthchecks to pass
|
- name: Wait for the healthchecks to pass
|
||||||
@@ -82,16 +84,8 @@ jobs:
|
|||||||
require-healthy: true
|
require-healthy: true
|
||||||
|
|
||||||
- name: Run Playwright tests
|
- name: Run Playwright tests
|
||||||
run: TRILIUM_DOCKER=1 TRILIUM_PORT=8082 pnpm --filter=server-e2e e2e
|
run: TRILIUM_DOCKER=1 npx playwright test
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
- name: Upload Playwright trace
|
|
||||||
if: failure()
|
|
||||||
uses: actions/upload-artifact@v5
|
|
||||||
with:
|
|
||||||
name: Playwright trace (${{ matrix.dockerfile }})
|
|
||||||
path: test-output/playwright/output
|
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v5
|
|
||||||
if: ${{ !cancelled() }}
|
if: ${{ !cancelled() }}
|
||||||
with:
|
with:
|
||||||
name: Playwright report (${{ matrix.dockerfile }})
|
name: Playwright report (${{ matrix.dockerfile }})
|
||||||
@@ -106,23 +100,7 @@ jobs:
|
|||||||
|
|
||||||
build:
|
build:
|
||||||
name: Build Docker images
|
name: Build Docker images
|
||||||
strategy:
|
runs-on: ubuntu-latest
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- dockerfile: Dockerfile.alpine
|
|
||||||
platform: linux/amd64
|
|
||||||
image: ubuntu-latest
|
|
||||||
- dockerfile: Dockerfile
|
|
||||||
platform: linux/arm64
|
|
||||||
image: ubuntu-24.04-arm
|
|
||||||
- dockerfile: Dockerfile.legacy
|
|
||||||
platform: linux/arm/v7
|
|
||||||
image: ubuntu-24.04-arm
|
|
||||||
- dockerfile: Dockerfile.legacy
|
|
||||||
platform: linux/arm/v8
|
|
||||||
image: ubuntu-24.04-arm
|
|
||||||
runs-on: ${{ matrix.image }}
|
|
||||||
needs:
|
needs:
|
||||||
- test_docker
|
- test_docker
|
||||||
permissions:
|
permissions:
|
||||||
@@ -130,6 +108,16 @@ jobs:
|
|||||||
packages: write
|
packages: write
|
||||||
attestations: write
|
attestations: write
|
||||||
id-token: write
|
id-token: write
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- dockerfile: Dockerfile.alpine
|
||||||
|
platform: linux/amd64
|
||||||
|
- dockerfile: Dockerfile
|
||||||
|
platform: linux/arm64
|
||||||
|
- dockerfile: Dockerfile
|
||||||
|
platform: linux/arm/v7
|
||||||
steps:
|
steps:
|
||||||
- name: Prepare
|
- name: Prepare
|
||||||
run: |
|
run: |
|
||||||
@@ -140,28 +128,9 @@ jobs:
|
|||||||
- name: Set TEST_TAG to lowercase
|
- name: Set TEST_TAG to lowercase
|
||||||
run: echo "TEST_TAG=${TEST_TAG,,}" >> $GITHUB_ENV
|
run: echo "TEST_TAG=${TEST_TAG,,}" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v4
|
|
||||||
- name: Set up node & dependencies
|
|
||||||
uses: actions/setup-node@v6
|
|
||||||
with:
|
|
||||||
node-version: 24
|
|
||||||
cache: 'pnpm'
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --frozen-lockfile
|
|
||||||
|
|
||||||
- name: Update build info
|
|
||||||
run: pnpm run chore:update-build-info
|
|
||||||
|
|
||||||
- name: Update nightly version
|
|
||||||
if: ${{ !startsWith(github.ref, 'refs/tags/v') }}
|
|
||||||
run: pnpm run chore:ci-update-nightly-version
|
|
||||||
|
|
||||||
- name: Run the TypeScript build
|
|
||||||
run: pnpm run server:build
|
|
||||||
|
|
||||||
- name: Docker meta
|
- name: Docker meta
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@v5
|
uses: docker/metadata-action@v5
|
||||||
@@ -182,6 +151,18 @@ jobs:
|
|||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
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
|
- name: Login to GHCR
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
@@ -200,8 +181,8 @@ jobs:
|
|||||||
id: build
|
id: build
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: apps/server
|
context: .
|
||||||
file: apps/server/${{ matrix.dockerfile }}
|
file: ${{ matrix.dockerfile }}
|
||||||
platforms: ${{ matrix.platform }}
|
platforms: ${{ matrix.platform }}
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
outputs: type=image,name=${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
|
outputs: type=image,name=${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
|
||||||
@@ -213,9 +194,9 @@ jobs:
|
|||||||
touch "/tmp/digests/${digest#sha256:}"
|
touch "/tmp/digests/${digest#sha256:}"
|
||||||
|
|
||||||
- name: Upload digest
|
- name: Upload digest
|
||||||
uses: actions/upload-artifact@v5
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: digests-${{ env.PLATFORM_PAIR }}-${{ matrix.dockerfile }}
|
name: digests-${{ env.PLATFORM_PAIR }}
|
||||||
path: /tmp/digests/*
|
path: /tmp/digests/*
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
retention-days: 1
|
retention-days: 1
|
||||||
@@ -227,7 +208,7 @@ jobs:
|
|||||||
- build
|
- build
|
||||||
steps:
|
steps:
|
||||||
- name: Download digests
|
- name: Download digests
|
||||||
uses: actions/download-artifact@v6
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
path: /tmp/digests
|
path: /tmp/digests
|
||||||
pattern: digests-*
|
pattern: digests-*
|
||||||
|
|||||||
100
.github/workflows/main.yml
vendored
Normal file
100
.github/workflows/main.yml
vendored
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
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
|
||||||
|
- name: linux
|
||||||
|
image: ubuntu-latest
|
||||||
|
extension: deb
|
||||||
|
- name: windows
|
||||||
|
image: windows-latest
|
||||||
|
extension: exe
|
||||||
|
runs-on: ${{ matrix.os.image }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Set up node & dependencies
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 20
|
||||||
|
- name: Set up Python for appdmg to be installed
|
||||||
|
if: ${{ matrix.os.name == 'macos' }}
|
||||||
|
run: brew install python-setuptools
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
- name: Update build info
|
||||||
|
run: npm run update-build-info
|
||||||
|
- name: Run electron-forge
|
||||||
|
run: npm run make-electron -- --arch=${{ matrix.arch }}
|
||||||
|
- name: Prepare artifacts (Unix)
|
||||||
|
if: runner.os != 'windows'
|
||||||
|
run: |
|
||||||
|
mkdir -p upload
|
||||||
|
file=$(find out/make -name '*.zip' -print -quit)
|
||||||
|
cp "$file" "upload/TriliumNextNotes-${{ matrix.os.name }}-${{ matrix.arch }}-${{ github.ref_name }}.zip"
|
||||||
|
file=$(find out/make -name '*.${{ matrix.os.extension }}' -print -quit)
|
||||||
|
cp "$file" "upload/TriliumNextNotes-${{ matrix.os.name }}-${{ matrix.arch }}-${{ github.ref_name }}.${{ matrix.os.extension }}"
|
||||||
|
- name: Prepare artifacts (Windows)
|
||||||
|
if: runner.os == 'windows'
|
||||||
|
run: |
|
||||||
|
mkdir upload
|
||||||
|
$file = Get-ChildItem -Path out/make -Filter '*.zip' -Recurse | Select-Object -First 1
|
||||||
|
Copy-Item -Path $file.FullName -Destination "upload/TriliumNextNotes-${{ matrix.os.name }}-${{ matrix.arch }}-${{ github.ref_name }}.zip"
|
||||||
|
$file = Get-ChildItem -Path out/make -Filter '*.${{ matrix.os.extension }}' -Recurse | Select-Object -First 1
|
||||||
|
Copy-Item -Path $file.FullName -Destination "upload/TriliumNextNotes-${{ matrix.os.name }}-${{ matrix.arch }}-${{ github.ref_name }}.${{ matrix.os.extension }}"
|
||||||
|
- 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-x64:
|
||||||
|
name: Build Linux Server x86_64
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Set up node & dependencies
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 20
|
||||||
|
cache: "npm"
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
- name: Run Linux server build (x86_64)
|
||||||
|
run: |
|
||||||
|
npm run update-build-info
|
||||||
|
./bin/build-server.sh
|
||||||
|
- name: Prepare artifacts
|
||||||
|
if: runner.os != 'windows'
|
||||||
|
run: |
|
||||||
|
mkdir -p upload
|
||||||
|
file=$(find dist -name '*.tar.xz' -print -quit)
|
||||||
|
cp "$file" "upload/TriliumNextNotes-linux-x64-${{ github.ref_name }}.tar.xz"
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: TriliumNextNotes linux server x64
|
||||||
|
path: upload/TriliumNextNotes-linux-x64-${{ github.ref_name }}.tar.xz
|
||||||
200
.github/workflows/nightly.yml
vendored
200
.github/workflows/nightly.yml
vendored
@@ -2,31 +2,16 @@ name: Nightly Release
|
|||||||
on:
|
on:
|
||||||
# This can be used to automatically publish nightlies at UTC nighttime
|
# This can be used to automatically publish nightlies at UTC nighttime
|
||||||
schedule:
|
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
|
# This can be used to allow manually triggering nightlies from the web interface
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- renovate/electron-forge*
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- .github/actions/build-electron/*
|
|
||||||
- .github/workflows/nightly.yml
|
|
||||||
- forge.config.ts
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
GITHUB_UPLOAD_URL: https://uploads.github.com/repos/TriliumNext/Notes/releases/179589950/assets{?name,label}
|
||||||
GITHUB_RELEASE_ID: 179589950
|
GITHUB_RELEASE_ID: 179589950
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
nightly-electron:
|
nightly-electron:
|
||||||
if: github.repository == ${{ vars.REPO_MAIN }}
|
|
||||||
name: Deploy nightly
|
name: Deploy nightly
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
@@ -35,109 +20,110 @@ jobs:
|
|||||||
os:
|
os:
|
||||||
- name: macos
|
- name: macos
|
||||||
image: macos-latest
|
image: macos-latest
|
||||||
shell: bash
|
extension: dmg
|
||||||
forge_platform: darwin
|
|
||||||
- name: linux
|
- name: linux
|
||||||
image: ubuntu-22.04
|
image: ubuntu-latest
|
||||||
shell: bash
|
extension: deb
|
||||||
forge_platform: linux
|
|
||||||
- name: windows
|
- name: windows
|
||||||
image: win-signing
|
image: windows-latest
|
||||||
shell: cmd
|
extension: exe
|
||||||
forge_platform: win32
|
|
||||||
# Exclude ARM64 Linux from default matrix to use native runner
|
|
||||||
exclude:
|
|
||||||
- arch: arm64
|
|
||||||
os:
|
|
||||||
name: linux
|
|
||||||
# Add ARM64 Linux with native ubuntu-24.04-arm runner for better-sqlite3 compatibility
|
|
||||||
include:
|
|
||||||
- arch: arm64
|
|
||||||
os:
|
|
||||||
name: linux
|
|
||||||
image: ubuntu-24.04-arm
|
|
||||||
shell: bash
|
|
||||||
forge_platform: linux
|
|
||||||
runs-on: ${{ matrix.os.image }}
|
runs-on: ${{ matrix.os.image }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v4
|
|
||||||
- name: Set up node & dependencies
|
- name: Set up node & dependencies
|
||||||
uses: actions/setup-node@v6
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 20
|
||||||
cache: 'pnpm'
|
- name: Set up Python for appdmg to be installed
|
||||||
|
if: ${{ matrix.os.name == 'macos' }}
|
||||||
|
run: brew install python-setuptools
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install --frozen-lockfile
|
run: npm ci
|
||||||
|
- name: Update build info
|
||||||
|
run: npm run update-build-info
|
||||||
- name: Update nightly version
|
- name: Update nightly version
|
||||||
run: pnpm run chore:ci-update-nightly-version
|
run: npm run ci-update-nightly-version
|
||||||
- name: Run the build
|
- name: Run electron-forge
|
||||||
uses: ./.github/actions/build-electron
|
run: npm run make-electron -- --arch=${{ matrix.arch }}
|
||||||
with:
|
- name: Prepare artifacts (Unix)
|
||||||
os: ${{ matrix.os.name }}
|
if: runner.os != 'windows'
|
||||||
arch: ${{ matrix.arch }}
|
run: |
|
||||||
shell: ${{ matrix.os.shell }}
|
mkdir -p upload
|
||||||
forge_platform: ${{ matrix.os.forge_platform }}
|
file=$(find out/make -name '*.zip' -print -quit)
|
||||||
env:
|
cp "$file" "upload/TriliumNextNotes-${{ matrix.os.name }}-${{ matrix.arch }}.zip"
|
||||||
APPLE_APP_CERTIFICATE_BASE64: ${{ secrets.APPLE_APP_CERTIFICATE_BASE64 }}
|
file=$(find out/make -name '*.${{ matrix.os.extension }}' -print -quit)
|
||||||
APPLE_APP_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_APP_CERTIFICATE_PASSWORD }}
|
cp "$file" "upload/TriliumNextNotes-${{ matrix.os.name }}-${{ matrix.arch }}.${{ matrix.os.extension }}"
|
||||||
APPLE_INSTALLER_CERTIFICATE_BASE64: ${{ secrets.APPLE_INSTALLER_CERTIFICATE_BASE64 }}
|
- name: Prepare artifacts (Windows)
|
||||||
APPLE_INSTALLER_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_INSTALLER_CERTIFICATE_PASSWORD }}
|
if: runner.os == 'windows'
|
||||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
run: |
|
||||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
mkdir upload
|
||||||
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
$file = Get-ChildItem -Path out/make -Filter '*.zip' -Recurse | Select-Object -First 1
|
||||||
WINDOWS_SIGN_EXECUTABLE: ${{ vars.WINDOWS_SIGN_EXECUTABLE }}
|
Copy-Item -Path $file.FullName -Destination "upload/TriliumNextNotes-${{ matrix.os.name }}-${{ matrix.arch }}.zip"
|
||||||
GPG_SIGNING_KEY: ${{ secrets.GPG_SIGN_KEY }}
|
$file = Get-ChildItem -Path out/make -Filter '*.${{ matrix.os.extension }}' -Recurse | Select-Object -First 1
|
||||||
|
Copy-Item -Path $file.FullName -Destination "upload/TriliumNextNotes-${{ matrix.os.name }}-${{ matrix.arch }}.${{ matrix.os.extension }}"
|
||||||
- name: Publish release
|
|
||||||
uses: softprops/action-gh-release@v2.4.2
|
|
||||||
if: ${{ github.event_name != 'pull_request' }}
|
|
||||||
with:
|
|
||||||
make_latest: false
|
|
||||||
prerelease: true
|
|
||||||
draft: false
|
|
||||||
fail_on_unmatched_files: true
|
|
||||||
files: apps/desktop/upload/*.*
|
|
||||||
tag_name: nightly
|
|
||||||
name: Nightly Build
|
|
||||||
|
|
||||||
- name: Publish artifacts
|
- name: Publish artifacts
|
||||||
uses: actions/upload-artifact@v5
|
uses: actions/upload-artifact@v4
|
||||||
if: ${{ github.event_name == 'pull_request' }}
|
|
||||||
with:
|
with:
|
||||||
name: TriliumNotes ${{ matrix.os.name }} ${{ matrix.arch }}
|
name: TriliumNextNotes ${{ matrix.os.name }} ${{ matrix.arch }}
|
||||||
path: apps/desktop/upload
|
path: upload/*.zip
|
||||||
|
overwrite: true
|
||||||
|
- name: Publish installer artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: TriliumNextNotes ${{ matrix.os.name }} ${{ matrix.arch }}
|
||||||
|
path: upload/*.${{ matrix.os.extension }}
|
||||||
|
overwrite: true
|
||||||
|
|
||||||
|
- name: Deploy release
|
||||||
|
uses: WebFreak001/deploy-nightly@v3.2.0
|
||||||
|
with:
|
||||||
|
upload_url: ${{ env.GITHUB_UPLOAD_URL }}
|
||||||
|
release_id: ${{ env.GITHUB_RELEASE_ID }}
|
||||||
|
asset_path: upload/TriliumNextNotes-${{ matrix.os.name }}-${{ matrix.arch }}.zip # path to archive to upload
|
||||||
|
asset_name: TriliumNextNotes-${{ matrix.os.name }}-${{ matrix.arch }}-nightly.zip # name to upload the release as, use $$ to insert date (YYYYMMDD) and 6 letter commit hash
|
||||||
|
asset_content_type: application/zip # required by GitHub API
|
||||||
|
- name: Deploy installer release
|
||||||
|
uses: WebFreak001/deploy-nightly@v3.2.0
|
||||||
|
with:
|
||||||
|
upload_url: ${{ env.GITHUB_UPLOAD_URL }}
|
||||||
|
release_id: ${{ env.GITHUB_RELEASE_ID }}
|
||||||
|
asset_path: upload/TriliumNextNotes-${{ matrix.os.name }}-${{ matrix.arch }}.${{ matrix.os.extension }} # path to archive to upload
|
||||||
|
asset_name: TriliumNextNotes-${{ matrix.os.name }}-${{ matrix.arch }}-nightly.${{ matrix.os.extension }} # name to upload the release as, use $$ to insert date (YYYYMMDD) and 6 letter commit hash
|
||||||
|
asset_content_type: application/zip # required by GitHub API
|
||||||
nightly-server:
|
nightly-server:
|
||||||
if: github.repository == ${{ vars.REPO_MAIN }}
|
|
||||||
name: Deploy server nightly
|
name: Deploy server nightly
|
||||||
strategy:
|
runs-on: ubuntu-latest
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
arch: [x64, arm64]
|
|
||||||
include:
|
|
||||||
- arch: x64
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
- arch: arm64
|
|
||||||
runs-on: ubuntu-24.04-arm
|
|
||||||
runs-on: ${{ matrix.runs-on }}
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v4
|
||||||
|
- name: Set up node & dependencies
|
||||||
- name: Run the build
|
uses: actions/setup-node@v4
|
||||||
uses: ./.github/actions/build-server
|
|
||||||
with:
|
with:
|
||||||
os: linux
|
node-version: 20
|
||||||
arch: ${{ matrix.arch }}
|
cache: "npm"
|
||||||
|
- name: Install dependencies
|
||||||
- name: Publish release
|
run: npm ci
|
||||||
uses: softprops/action-gh-release@v2.4.2
|
- name: Run Linux server build (x86_64)
|
||||||
if: ${{ github.event_name != 'pull_request' }}
|
run: |
|
||||||
|
npm run update-build-info
|
||||||
|
npm run ci-update-nightly-version
|
||||||
|
./bin/build-server.sh
|
||||||
|
- name: Prepare artifacts
|
||||||
|
if: runner.os != 'windows'
|
||||||
|
run: |
|
||||||
|
mkdir -p upload
|
||||||
|
file=$(find dist -name '*.tar.xz' -print -quit)
|
||||||
|
cp "$file" "upload/TriliumNextNotes-linux-x64-${{ github.ref_name }}.tar.xz"
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
make_latest: false
|
name: TriliumNextNotes linux server x64
|
||||||
prerelease: true
|
path: upload/TriliumNextNotes-linux-x64-${{ github.ref_name }}.tar.xz
|
||||||
draft: false
|
overwrite: true
|
||||||
fail_on_unmatched_files: true
|
|
||||||
files: upload/*.*
|
- name: Deploy release
|
||||||
tag_name: nightly
|
uses: WebFreak001/deploy-nightly@v3.2.0
|
||||||
name: Nightly Build
|
with:
|
||||||
|
upload_url: ${{ env.GITHUB_UPLOAD_URL }}
|
||||||
|
release_id: ${{ env.GITHUB_RELEASE_ID }}
|
||||||
|
asset_path: upload/TriliumNextNotes-linux-x64-${{ github.ref_name }}.tar.xz # path to archive to upload
|
||||||
|
asset_name: TriliumNextNotes-linux-x64-nightly.zip # name to upload the release as, use $$ to insert date (YYYYMMDD) and 6 letter commit hash
|
||||||
|
asset_content_type: application/zip # required by GitHub API
|
||||||
|
|||||||
98
.github/workflows/playwright.yml
vendored
98
.github/workflows/playwright.yml
vendored
@@ -1,87 +1,27 @@
|
|||||||
name: playwright
|
name: Playwright Tests
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches: [ develop ]
|
||||||
- main
|
|
||||||
- hotfix
|
|
||||||
paths-ignore:
|
|
||||||
- "apps/website/**"
|
|
||||||
pull_request:
|
pull_request:
|
||||||
|
branches: [ develop ]
|
||||||
permissions:
|
|
||||||
actions: read
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
e2e:
|
test:
|
||||||
strategy:
|
timeout-minutes: 60
|
||||||
fail-fast: false
|
runs-on: ubuntu-latest
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- name: linux-x64
|
|
||||||
os: ubuntu-22.04
|
|
||||||
arch: x64
|
|
||||||
- name: linux-arm64
|
|
||||||
os: ubuntu-24.04-arm
|
|
||||||
arch: arm64
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
name: E2E tests on ${{ matrix.name }}
|
|
||||||
env:
|
|
||||||
TRILIUM_DOCKER: 1
|
|
||||||
TRILIUM_PORT: 8082
|
|
||||||
TRILIUM_DATA_DIR: "${{ github.workspace }}/apps/server/spec/db"
|
|
||||||
TRILIUM_INTEGRATION_TEST: memory
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
filter: tree:0
|
node-version: lts/*
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v4
|
|
||||||
- uses: actions/setup-node@v6
|
|
||||||
with:
|
|
||||||
node-version: 24
|
|
||||||
cache: 'pnpm'
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install --frozen-lockfile
|
run: npm ci
|
||||||
|
- name: Install Playwright Browsers
|
||||||
- name: Install Playwright browsers
|
run: npx playwright install --with-deps
|
||||||
run: pnpm exec playwright install --with-deps
|
- name: Run Playwright tests
|
||||||
|
run: npx playwright test
|
||||||
- name: Build the server
|
- uses: actions/upload-artifact@v4
|
||||||
uses: ./.github/actions/build-server
|
if: ${{ !cancelled() }}
|
||||||
with:
|
with:
|
||||||
os: linux
|
name: playwright-report
|
||||||
arch: ${{ matrix.arch }}
|
path: playwright-report/
|
||||||
|
retention-days: 30
|
||||||
- name: Unpack and start the server
|
|
||||||
run: |
|
|
||||||
version=$(node --eval "console.log(require('./package.json').version)")
|
|
||||||
file=$(find ./upload -name '*.tar.xz' -print -quit)
|
|
||||||
name=$(basename "$file" .tar.xz)
|
|
||||||
mkdir -p ./server-dist
|
|
||||||
tar -xvf "$file" -C ./server-dist
|
|
||||||
server_dir="./server-dist/TriliumNotes-Server-$version-linux-${{ matrix.arch }}"
|
|
||||||
if [ ! -d "$server_dir" ]; then
|
|
||||||
echo Missing dir.
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
cd "$server_dir"
|
|
||||||
"./trilium.sh" &
|
|
||||||
sleep 10
|
|
||||||
|
|
||||||
- name: Server end-to-end tests
|
|
||||||
run: pnpm --filter server-e2e e2e
|
|
||||||
|
|
||||||
- name: Upload test report
|
|
||||||
if: failure()
|
|
||||||
uses: actions/upload-artifact@v5
|
|
||||||
with:
|
|
||||||
name: e2e report ${{ matrix.arch }}
|
|
||||||
path: apps/server-e2e/test-output
|
|
||||||
|
|
||||||
- name: Kill the server
|
|
||||||
if: always()
|
|
||||||
run: pkill -f trilium || true
|
|
||||||
|
|||||||
20
.github/workflows/release-winget.yml
vendored
20
.github/workflows/release-winget.yml
vendored
@@ -1,20 +0,0 @@
|
|||||||
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.WINGET_PAT }}
|
|
||||||
release-tag: ${{ github.event.inputs.release_tag || github.event.release.tag_name }}
|
|
||||||
172
.github/workflows/release.yml
vendored
172
.github/workflows/release.yml
vendored
@@ -3,9 +3,9 @@ on:
|
|||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- "v*"
|
- "v*"
|
||||||
|
workflow_dispatch:
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
discussions: write
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
@@ -20,120 +20,76 @@ jobs:
|
|||||||
os:
|
os:
|
||||||
- name: macos
|
- name: macos
|
||||||
image: macos-latest
|
image: macos-latest
|
||||||
shell: bash
|
extension: dmg
|
||||||
forge_platform: darwin
|
|
||||||
- name: linux
|
- name: linux
|
||||||
image: ubuntu-22.04
|
image: ubuntu-latest
|
||||||
shell: bash
|
extension: deb
|
||||||
forge_platform: linux
|
|
||||||
- name: windows
|
- name: windows
|
||||||
image: win-signing
|
image: windows-latest
|
||||||
shell: cmd
|
extension: exe
|
||||||
forge_platform: win32
|
|
||||||
# Exclude ARM64 Linux from default matrix to use native runner
|
|
||||||
exclude:
|
|
||||||
- arch: arm64
|
|
||||||
os:
|
|
||||||
name: linux
|
|
||||||
# Add ARM64 Linux with native ubuntu-24.04-arm runner for better-sqlite3 compatibility
|
|
||||||
include:
|
|
||||||
- arch: arm64
|
|
||||||
os:
|
|
||||||
name: linux
|
|
||||||
image: ubuntu-24.04-arm
|
|
||||||
shell: bash
|
|
||||||
forge_platform: linux
|
|
||||||
runs-on: ${{ matrix.os.image }}
|
runs-on: ${{ matrix.os.image }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v4
|
|
||||||
- name: Set up node & dependencies
|
- name: Set up node & dependencies
|
||||||
uses: actions/setup-node@v6
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 20
|
||||||
cache: 'pnpm'
|
- name: Set up Python for appdmg to be installed
|
||||||
|
if: ${{ matrix.os.name == 'macos' }}
|
||||||
|
run: brew install python-setuptools
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: pnpm install --frozen-lockfile
|
run: npm ci
|
||||||
- name: Run the build
|
- name: Update build info
|
||||||
uses: ./.github/actions/build-electron
|
run: npm run update-build-info
|
||||||
|
- name: Run electron-forge
|
||||||
|
run: npm run make-electron -- --arch=${{ matrix.arch }}
|
||||||
|
- name: Prepare artifacts (Unix)
|
||||||
|
if: runner.os != 'windows'
|
||||||
|
run: |
|
||||||
|
mkdir -p upload
|
||||||
|
file=$(find out/make -name '*.zip' -print -quit)
|
||||||
|
cp "$file" "upload/TriliumNextNotes-${{ github.ref_name }}-${{ matrix.os.name }}-${{ matrix.arch }}.zip"
|
||||||
|
file=$(find out/make -name '*.${{ matrix.os.extension }}' -print -quit)
|
||||||
|
cp "$file" "upload/TriliumNextNotes-${{ github.ref_name }}-${{ matrix.os.name }}-${{ matrix.arch }}.${{ matrix.os.extension }}"
|
||||||
|
- name: Prepare artifacts (Windows)
|
||||||
|
if: runner.os == 'windows'
|
||||||
|
run: |
|
||||||
|
mkdir upload
|
||||||
|
$file = Get-ChildItem -Path out/make -Filter '*.zip' -Recurse | Select-Object -First 1
|
||||||
|
Copy-Item -Path $file.FullName -Destination "upload/TriliumNextNotes-${{ github.ref_name }}-${{ matrix.os.name }}-${{ matrix.arch }}.zip"
|
||||||
|
$file = Get-ChildItem -Path out/make -Filter '*.${{ matrix.os.extension }}' -Recurse | Select-Object -First 1
|
||||||
|
Copy-Item -Path $file.FullName -Destination "upload/TriliumNextNotes-${{ github.ref_name }}-${{ matrix.os.name }}-${{ matrix.arch }}.${{ matrix.os.extension }}"
|
||||||
|
- name: Publish release
|
||||||
|
uses: softprops/action-gh-release@v2
|
||||||
with:
|
with:
|
||||||
os: ${{ matrix.os.name }}
|
draft: true
|
||||||
arch: ${{ matrix.arch }}
|
fail_on_unmatched_files: true
|
||||||
shell: ${{ matrix.os.shell }}
|
files: upload/*.*
|
||||||
forge_platform: ${{ matrix.os.forge_platform }}
|
build_linux_server-x64:
|
||||||
env:
|
name: Build Linux Server x86_64
|
||||||
APPLE_APP_CERTIFICATE_BASE64: ${{ secrets.APPLE_APP_CERTIFICATE_BASE64 }}
|
runs-on: ubuntu-latest
|
||||||
APPLE_APP_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_APP_CERTIFICATE_PASSWORD }}
|
steps:
|
||||||
APPLE_INSTALLER_CERTIFICATE_BASE64: ${{ secrets.APPLE_INSTALLER_CERTIFICATE_BASE64 }}
|
- uses: actions/checkout@v4
|
||||||
APPLE_INSTALLER_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_INSTALLER_CERTIFICATE_PASSWORD }}
|
- name: Set up node & dependencies
|
||||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
uses: actions/setup-node@v4
|
||||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
with:
|
||||||
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
node-version: 20
|
||||||
WINDOWS_SIGN_EXECUTABLE: ${{ vars.WINDOWS_SIGN_EXECUTABLE }}
|
cache: "npm"
|
||||||
GPG_SIGNING_KEY: ${{ secrets.GPG_SIGN_KEY }}
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
- name: Upload the artifact
|
- name: Run Linux server build (x86_64)
|
||||||
uses: actions/upload-artifact@v5
|
run: |
|
||||||
with:
|
npm run update-build-info
|
||||||
name: release-desktop-${{ matrix.os.name }}-${{ matrix.arch }}
|
./bin/build-server.sh
|
||||||
path: apps/desktop/upload/*.*
|
- name: Prepare artifacts
|
||||||
|
if: runner.os != 'windows'
|
||||||
build_server:
|
run: |
|
||||||
name: Build Linux Server
|
mkdir -p upload
|
||||||
strategy:
|
file=$(find dist -name '*.tar.xz' -print -quit)
|
||||||
fail-fast: false
|
cp "$file" "upload/TriliumNextNotes-${{ github.ref_name }}-server-linux-x64.tar.xz"
|
||||||
matrix:
|
- name: Publish release
|
||||||
arch: [x64, arm64]
|
uses: softprops/action-gh-release@v2
|
||||||
include:
|
with:
|
||||||
- arch: x64
|
draft: true
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
- arch: arm64
|
|
||||||
runs-on: ubuntu-24.04-arm
|
|
||||||
runs-on: ${{ matrix.runs-on }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
|
|
||||||
- name: Run the build
|
|
||||||
uses: ./.github/actions/build-server
|
|
||||||
with:
|
|
||||||
os: linux
|
|
||||||
arch: ${{ matrix.arch }}
|
|
||||||
|
|
||||||
- name: Upload the artifact
|
|
||||||
uses: actions/upload-artifact@v5
|
|
||||||
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
|
|
||||||
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
with:
|
|
||||||
sparse-checkout: |
|
|
||||||
docs/Release Notes
|
|
||||||
|
|
||||||
- name: Download all artifacts
|
|
||||||
uses: actions/download-artifact@v6
|
|
||||||
with:
|
|
||||||
merge-multiple: true
|
|
||||||
pattern: release-*
|
|
||||||
path: upload
|
|
||||||
|
|
||||||
- name: Publish stable release
|
|
||||||
uses: softprops/action-gh-release@v2.4.2
|
|
||||||
with:
|
|
||||||
draft: false
|
|
||||||
body_path: docs/Release Notes/Release Notes/${{ github.ref_name }}.md
|
|
||||||
fail_on_unmatched_files: true
|
fail_on_unmatched_files: true
|
||||||
files: upload/*.*
|
files: upload/*.*
|
||||||
discussion_category_name: Releases
|
|
||||||
make_latest: ${{ !contains(github.ref, 'rc') }}
|
|
||||||
prerelease: ${{ contains(github.ref, 'rc') }}
|
|
||||||
token: ${{ secrets.RELEASE_PAT }}
|
|
||||||
|
|||||||
11
.github/workflows/unblock_signing.yml
vendored
11
.github/workflows/unblock_signing.yml
vendored
@@ -1,11 +0,0 @@
|
|||||||
name: Unblock signing
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
unblock-win-signing:
|
|
||||||
runs-on: win-signing
|
|
||||||
steps:
|
|
||||||
- run: |
|
|
||||||
cat ${{ vars.WINDOWS_SIGN_ERROR_LOG }}
|
|
||||||
rm ${{ vars.WINDOWS_SIGN_ERROR_LOG }}
|
|
||||||
51
.github/workflows/website.yml
vendored
51
.github/workflows/website.yml
vendored
@@ -1,51 +0,0 @@
|
|||||||
name: Deploy website
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
paths:
|
|
||||||
- "apps/website/**"
|
|
||||||
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- "apps/website/**"
|
|
||||||
|
|
||||||
release:
|
|
||||||
types: [ released ]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-and-deploy:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
name: Build & deploy website
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
deployments: write
|
|
||||||
pull-requests: write # For PR preview comments
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- uses: pnpm/action-setup@v4
|
|
||||||
- name: Set up node & dependencies
|
|
||||||
uses: actions/setup-node@v6
|
|
||||||
with:
|
|
||||||
node-version: 24
|
|
||||||
cache: "pnpm"
|
|
||||||
|
|
||||||
- name: Install dependencies
|
|
||||||
run: pnpm install --filter website --frozen-lockfile
|
|
||||||
|
|
||||||
- name: Build the website
|
|
||||||
run: pnpm website:build
|
|
||||||
|
|
||||||
- name: Deploy
|
|
||||||
uses: ./.github/actions/deploy-to-cloudflare-pages
|
|
||||||
with:
|
|
||||||
project_name: "trilium-homepage"
|
|
||||||
comment_body: "📚 Website preview is ready"
|
|
||||||
production_url: "https://triliumnotes.org"
|
|
||||||
deploy_dir: "apps/website/dist"
|
|
||||||
cloudflare_api_token: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
|
||||||
cloudflare_account_id: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
71
.github/workflows_old/codeql-analysis.yml
vendored
Normal file
71
.github/workflows_old/codeql-analysis.yml
vendored
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
# 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"
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
# The branches below must be a subset of the branches above
|
||||||
|
branches: [ master ]
|
||||||
|
schedule:
|
||||||
|
- cron: '37 4 * * 1'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
analyze:
|
||||||
|
name: Analyze
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
actions: read
|
||||||
|
contents: read
|
||||||
|
security-events: write
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
language: [ 'javascript' ]
|
||||||
|
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
|
||||||
|
# Learn more:
|
||||||
|
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
# Initializes the CodeQL tools for scanning.
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@v1
|
||||||
|
with:
|
||||||
|
languages: ${{ matrix.language }}
|
||||||
|
# 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.
|
||||||
|
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||||
|
|
||||||
|
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||||
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
|
- name: Autobuild
|
||||||
|
uses: github/codeql-action/autobuild@v1
|
||||||
|
|
||||||
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
|
# 📚 https://git.io/JvXDl
|
||||||
|
|
||||||
|
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||||
|
# and modify them (or add more) to build your code if your project
|
||||||
|
# uses a compiled language
|
||||||
|
|
||||||
|
#- run: |
|
||||||
|
# make bootstrap
|
||||||
|
# make release
|
||||||
|
|
||||||
|
- name: Perform CodeQL Analysis
|
||||||
|
uses: github/codeql-action/analyze@v1
|
||||||
53
.github/workflows_old/docker.yaml
vendored
Normal file
53
.github/workflows_old/docker.yaml
vendored
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
name: Publish Docker image
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags: [v*]
|
||||||
|
jobs:
|
||||||
|
push_to_registries:
|
||||||
|
name: Push Docker image to multiple registries
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
packages: write
|
||||||
|
contents: read
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v1
|
||||||
|
- name: Docker meta
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v3
|
||||||
|
with:
|
||||||
|
images: |
|
||||||
|
zadam/trilium
|
||||||
|
ghcr.io/zadam/trilium
|
||||||
|
tags: |
|
||||||
|
type=semver,pattern={{version}}
|
||||||
|
type=semver,pattern={{major}}.{{minor}}-latest
|
||||||
|
type=match,pattern=(\d+.\d+).\d+\-beta,enable=${{ endsWith(github.ref, 'beta') }},group=1,suffix=-latest
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v1
|
||||||
|
with:
|
||||||
|
install: true
|
||||||
|
- name: Log in to Docker Hub
|
||||||
|
uses: docker/login-action@v1
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
- name: Log in to GitHub Docker Registry
|
||||||
|
uses: docker/login-action@v1
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.repository_owner }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Create server-package.json
|
||||||
|
run: cat package.json | grep -v electron > server-package.json
|
||||||
|
- name: Build and Push
|
||||||
|
uses: docker/build-push-action@v2.7.0
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/arm/v6
|
||||||
|
push: true
|
||||||
|
cache-from: type=registry,ref=zadam/trilium:buildcache
|
||||||
|
cache-to: type=registry,ref=zadam/trilium:buildcache,mode=max
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
74
.gitignore
vendored
74
.gitignore
vendored
@@ -1,51 +1,35 @@
|
|||||||
# See https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files for more about ignoring files.
|
.DS_Store
|
||||||
/.cache
|
node_modules/
|
||||||
|
dist/
|
||||||
# compiled output
|
build/
|
||||||
dist
|
src/public/app-dist/
|
||||||
tmp
|
|
||||||
out-tsc
|
|
||||||
|
|
||||||
# dependencies
|
|
||||||
node_modules
|
|
||||||
|
|
||||||
# IDEs and editors
|
|
||||||
/.idea
|
|
||||||
.idea
|
|
||||||
.project
|
|
||||||
.classpath
|
|
||||||
.c9/
|
|
||||||
*.launch
|
|
||||||
.settings/
|
|
||||||
*.sublime-workspace
|
|
||||||
|
|
||||||
# misc
|
|
||||||
/.sass-cache
|
|
||||||
/connect.lock
|
|
||||||
/coverage
|
|
||||||
/libpeerconnection.log
|
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
yarn-error.log
|
yarn-error.log
|
||||||
testem.log
|
po-*/
|
||||||
/typings
|
|
||||||
|
|
||||||
# System Files
|
*.db
|
||||||
.DS_Store
|
!integration-tests/db/document.db
|
||||||
Thumbs.db
|
!integration-tests/db/config.ini
|
||||||
|
integration-tests/db/log
|
||||||
|
integration-tests/db/sessions
|
||||||
|
integration-tests/db/backup
|
||||||
|
integration-tests/db/session_secret.txt
|
||||||
|
|
||||||
vite.config.*.timestamp*
|
cert.key
|
||||||
vitest.config.*.timestamp*
|
cert.crt
|
||||||
test-output
|
server-package.json
|
||||||
|
.idea/httpRequests/
|
||||||
|
.idea/shelf/
|
||||||
|
data/
|
||||||
|
data-test/
|
||||||
|
tmp/
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
apps/*/data*
|
out/
|
||||||
apps/*/out
|
|
||||||
upload
|
|
||||||
|
|
||||||
.rollup.cache
|
images/app-icons/mac/*.png
|
||||||
*.tsbuildinfo
|
/test-results/
|
||||||
|
/playwright-report/
|
||||||
/result
|
/blob-report/
|
||||||
.svelte-kit
|
/playwright/.cache/
|
||||||
|
/playwright/.auth/
|
||||||
# docs
|
|
||||||
site/
|
|
||||||
15
.gitpod.dockerfile
Normal file
15
.gitpod.dockerfile
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
FROM gitpod/workspace-full
|
||||||
|
|
||||||
|
RUN sudo apt-get update \
|
||||||
|
&& sudo apt-get install -yq --no-install-recommends \
|
||||||
|
libpng16-16 \
|
||||||
|
libpng-dev \
|
||||||
|
pkg-config \
|
||||||
|
autoconf \
|
||||||
|
libtool \
|
||||||
|
build-essential \
|
||||||
|
nasm \
|
||||||
|
libx11-dev \
|
||||||
|
libxkbfile-dev \
|
||||||
|
&& sudo rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
11
.gitpod.yml
Normal file
11
.gitpod.yml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
image:
|
||||||
|
file: .gitpod.dockerfile
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- before: nvm install 20.15.1 && nvm use 20.15.1
|
||||||
|
init: npm install
|
||||||
|
command: npm run start-server
|
||||||
|
|
||||||
|
ports:
|
||||||
|
- port: 8080
|
||||||
|
onOpen: open-preview
|
||||||
6
.idea/.gitignore
generated
vendored
Normal file
6
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/workspace.xml
|
||||||
|
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources.local.xml
|
||||||
|
/dataSources/
|
||||||
15
.idea/codeStyles/Project.xml
generated
Normal file
15
.idea/codeStyles/Project.xml
generated
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<code_scheme name="Project" version="173">
|
||||||
|
<option name="OTHER_INDENT_OPTIONS">
|
||||||
|
<value>
|
||||||
|
<option name="INDENT_SIZE" value="2" />
|
||||||
|
<option name="TAB_SIZE" value="2" />
|
||||||
|
</value>
|
||||||
|
</option>
|
||||||
|
<codeStyleSettings language="JSON">
|
||||||
|
<indentOptions>
|
||||||
|
<option name="INDENT_SIZE" value="4" />
|
||||||
|
</indentOptions>
|
||||||
|
</codeStyleSettings>
|
||||||
|
</code_scheme>
|
||||||
|
</component>
|
||||||
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
5
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<component name="ProjectCodeStyleConfiguration">
|
||||||
|
<state>
|
||||||
|
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||||
|
</state>
|
||||||
|
</component>
|
||||||
12
.idea/dataSources.xml
generated
Normal file
12
.idea/dataSources.xml
generated
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||||
|
<data-source source="LOCAL" name="document.db" uuid="2a4ac1e6-b828-4a2a-8e4a-3f59f10aff26">
|
||||||
|
<driver-ref>sqlite.xerial</driver-ref>
|
||||||
|
<synchronize>true</synchronize>
|
||||||
|
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
|
||||||
|
<jdbc-url>jdbc:sqlite:$PROJECT_DIR$/data/document.db</jdbc-url>
|
||||||
|
<working-dir>$ProjectFileDir$</working-dir>
|
||||||
|
</data-source>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
4
.idea/encodings.xml
generated
Normal file
4
.idea/encodings.xml
generated
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding" addBOMForNewFiles="with NO BOM" />
|
||||||
|
</project>
|
||||||
15
.idea/git_toolbox_prj.xml
generated
Normal file
15
.idea/git_toolbox_prj.xml
generated
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="GitToolBoxProjectSettings">
|
||||||
|
<option name="commitMessageIssueKeyValidationOverride">
|
||||||
|
<BoolValueOverride>
|
||||||
|
<option name="enabled" value="true" />
|
||||||
|
</BoolValueOverride>
|
||||||
|
</option>
|
||||||
|
<option name="commitMessageValidationEnabledOverride">
|
||||||
|
<BoolValueOverride>
|
||||||
|
<option name="enabled" value="true" />
|
||||||
|
</BoolValueOverride>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
11
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
11
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||||
|
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
||||||
|
<option name="processCode" value="true" />
|
||||||
|
<option name="processLiterals" value="true" />
|
||||||
|
<option name="processComments" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
</profile>
|
||||||
|
</component>
|
||||||
6
.idea/jsLibraryMappings.xml
generated
Normal file
6
.idea/jsLibraryMappings.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="JavaScriptLibraryMappings">
|
||||||
|
<includedPredefinedLibrary name="Node.js Core" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
9
.idea/jsLinters/jslint.xml
generated
Normal file
9
.idea/jsLinters/jslint.xml
generated
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="JSLintConfiguration">
|
||||||
|
<option devel="true" />
|
||||||
|
<option es6="true" />
|
||||||
|
<option maxerr="50" />
|
||||||
|
<option node="true" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
8
.idea/misc.xml
generated
Normal file
8
.idea/misc.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<project version="4">
|
||||||
|
<component name="JavaScriptSettings">
|
||||||
|
<option name="languageLevel" value="ES6" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_16" default="true" project-jdk-name="openjdk-16" project-jdk-type="JavaSDK">
|
||||||
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/trilium.iml" filepath="$PROJECT_DIR$/trilium.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
7
.idea/sqldialects.xml
generated
Normal file
7
.idea/sqldialects.xml
generated
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="SqlDialectMappings">
|
||||||
|
<file url="file://$PROJECT_DIR$" dialect="SQLite" />
|
||||||
|
<file url="PROJECT" dialect="SQLite" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
5
.prettierignore
Normal file
5
.prettierignore
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
*.html
|
||||||
|
*.md
|
||||||
|
*.yml
|
||||||
|
libraries/*
|
||||||
|
docs/*
|
||||||
22
.prettierrc
Normal file
22
.prettierrc
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
14
.vscode/extensions.json
vendored
14
.vscode/extensions.json
vendored
@@ -1,15 +1,3 @@
|
|||||||
{
|
{
|
||||||
"recommendations": [
|
"recommendations": ["lokalise.i18n-ally", "editorconfig.editorconfig"]
|
||||||
"dbaeumer.vscode-eslint",
|
|
||||||
"editorconfig.editorconfig",
|
|
||||||
"lokalise.i18n-ally",
|
|
||||||
"ms-azuretools.vscode-docker",
|
|
||||||
"ms-playwright.playwright",
|
|
||||||
"redhat.vscode-yaml",
|
|
||||||
"tobermory.es6-string-html",
|
|
||||||
"vitest.explorer",
|
|
||||||
"yzhang.markdown-all-in-one",
|
|
||||||
"svelte.svelte-vscode",
|
|
||||||
"bradlc.vscode-tailwindcss"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
3
.vscode/i18n-ally-custom-framework.yml
vendored
3
.vscode/i18n-ally-custom-framework.yml
vendored
@@ -3,7 +3,6 @@
|
|||||||
languageIds:
|
languageIds:
|
||||||
- javascript
|
- javascript
|
||||||
- typescript
|
- typescript
|
||||||
- typescriptreact
|
|
||||||
- html
|
- html
|
||||||
|
|
||||||
# An array of RegExes to find the key usage. **The key should be captured in the first match group**.
|
# An array of RegExes to find the key usage. **The key should be captured in the first match group**.
|
||||||
@@ -14,7 +13,6 @@ usageMatchRegex:
|
|||||||
# the `{key}` will be placed by a proper keypath matching regex,
|
# the `{key}` will be placed by a proper keypath matching regex,
|
||||||
# you can ignore it and use your own matching rules as well
|
# you can ignore it and use your own matching rules as well
|
||||||
- "[^\\w\\d]t\\(['\"`]({key})['\"`]"
|
- "[^\\w\\d]t\\(['\"`]({key})['\"`]"
|
||||||
- <Trans\s*i18nKey="({key})"[^>]*>
|
|
||||||
|
|
||||||
# A RegEx to set a custom scope range. This scope will be used as a prefix when detecting keys
|
# A RegEx to set a custom scope range. This scope will be used as a prefix when detecting keys
|
||||||
# and works like how the i18next framework identifies the namespace scope from the
|
# and works like how the i18next framework identifies the namespace scope from the
|
||||||
@@ -27,7 +25,6 @@ scopeRangeRegex: "useTranslation\\(\\s*\\[?\\s*['\"`](.*?)['\"`]"
|
|||||||
# The "$1" will be replaced by the keypath specified.
|
# The "$1" will be replaced by the keypath specified.
|
||||||
refactorTemplates:
|
refactorTemplates:
|
||||||
- t("$1")
|
- t("$1")
|
||||||
- {t("$1")}
|
|
||||||
- ${t("$1")}
|
- ${t("$1")}
|
||||||
- <%= t("$1") %>
|
- <%= t("$1") %>
|
||||||
|
|
||||||
|
|||||||
20
.vscode/i18n-ally-reviews.yml
vendored
Normal file
20
.vscode/i18n-ally-reviews.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# Review comments generated by i18n-ally. Please commit this file.
|
||||||
|
|
||||||
|
reviews:
|
||||||
|
help.inPageSearch:
|
||||||
|
description: >-
|
||||||
|
Describes the shortcut which triggers a search within the current
|
||||||
|
page/note only
|
||||||
|
add_label.to_value:
|
||||||
|
locales:
|
||||||
|
fr:
|
||||||
|
comments:
|
||||||
|
- user:
|
||||||
|
name: Potjoe-97
|
||||||
|
email: giann@LAPTOPT490-GF
|
||||||
|
id: QXec0JUoxfGmMlpch-B1S
|
||||||
|
comment: ''
|
||||||
|
suggestion: vers la valeur
|
||||||
|
type: request_change
|
||||||
|
time: '2024-10-15T16:57:06.188Z'
|
||||||
|
resolved: true
|
||||||
22
.vscode/launch.json
vendored
Normal file
22
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
// nodemon should be installed globally, use npm i -g nodemon
|
||||||
|
{
|
||||||
|
"console": "integratedTerminal",
|
||||||
|
"internalConsoleOptions": "neverOpen",
|
||||||
|
"name": "nodemon start-server",
|
||||||
|
"program": "${workspaceFolder}/src/www",
|
||||||
|
"request": "launch",
|
||||||
|
"restart": true,
|
||||||
|
"runtimeExecutable": "nodemon",
|
||||||
|
"env": {
|
||||||
|
"TRILIUM_ENV": "dev",
|
||||||
|
"TRILIUM_DATA_DIR": "./data"
|
||||||
|
},
|
||||||
|
"skipFiles": ["<node_internals>/**"],
|
||||||
|
"type": "node",
|
||||||
|
"outputCapture": "std"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
26
.vscode/settings.json
vendored
26
.vscode/settings.json
vendored
@@ -1,16 +1,11 @@
|
|||||||
{
|
{
|
||||||
"editor.formatOnSave": false,
|
"editor.formatOnSave": false,
|
||||||
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
"files.eol": "\n",
|
"files.eol": "\n",
|
||||||
|
"typescript.tsdk": "node_modules/typescript/lib",
|
||||||
"i18n-ally.sourceLanguage": "en",
|
"i18n-ally.sourceLanguage": "en",
|
||||||
"i18n-ally.keystyle": "nested",
|
"i18n-ally.keystyle": "nested",
|
||||||
"i18n-ally.localesPaths": [
|
"i18n-ally.localesPaths": ["./src/public/translations", "./translations"],
|
||||||
"apps/server/src/assets/translations",
|
|
||||||
"apps/client/src/translations",
|
|
||||||
"apps/website/public/translations"
|
|
||||||
],
|
|
||||||
"npm.exclude": [
|
|
||||||
"**/dist",
|
|
||||||
],
|
|
||||||
"[jsonc]": {
|
"[jsonc]": {
|
||||||
"editor.defaultFormatter": "vscode.json-language-features"
|
"editor.defaultFormatter": "vscode.json-language-features"
|
||||||
},
|
},
|
||||||
@@ -20,21 +15,8 @@
|
|||||||
"[typescript]": {
|
"[typescript]": {
|
||||||
"editor.defaultFormatter": "vscode.typescript-language-features"
|
"editor.defaultFormatter": "vscode.typescript-language-features"
|
||||||
},
|
},
|
||||||
|
"github-actions.workflows.pinned.workflows": [".github/workflows/nightly.yml"],
|
||||||
"[css]": {
|
"[css]": {
|
||||||
"editor.defaultFormatter": "vscode.css-language-features"
|
"editor.defaultFormatter": "vscode.css-language-features"
|
||||||
},
|
|
||||||
"github-actions.workflows.pinned.workflows": [
|
|
||||||
".github/workflows/nightly.yml"
|
|
||||||
],
|
|
||||||
"typescript.validate.enable": true,
|
|
||||||
"typescript.tsserver.experimental.enableProjectDiagnostics": true,
|
|
||||||
"typescript.tsdk": "node_modules/typescript/lib",
|
|
||||||
"typescript.enablePromptUseWorkspaceTsdk": true,
|
|
||||||
"search.exclude": {
|
|
||||||
"**/node_modules": true,
|
|
||||||
"docs/**/*.html": true,
|
|
||||||
"docs/**/*.png": true,
|
|
||||||
"apps/server/src/assets/doc_notes/**": true,
|
|
||||||
"apps/edit-docs/demo/**": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
5
.vscode/snippets.code-snippets
vendored
5
.vscode/snippets.code-snippets
vendored
@@ -20,10 +20,5 @@
|
|||||||
"scope": "typescript",
|
"scope": "typescript",
|
||||||
"prefix": "jqf",
|
"prefix": "jqf",
|
||||||
"body": ["private $${1:name}!: JQuery<HTMLElement>;"]
|
"body": ["private $${1:name}!: JQuery<HTMLElement>;"]
|
||||||
},
|
|
||||||
"region": {
|
|
||||||
"scope": "css",
|
|
||||||
"prefix": "region",
|
|
||||||
"body": ["/* #region ${1:name} */\n$0\n/* #endregion */"]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
152
CLAUDE.md
152
CLAUDE.md
@@ -1,152 +0,0 @@
|
|||||||
# CLAUDE.md
|
|
||||||
|
|
||||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
Trilium Notes is a hierarchical note-taking application with advanced features like synchronization, scripting, and rich text editing. It's built as a TypeScript monorepo using pnpm, with multiple applications and shared packages.
|
|
||||||
|
|
||||||
## Development Commands
|
|
||||||
|
|
||||||
### Setup
|
|
||||||
- `pnpm install` - Install all dependencies
|
|
||||||
- `corepack enable` - Enable pnpm if not available
|
|
||||||
|
|
||||||
### Running Applications
|
|
||||||
- `pnpm run server:start` - Start development server (http://localhost:8080)
|
|
||||||
- `pnpm run server:start-prod` - Run server in production mode
|
|
||||||
|
|
||||||
### Building
|
|
||||||
- `pnpm run client:build` - Build client application
|
|
||||||
- `pnpm run server:build` - Build server application
|
|
||||||
- `pnpm run electron:build` - Build desktop application
|
|
||||||
|
|
||||||
### Testing
|
|
||||||
- `pnpm test:all` - Run all tests (parallel + sequential)
|
|
||||||
- `pnpm test:parallel` - Run tests that can run in parallel
|
|
||||||
- `pnpm test:sequential` - Run tests that must run sequentially (server, ckeditor5-mermaid, ckeditor5-math)
|
|
||||||
- `pnpm coverage` - Generate coverage reports
|
|
||||||
|
|
||||||
## Architecture Overview
|
|
||||||
|
|
||||||
### Monorepo Structure
|
|
||||||
- **apps/**: Runnable applications
|
|
||||||
- `client/` - Frontend application (shared by server and desktop)
|
|
||||||
- `server/` - Node.js server with web interface
|
|
||||||
- `desktop/` - Electron desktop application
|
|
||||||
- `web-clipper/` - Browser extension for saving web content
|
|
||||||
- Additional tools: `db-compare`, `dump-db`, `edit-docs`
|
|
||||||
|
|
||||||
- **packages/**: Shared libraries
|
|
||||||
- `commons/` - Shared interfaces and utilities
|
|
||||||
- `ckeditor5/` - Custom rich text editor with Trilium-specific plugins
|
|
||||||
- `codemirror/` - Code editor customizations
|
|
||||||
- `highlightjs/` - Syntax highlighting
|
|
||||||
- Custom CKEditor plugins: `ckeditor5-admonition`, `ckeditor5-footnotes`, `ckeditor5-math`, `ckeditor5-mermaid`
|
|
||||||
|
|
||||||
### Core Architecture Patterns
|
|
||||||
|
|
||||||
#### Three-Layer Cache System
|
|
||||||
- **Becca** (Backend Cache): Server-side entity cache (`apps/server/src/becca/`)
|
|
||||||
- **Froca** (Frontend Cache): Client-side mirror of backend data (`apps/client/src/services/froca.ts`)
|
|
||||||
- **Shaca** (Share Cache): Optimized cache for shared/published notes (`apps/server/src/share/`)
|
|
||||||
|
|
||||||
#### Entity System
|
|
||||||
Core entities are defined in `apps/server/src/becca/entities/`:
|
|
||||||
- `BNote` - Notes with content and metadata
|
|
||||||
- `BBranch` - Hierarchical relationships between notes (allows multiple parents)
|
|
||||||
- `BAttribute` - Key-value metadata attached to notes
|
|
||||||
- `BRevision` - Note version history
|
|
||||||
- `BOption` - Application configuration
|
|
||||||
|
|
||||||
#### Widget-Based UI
|
|
||||||
Frontend uses a widget system (`apps/client/src/widgets/`):
|
|
||||||
- `BasicWidget` - Base class for all UI components
|
|
||||||
- `NoteContextAwareWidget` - Widgets that respond to note changes
|
|
||||||
- `RightPanelWidget` - Widgets displayed in the right panel
|
|
||||||
- Type-specific widgets in `type_widgets/` directory
|
|
||||||
|
|
||||||
#### API Architecture
|
|
||||||
- **Internal API**: REST endpoints in `apps/server/src/routes/api/`
|
|
||||||
- **ETAPI**: External API for third-party integrations (`apps/server/src/etapi/`)
|
|
||||||
- **WebSocket**: Real-time synchronization (`apps/server/src/services/ws.ts`)
|
|
||||||
|
|
||||||
### Key Files for Understanding Architecture
|
|
||||||
|
|
||||||
1. **Application Entry Points**:
|
|
||||||
- `apps/server/src/main.ts` - Server startup
|
|
||||||
- `apps/client/src/desktop.ts` - Client initialization
|
|
||||||
|
|
||||||
2. **Core Services**:
|
|
||||||
- `apps/server/src/becca/becca.ts` - Backend data management
|
|
||||||
- `apps/client/src/services/froca.ts` - Frontend data synchronization
|
|
||||||
- `apps/server/src/services/backend_script_api.ts` - Scripting API
|
|
||||||
|
|
||||||
3. **Database Schema**:
|
|
||||||
- `apps/server/src/assets/db/schema.sql` - Core database structure
|
|
||||||
|
|
||||||
4. **Configuration**:
|
|
||||||
- `package.json` - Project dependencies and scripts
|
|
||||||
|
|
||||||
## Note Types and Features
|
|
||||||
|
|
||||||
Trilium supports multiple note types, each with specialized widgets:
|
|
||||||
- **Text**: Rich text with CKEditor5 (markdown import/export)
|
|
||||||
- **Code**: Syntax-highlighted code editing with CodeMirror
|
|
||||||
- **File**: Binary file attachments
|
|
||||||
- **Image**: Image display with editing capabilities
|
|
||||||
- **Canvas**: Drawing/diagramming with Excalidraw
|
|
||||||
- **Mermaid**: Diagram generation
|
|
||||||
- **Relation Map**: Visual note relationship mapping
|
|
||||||
- **Web View**: Embedded web pages
|
|
||||||
- **Doc/Book**: Hierarchical documentation structure
|
|
||||||
|
|
||||||
## Development Guidelines
|
|
||||||
|
|
||||||
### Testing Strategy
|
|
||||||
- Server tests run sequentially due to shared database
|
|
||||||
- Client tests can run in parallel
|
|
||||||
- E2E tests use Playwright for both server and desktop apps
|
|
||||||
- Build validation tests check artifact integrity
|
|
||||||
|
|
||||||
### Scripting System
|
|
||||||
Trilium provides powerful user scripting capabilities:
|
|
||||||
- Frontend scripts run in browser context
|
|
||||||
- Backend scripts run in Node.js context with full API access
|
|
||||||
- Script API documentation available in `docs/Script API/`
|
|
||||||
|
|
||||||
### Internationalization
|
|
||||||
- Translation files in `apps/client/src/translations/`
|
|
||||||
- Supported languages: English, German, Spanish, French, Romanian, Chinese
|
|
||||||
|
|
||||||
### Security Considerations
|
|
||||||
- Per-note encryption with granular protected sessions
|
|
||||||
- CSRF protection for API endpoints
|
|
||||||
- OpenID and TOTP authentication support
|
|
||||||
- Sanitization of user-generated content
|
|
||||||
|
|
||||||
## Common Development Tasks
|
|
||||||
|
|
||||||
### Adding New Note Types
|
|
||||||
1. Create widget in `apps/client/src/widgets/type_widgets/`
|
|
||||||
2. Register in `apps/client/src/services/note_types.ts`
|
|
||||||
3. Add backend handling in `apps/server/src/services/notes.ts`
|
|
||||||
|
|
||||||
### Extending Search
|
|
||||||
- Search expressions handled in `apps/server/src/services/search/`
|
|
||||||
- Add new search operators in search context files
|
|
||||||
|
|
||||||
### Custom CKEditor Plugins
|
|
||||||
- Create new package in `packages/` following existing plugin structure
|
|
||||||
- Register in `packages/ckeditor5/src/plugins.ts`
|
|
||||||
|
|
||||||
### Database Migrations
|
|
||||||
- Add migration scripts in `apps/server/src/migrations/`
|
|
||||||
- Update schema in `apps/server/src/assets/db/schema.sql`
|
|
||||||
|
|
||||||
## Build System Notes
|
|
||||||
- Uses pnpm for monorepo management
|
|
||||||
- Vite for fast development builds
|
|
||||||
- ESBuild for production optimization
|
|
||||||
- pnpm workspaces for dependency management
|
|
||||||
- Docker support with multi-stage builds
|
|
||||||
65
Dockerfile
Normal file
65
Dockerfile
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
# Build stage
|
||||||
|
FROM node:22.13.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
|
||||||
|
|
||||||
|
# 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 webpack && \
|
||||||
|
npm prune --omit=dev && \
|
||||||
|
npm cache clean --force && \
|
||||||
|
cp src/public/app/share.js src/public/app-dist/. && \
|
||||||
|
cp -r src/public/app/doc_notes src/public/app-dist/. && \
|
||||||
|
rm -rf src/public/app/* && \
|
||||||
|
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
|
||||||
|
|
||||||
|
# Runtime stage
|
||||||
|
FROM node:22.13.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
|
||||||
|
|
||||||
|
# Configure container
|
||||||
|
EXPOSE 8080
|
||||||
|
CMD [ "./start-docker.sh" ]
|
||||||
|
HEALTHCHECK --start-period=10s CMD exec gosu node node docker_healthcheck.js
|
||||||
64
Dockerfile.alpine
Normal file
64
Dockerfile.alpine
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
# Build stage
|
||||||
|
FROM node:22.13.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
|
||||||
|
|
||||||
|
# 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 webpack && \
|
||||||
|
npm prune --omit=dev && \
|
||||||
|
npm cache clean --force && \
|
||||||
|
cp src/public/app/share.js src/public/app-dist/. && \
|
||||||
|
cp -r src/public/app/doc_notes src/public/app-dist/. && \
|
||||||
|
rm -rf src/public/app && \
|
||||||
|
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
|
||||||
|
|
||||||
|
# Runtime stage
|
||||||
|
FROM node:22.13.0-alpine
|
||||||
|
|
||||||
|
# Install runtime dependencies
|
||||||
|
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
|
||||||
|
|
||||||
|
# Add application user
|
||||||
|
RUN adduser -s /bin/false node; exit 0
|
||||||
|
|
||||||
|
# Configure container
|
||||||
|
EXPOSE 8080
|
||||||
|
CMD [ "./start-docker.sh" ]
|
||||||
|
HEALTHCHECK --start-period=10s CMD exec su-exec node node docker_healthcheck.js
|
||||||
97
README-ZH_CN.md
Normal file
97
README-ZH_CN.md
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
# 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)
|
||||||
|
|
||||||
|
TriliumNext Notes 是一个层次化的笔记应用程序,专注于建立大型个人知识库。请参阅[屏幕截图](https://triliumnext.github.io/Docs/Wiki/screenshot-tour)以快速了解:
|
||||||
|
|
||||||
|
<a href="https://triliumnext.github.io/Docs/Wiki/screenshot-tour"><img src="https://github.com/TriliumNext/Docs/blob/main/Wiki/images/screenshot.png?raw=true" alt="Trilium Screenshot" width="1000"></a>
|
||||||
|
|
||||||
|
## ⚠️ 为什么选择TriliumNext?
|
||||||
|
|
||||||
|
[原始的Trilium项目目前处于维护模式](https://github.com/zadam/trilium/issues/4620)
|
||||||
|
|
||||||
|
## 🗭 与我们讨论
|
||||||
|
|
||||||
|
欢迎加入我们的官方讨论和社区。我们专注于Trilium的开发,乐于听取您对功能、建议或问题的意见!
|
||||||
|
|
||||||
|
- [Matrix](https://matrix.to/#/#triliumnext:matrix.org)(用于同步讨论)
|
||||||
|
- [Github Discussions](https://github.com/TriliumNext/Notes/discussions)(用于异步讨论)
|
||||||
|
- [Wiki](https://triliumnext.github.io/Docs/)(用于常见操作问题和用户指南)
|
||||||
|
|
||||||
|
上面链接的两个房间是镜像的,所以您可以在任意平台上使用XMPP或者Matrix来和我们交流。
|
||||||
|
|
||||||
|
### 非官方社区
|
||||||
|
|
||||||
|
[Trilium Rocks](https://discord.gg/aqdX9mXX4r)
|
||||||
|
|
||||||
|
## 🎁 特性
|
||||||
|
|
||||||
|
* 笔记可以排列成任意深的树。单个笔记可以放在树中的多个位置(请参阅[克隆](https://triliumnext.github.io/Docs/Wiki/cloning-notes))
|
||||||
|
* 丰富的所见即所得笔记编辑功能,包括带有 Markdown [自动格式化功能的](https://triliumnext.github.io/Docs/Wiki/text-notes#autoformat)表格,图像和[数学公式](https://triliumnext.github.io/Docs/Wiki/text-notes#math-support)
|
||||||
|
* 支持编辑[使用源代码的笔记](https://triliumnext.github.io/Docs/Wiki/code-notes),包括语法高亮显示
|
||||||
|
* 笔记之间快速[导航](https://triliumnext.github.io/Docs/Wiki/note-navigation),全文搜索和[提升笔记](https://triliumnext.github.io/Docs/Wiki/note-hoisting)
|
||||||
|
* 无缝[笔记版本控制](https://triliumnext.github.io/Docs/Wiki/note-revisions)
|
||||||
|
* 笔记[属性](https://triliumnext.github.io/Docs/Wiki/attributes)可用于笔记组织,查询和高级[脚本编写](https://triliumnext.github.io/Docs/Wiki/scripts)
|
||||||
|
* [同步](https://triliumnext.github.io/Docs/Wiki/synchronization)与自托管同步服务器
|
||||||
|
* 有一个[第三方提供的同步服务器托管服务](https://trilium.cc/paid-hosting)
|
||||||
|
* 公开地[分享](https://triliumnext.github.io/Docs/Wiki/sharing)(发布)笔记到互联网
|
||||||
|
* 具有按笔记粒度的强大的[笔记加密](https://triliumnext.github.io/Docs/Wiki/protected-notes)
|
||||||
|
* 使用自带的 Excalidraw 来绘制图表(笔记类型“画布”)
|
||||||
|
* [关系图](https://triliumnext.github.io/Docs/Wiki/relation-map)和[链接图](https://triliumnext.github.io/Docs/Wiki/link-map),用于可视化笔记及其关系
|
||||||
|
* [脚本](https://triliumnext.github.io/Docs/Wiki/scripts) - 请参阅[高级功能展示](https://triliumnext.github.io/Docs/Wiki/advanced-showcases)
|
||||||
|
* 可用于自动化的 [REST API](https://triliumnext.github.io/Docs/Wiki/etapi)
|
||||||
|
* 在拥有超过 10 万条笔记时仍能保持良好的可用性和性能
|
||||||
|
* 针对智能手机和平板电脑进行优化的[用于移动设备的前端](https://triliumnext.github.io/Docs/Wiki/mobile-frontend)
|
||||||
|
* [夜间主题](https://triliumnext.github.io/Docs/Wiki/themes)
|
||||||
|
* [Evernote](https://triliumnext.github.io/Docs/Wiki/evernote-import) 和 [Markdown 导入导出](https://triliumnext.github.io/Docs/Wiki/markdown)功能
|
||||||
|
* 使用[网页剪藏](https://triliumnext.github.io/Docs/Wiki/web-clipper)轻松保存互联网上的内容
|
||||||
|
|
||||||
|
✨ 查看以下第三方资源,获取更多关于TriliumNext的好东西:
|
||||||
|
|
||||||
|
- [awesome-trilium](https://github.com/Nriver/awesome-trilium):提供第三方主题、脚本、插件等资源的列表。
|
||||||
|
- [TriliumRocks!](https://trilium.rocks/):提供教程、指南等更多内容。
|
||||||
|
|
||||||
|
## 🏗 构建
|
||||||
|
|
||||||
|
Trilium 可以用作桌面应用程序(Linux 和 Windows)或服务器(Linux)上托管的 Web 应用程序。虽然有 macOS 版本的桌面应用程序,但它[不受支持](https://triliumnext.github.io/Docs/Wiki/faq#mac-os-support)。
|
||||||
|
|
||||||
|
* 如果要在桌面上使用 Trilium,请从[最新版本](https://github.com/TriliumNext/Notes/releases/latest)下载适用于您平台的二进制版本,解压缩该软件包并运行`trilium`可执行文件。
|
||||||
|
* 如果要在服务器上安装 Trilium,请参考[此页面](https://triliumnext.github.io/Docs/Wiki/server-installation)。
|
||||||
|
* 当前仅支持(测试过)最近发布的 Chrome 和 Firefox 浏览器。
|
||||||
|
|
||||||
|
Trilium 也提供 Flatpak:
|
||||||
|
|
||||||
|
[<img width="240" src="https://flathub.org/assets/badges/flathub-badge-en.png">](https://flathub.org/apps/details/com.github.zadam.trilium)
|
||||||
|
|
||||||
|
## 📝 文档
|
||||||
|
|
||||||
|
[有关文档页面的完整列表,请参见 Wiki。](https://triliumnext.github.io/Docs/)
|
||||||
|
|
||||||
|
* [Wiki 的中文翻译版本](https://github.com/baddate/trilium/wiki/)
|
||||||
|
|
||||||
|
您还可以阅读[个人知识库模式](https://triliumnext.github.io/Docs/Wiki/patterns-of-personal-knowledge),以获取有关如何使用 Trilium 的灵感。
|
||||||
|
|
||||||
|
## 💻 贡献
|
||||||
|
|
||||||
|
|
||||||
|
或者克隆本仓库到本地,并运行
|
||||||
|
|
||||||
|
```shell
|
||||||
|
npm install
|
||||||
|
npm run start-server
|
||||||
|
```
|
||||||
|
|
||||||
|
## 👏 致谢
|
||||||
|
|
||||||
|
* [CKEditor 5](https://github.com/ckeditor/ckeditor5) - 市面上最好的所见即所得编辑器,拥有互动性强且聆听能力强的团队
|
||||||
|
* [FancyTree](https://github.com/mar10/fancytree) - 一个非常丰富的关于树的库,强大到没有对手。没有它,Trilium Notes 将不会如此。
|
||||||
|
* [CodeMirror](https://github.com/codemirror/CodeMirror) - 支持大量语言的代码编辑器
|
||||||
|
* [jsPlumb](https://github.com/jsplumb/jsplumb) - 强大的可视化连接库。用于[关系图](https://triliumnext.github.io/Docs/Wiki/relation-map)和[链接图](https://triliumnext.github.io/Docs/Wiki/link-map)
|
||||||
|
|
||||||
|
## 🤝 捐赠
|
||||||
|
|
||||||
|
你可以通过 GitHub Sponsors,[PayPal](https://paypal.me/za4am) 或者比特币 (bitcoin:bc1qv3svjn40v89mnkre5vyvs2xw6y8phaltl385d2) 来捐赠。
|
||||||
|
|
||||||
|
## 🔑 许可证
|
||||||
|
|
||||||
|
本程序是自由软件:你可以再发布本软件和/或修改本软件,只要你遵循 Free Software Foundation 发布的 GNU Affero General Public License 的第三版或者任何(由你选择)更晚的版本。
|
||||||
106
README.es.md
Normal file
106
README.es.md
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
# 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)
|
||||||
|
|
||||||
|
TriliumNext Notes es una aplicación de toma de notas jerárquicas multi-plataforma y de código libre con un enfoque en la construcción de grandes bases de conocimiento personal.
|
||||||
|
|
||||||
|
Vea estas [capturas de pantalla](https://triliumnext.github.io/Docs/Wiki/screenshot-tour) para un vistazo rápido:
|
||||||
|
|
||||||
|
<a href="https://triliumnext.github.io/Docs/Wiki/screenshot-tour"><img src="https://github.com/TriliumNext/Docs/blob/main/Wiki/images/screenshot.png?raw=true" alt="Trilium Screenshot" width="1000"></a>
|
||||||
|
|
||||||
|
## ⚠️ ¿Por qué usar TriliumNext?
|
||||||
|
|
||||||
|
[El proyecto Trilium original está en modo de mantenimiento](https://github.com/zadam/trilium/issues/4620)
|
||||||
|
|
||||||
|
### ¿Cómo migrar desde Trilium?
|
||||||
|
|
||||||
|
No hay pasos de migración especiales para migrar de una instancia de zadam/Trilium a una instancia de TriliumNext/Notes. Simplemente actualice su instancia de Trilium a la última versión e [instale TriliumNext/Notes como de costumbre](#-Instalación)
|
||||||
|
|
||||||
|
## 💬 Discuta con nosotros
|
||||||
|
|
||||||
|
Siéntase libre de unirse a nuestras conversaciones oficiales. ¡Nos encantaría escuchar de las características, sugerencias o problemas que pueda tener!
|
||||||
|
|
||||||
|
- [Matrix](https://matrix.to/#/#triliumnext:matrix.org) (Para discusiones síncronas)
|
||||||
|
- La sala `General` es replicada a [XMPP](xmpp:discuss@trilium.thisgreat.party?join)
|
||||||
|
- [Discusiones de GitHub](https://github.com/TriliumNext/Notes/discussions) (Para discusiones asíncronas)
|
||||||
|
- [Wiki](https://triliumnext.github.io/Docs/) (Para preguntas frecuentes y guías de usuario)
|
||||||
|
|
||||||
|
## 🎁 Características
|
||||||
|
|
||||||
|
- Las notas pueden ser acomodadas en un árbol de profundidad arbitraria. Una sola nota puede ser colocada en múltiples lugares del árbol (vea [clonar](https://triliumnext.github.io/Docs/Wiki/cloning-notes)
|
||||||
|
- Edición de notas WYSIWYG enriquecida que incluye, por ejemplo, tablas, imágenes y [matemáticas](https://triliumnext.github.io/Docs/Wiki/text-notes) con [autoformato](https://triliumnext.github.io/Docs/Wiki/text-notes#autoformat) markdown
|
||||||
|
- Soporte para editar [notas con código fuente](https://triliumnext.github.io/Docs/Wiki/code-notes), incluyendo resaltado de sintaxis
|
||||||
|
- Rápida y sencilla [navegación entre notas](https://triliumnext.github.io/Docs/Wiki/note-navigation), búsqueda de texto completo y [elevación de notas](https://triliumnext.github.io/Docs/Wiki/note-hoisting)
|
||||||
|
- [Versionado de notas](https://triliumnext.github.io/Docs/Wiki/note-revisions) sutil
|
||||||
|
- Los [atributos](https://triliumnext.github.io/Docs/Wiki/attributes) de las notas pueden utilizarse para organización, realizar consultas y [scripts](https://triliumnext.github.io/Docs/Wiki/scripts) avanzados
|
||||||
|
- [Sincronización](https://triliumnext.github.io/Docs/Wiki/synchronization) con servidor de sincronización propio
|
||||||
|
- existe un [servicio de terceros para alojar el servidor de sincronización](https://trilium.cc/paid-hosting)
|
||||||
|
- [Compartir](https://triliumnext.github.io/Docs/Wiki/sharing) (publicar) notas al Internet público
|
||||||
|
- Fuerte [encriptación de notas](https://triliumnext.github.io/Docs/Wiki/protected-notes) con granularidad para cada nota
|
||||||
|
- Esbozo de diagramas con Excalidraw incorporado (tipo de nota «canvas»)
|
||||||
|
- [Mapas de relaciones](<https://triliumnext.github.io/Docs/Wiki/relation-map>) y [mapas de enlaces](https://triliumnext.github.io/Docs/Wiki/link-map) para visualizar las notas y sus relaciones
|
||||||
|
- [Scripting](https://triliumnext.github.io/Docs/Wiki/scripts) - vea [casos de uso avanzados](https://triliumnext.github.io/Docs/Wiki/advanced-showcases)
|
||||||
|
- [REST API](https://triliumnext.github.io/Docs/Wiki/etapi) para automatización
|
||||||
|
- Escala bien tanto en uso como en rendimiento a partir de 100,000 notas
|
||||||
|
- [Interfaz móvil](https://triliumnext.github.io/Docs/Wiki/mobile-frontend) optimizada para teléfonos inteligentes y tabletas
|
||||||
|
- [Tema nocturno](https://triliumnext.github.io/Docs/Wiki/themes)
|
||||||
|
- Importación y exportación de [Evernote](https://triliumnext.github.io/Docs/Wiki/evernote-import) y [Markdown](https://triliumnext.github.io/Docs/Wiki/markdown)
|
||||||
|
- [Web Clipper](https://triliumnext.github.io/Docs/Wiki/web-clipper) para guardar fácilmente contenido web
|
||||||
|
|
||||||
|
✨ Consulte los/las siguientes recursos/comunidades de terceros para obtener más información sobre complementos para TriliumNext:
|
||||||
|
|
||||||
|
- [awesome-trilium](https://github.com/Nriver/awesome-trilium) para temas, scripts, plugins y más de terceros.
|
||||||
|
- [TriliumRocks!](https://trilium.rocks/) para tutoriales, guías y mucho más.
|
||||||
|
|
||||||
|
## 🏗 Instalación
|
||||||
|
|
||||||
|
### Escritorio
|
||||||
|
|
||||||
|
Para usar TriliumNext en su máquina de escritorio (Linux, MacOS y Windows) tiene algunas opciones:
|
||||||
|
|
||||||
|
- Descargue la versión binaria para su plataforma desde la [página de lanzamientos](https://github.com/TriliumNext/Notes/releases/latest), descomprima el paquete y ejecute el ejecutable `trilium`.
|
||||||
|
- Acceda a TriliumNext a través de la interfaz web de una instalación de servidor (ver más abajo)
|
||||||
|
- Actualmente solo las últimas versiones de Chrome y Firefox son compatibles (y están probadas).
|
||||||
|
- (Próximamente) TriliumNext también se proporcionará como un Flatpak
|
||||||
|
|
||||||
|
### Móvil
|
||||||
|
|
||||||
|
Para usar TriliumNext en un dispositivo móvil:
|
||||||
|
|
||||||
|
- Utilice un navegador web móvil para acceder a la interfaz móvil de una instalación de servidor (ver más abajo)
|
||||||
|
- El uso de una aplicación móvil aún no está soportado ([vea aquí](https://github.com/TriliumNext/Notes/issues/72)) para seguir las mejoras móviles.
|
||||||
|
|
||||||
|
### Servidor
|
||||||
|
|
||||||
|
Para instalar TriliumNext en su servidor (incluyendo vía Docker desde [Dockerhub](https://hub.docker.com/r/triliumnext/notes)) siga la [documentación de instalación de servidor](https://triliumnext.github.io/Docs/Wiki/server-installation).
|
||||||
|
|
||||||
|
## 📝 Documentación
|
||||||
|
|
||||||
|
[Vea la Wiki para la lista completa de páginas de documentación.](https://triliumnext.github.io/Docs)
|
||||||
|
|
||||||
|
También puede leer [Patrones para una base de conocimiento personal](https://triliumnext.github.io/Docs/Wiki/patterns-of-personal-knowledge) para obtener un poco de inspiración de como podría usar TriliumNext.
|
||||||
|
|
||||||
|
## 💻 Contribuir
|
||||||
|
|
||||||
|
Clone localmente y ejecute
|
||||||
|
|
||||||
|
```shell
|
||||||
|
npm install
|
||||||
|
npm run start-server
|
||||||
|
```
|
||||||
|
|
||||||
|
## 👏 Reconocimientos
|
||||||
|
|
||||||
|
- [CKEditor 5](https://github.com/ckeditor/ckeditor5) - el mejor editor WYSIWYG en el mercado, equipo muy interactivo y atento
|
||||||
|
- [FancyTree](https://github.com/mar10/fancytree) - biblioteca de árbol muy rica en funciones sin competencia real. TriliumNext Notes no sería lo mismo sin esta.
|
||||||
|
- [CodeMirror](https://github.com/codemirror/CodeMirror) - editor de código con soporte para una gran cantidad de lenguajes
|
||||||
|
- [jsPlumb](https://github.com/jsplumb/jsplumb) - biblioteca de conectividad visual sin competencia. Usado en [mapas de relación](https://triliumnext.github.io/Docs/Wiki/Relation-map) y [mapas de enlace](https://triliumnext.github.io/Docs/Wiki/Link-map)
|
||||||
|
|
||||||
|
## 🤝 Soporte
|
||||||
|
|
||||||
|
Puede apoyar al desarrollador original de Trilium usando GitHub Sponsors, [PayPal](https://paypal.me/za4am) o Bitcoin (bitcoin:bc1qv3svjn40v89mnkre5vyvs2xw6y8phaltl385d2).
|
||||||
|
Apoyo para la organización TriliumNext será posible en un futuro próximo.
|
||||||
|
|
||||||
|
## 🔑 Licencia
|
||||||
|
|
||||||
|
Este programa es software libre: puede redistribuirlo y/o modificarlo bajo los términos de la Licencia Pública General de Affero GNU publicada por la Free Software Foundation, ya sea la versión 3 de la Licencia, o (a su elección) cualquier versión posterior.
|
||||||
93
README.it.md
Normal file
93
README.it.md
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
# 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)
|
||||||
|
|
||||||
|
TriliumNext Notes è un'applicazione per appunti ad organizzazione gerarchica, studiata per la costruzione di archivi di conoscenza personali di grandi dimensioni.
|
||||||
|
|
||||||
|
Vedi [fotografie](https://triliumnext.github.io/Docs/Wiki/screenshot-tour) per una panoramica veloce:
|
||||||
|
|
||||||
|
<a href="https://triliumnext.github.io/Docs/Wiki/screenshot-tour"><img src="https://github.com/TriliumNext/Docs/blob/main/Wiki/images/screenshot.png?raw=true" alt="Trilium Screenshot" width="1000"></a>
|
||||||
|
|
||||||
|
## ⚠️ Perchè TriliumNext?
|
||||||
|
[Il progetto originale Trilium è in modalità di manutenzione](https://github.com/zadam/trilium/issues/4620)
|
||||||
|
|
||||||
|
## 🗭 Discuti con noi
|
||||||
|
Sentiti libero di unirti alle nostre discussioni ufficiali e alla nostra comunità. Siamo concentrati sullo sviluppo di Trilium e ci piacerebbe sapere quali funzioni, suggerimenti o eventuali problemi hai!
|
||||||
|
|
||||||
|
- [Matrix](https://matrix.to/#/#triliumnext:matrix.org) (Per discussioni sincrone)
|
||||||
|
- [Discussioni Github](https://github.com/TriliumNext/Notes/discussions) (Per discussioni asincrone)
|
||||||
|
- [Wiki](https://triliumnext.github.io/Docs/) (Per le domande più comuni e le guide per l'utente)
|
||||||
|
|
||||||
|
Le due stanze linkate sopra sono connesse e contengono gli stessi messaggi, quindi puoi usare XMPP o Matrix da qualsiasi client tu preferisca, praticamente su qualsiasi piattaforma!
|
||||||
|
### Comunità non ufficiali
|
||||||
|
|
||||||
|
[Trilium Rocks](https://discord.gg/aqdX9mXX4r)
|
||||||
|
## 🎁 Funzionalità
|
||||||
|
|
||||||
|
* Gli appunti possono essere organizzati in un albero di profondità arbitraria. Un singolo appunto può essere collocato in più posti nell'albero (vedi [clonazione](https://triliumnext.github.io/Docs/Wiki/cloning-notes))
|
||||||
|
* Ricco editor visuale (WYSIWYG), con supporto -tra l'altro- per tabelle, immagini ed [espressioni matematiche](https://triliumnext.github.io/Docs/Wiki/text-notes#math-support) e con [formattazione automatica](https://triliumnext.github.io/Docs/Wiki/text-notes#autoformat) per markdown
|
||||||
|
* Supporto per la modifica di [appunti con codice sorgente](https://triliumnext.github.io/Docs/Wiki/code-notes), con evidenziazione della sintassi
|
||||||
|
* [Navigazione veloce](https://triliumnext.github.io/Docs/Wiki/note-navigation) tra gli appunti, ricerca testuale completa e [fissaggio degli appunti](https://triliumnext.github.io/Docs/Wiki/note-hoisting)
|
||||||
|
* Supporto integrato ed automatico per le [revisioni degli appunti](https://triliumnext.github.io/Docs/Wiki/note-revisions)
|
||||||
|
* Gli [attributi](https://triliumnext.github.io/Docs/Wiki/attributes) degli appunti possono essere utilizzati per l'organizzazione, per l'interrogazione e per lo scripting avanzato (prorgrammazione).
|
||||||
|
* [Sincronizzazione](https://triliumnext.github.io/Docs/Wiki/synchronization) con un server di sincronizzazione auto-ospitato
|
||||||
|
* c'è un [servizio di terze parti per ospitare server di sincronizzazione](https://trilium.cc/paid-hosting)
|
||||||
|
* [Condivisione](https://triliumnext.github.io/Docs/Wiki/sharing) (pubblicazione) di appunti sull'internet pubblico
|
||||||
|
* Robusta [crittografia](https://triliumnext.github.io/Docs/Wiki/protected-notes) configurabile singolarmente per ogni appunto
|
||||||
|
* Disegno di diagrammi con Excalidraw (tipo di appunto "canvas")
|
||||||
|
* [Mappe relazionali](https://triliumnext.github.io/Docs/Wiki/relation-map) e [mappe di collegamenti](https://triliumnext.github.io/Docs/Wiki/link-map) per visualizzare gli appunti e le loro relazioni
|
||||||
|
* [Scripting](https://triliumnext.github.io/Docs/Wiki/scripts) - vedi [Esempi avanzati](https://triliumnext.github.io/Docs/Wiki/advanced-showcases)
|
||||||
|
* [API REST](https://triliumnext.github.io/Docs/Wiki/etapi) per l'automazione
|
||||||
|
* Si adatta bene sia in termini di usabilità che di prestazioni fino ad oltre 100 000 appunti
|
||||||
|
* Interfaccia utente ottimizzata per il [mobile](https://triliumnext.github.io/Docs/Wiki/mobile-frontend) (smartphone e tablet)
|
||||||
|
* [Tema Notturno](https://triliumnext.github.io/Docs/Wiki/themes)
|
||||||
|
* Supporto per importazione ed esportazione da e per [Evernote](https://triliumnext.github.io/Docs/Wiki/evernote-import) e [Markdown import](https://triliumnext.github.io/Docs/Wiki/markdown)
|
||||||
|
* [Web Clipper](https://triliumnext.github.io/Docs/Wiki/web-clipper) per il salvataggio facile di contenuti web
|
||||||
|
|
||||||
|
✨ Dai un'occhiata alle seguenti risorse di terze parti per scoprire altre bellezze legate a TriliumNext:
|
||||||
|
|
||||||
|
-[awesome-trilium](https://github.com/Nriver/awesome-trilium) per temi, script, plugin e altro di terze parti.
|
||||||
|
- [TriliumRocks!](https://trilium.rocks/) per tutorial, guide e molto altro.
|
||||||
|
## 🏗 Rilasci
|
||||||
|
|
||||||
|
|
||||||
|
Trilium è fornito come applicazione desktop (Linux e Windows) o come applicazione web ospitata sul tuo server (Linux). La versione desktop per Mac OS è disponibile, ma [non è supportata](https://triliumnext.github.io/Docs/Wiki/faq#mac-os-support).
|
||||||
|
|
||||||
|
* Se vuoi usare Trilium sul tuo desktop, scarica il rilascio binario per la tua piattaforma dall'[ultimo rilascio](https://github.com/TriliumNext/Notes/releases/latest), decomprimi l'archivio e avvia l'eseguibile ```trilium```.
|
||||||
|
* Se vuoi installare Trilium su un server, segui [questa pagina](https://triliumnext.github.io/Docs/Wiki/server-installation).
|
||||||
|
* Per ora solo Chrome e Firefox sono i browser supportati (testati).
|
||||||
|
|
||||||
|
TriliumNext sarà fornito anche come Flatpak:
|
||||||
|
|
||||||
|
<img width="240" src="https://flathub.org/assets/badges/flathub-badge-en.png">
|
||||||
|
|
||||||
|
## 📝 Documentazione
|
||||||
|
|
||||||
|
[Vedi la wiki per una lista completa delle pagine di documentazione.](https://triliumnext.github.io/Docs/)
|
||||||
|
|
||||||
|
Puoi anche leggere ["Patterns of personal knowledge base"](https://triliumnext.github.io/Docs/Wiki/patterns-of-personal-knowledge) per avere un'ispirazione su come potresti utilizzare Trilium.
|
||||||
|
|
||||||
|
## 💻 Contribuire
|
||||||
|
|
||||||
|
Clona localmente ed esegui
|
||||||
|
|
||||||
|
```shell
|
||||||
|
npm install
|
||||||
|
npm run start-server
|
||||||
|
```
|
||||||
|
|
||||||
|
## 👏 Riconoscimenti
|
||||||
|
|
||||||
|
* [CKEditor 5](https://github.com/ckeditor/ckeditor5) - miglior editor visuale (WYSIWYG) sul mercato, squadra di sviluppo attenta e reattiva
|
||||||
|
* [FancyTree](https://github.com/mar10/fancytree) - libreria per alberi molto ricca di funzionalità, senza pari. Trilium Notes non sarebbe lo stesso senza di essa.
|
||||||
|
* [CodeMirror](https://github.com/codemirror/CodeMirror) - editor di codice con supporto per un'enorme quantità di linguaggi.
|
||||||
|
* [jsPlumb](https://github.com/jsplumb/jsplumb) - libreria per la connettività visuale senza pari. Utilizzata per [mappe relazionali](https://triliumnext.github.io/Docs/Wiki/relation-map) e [mappe di collegamenti](https://triliumnext.github.io/Docs/Wiki/link-map).
|
||||||
|
|
||||||
|
## 🤝 Supporto
|
||||||
|
|
||||||
|
Puoi sostenere lo sviluppatore originale di Trilium utilizzando gli sponsor di GitHub, [PayPal](https://paypal.me/za4am) o Bitcoin (bitcoin:bc1qv3svjn40v89mnkre5vyvs2xw6y8phaltl385d2).
|
||||||
|
Il supporto all'organizzazione TriliumNext sarà possibile nel prossimo futuro.
|
||||||
|
|
||||||
|
## 🔑 Licenza
|
||||||
|
|
||||||
|
Questo programma è software libero: è possibile redistribuirlo e/o modificarlo nei termini della GNU Affero General Public License come pubblicata dalla Free Software Foundation, sia la versione 3 della Licenza, o (a propria scelta) qualsiasi versione successiva.
|
||||||
73
README.ja.md
Normal file
73
README.ja.md
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
# 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)
|
||||||
|
|
||||||
|
Trilium Notes は、大規模な個人知識ベースの構築に焦点を当てた、階層型ノートアプリケーションです。概要は[スクリーンショット](https://triliumnext.github.io/Docs/Wiki/screenshot-tour)をご覧ください:
|
||||||
|
|
||||||
|
<a href="https://triliumnext.github.io/Docs/Wiki/screenshot-tour"><img src="https://raw.githubusercontent.com/wiki/zadam/trilium/images/screenshot.png" alt="Trilium Screenshot" width="1000"></a>
|
||||||
|
|
||||||
|
## 🎁 特徴
|
||||||
|
|
||||||
|
* ノートは、任意の深さのツリーに配置できます。単一のノートをツリー内の複数の場所に配置できます ([cloning](https://triliumnext.github.io/Docs/Wiki/cloning-notes) を参照)
|
||||||
|
* マークダウン[オートフォーマット](https://triliumnext.github.io/Docs/Wiki/text-notes#autoformat)による、表、画像、[数学](https://triliumnext.github.io/Docs/Wiki/text-notes#math-support)などの豊富な WYSIWYG ノート編集機能
|
||||||
|
* シンタックスハイライトを含む[ソースコード付きノート](https://triliumnext.github.io/Docs/Wiki/code-notes)の編集をサポート
|
||||||
|
* [ノート間のナビゲーション](https://triliumnext.github.io/Docs/Wiki/note-navigation)、全文検索、[ノートホイスト](https://triliumnext.github.io/Docs/Wiki/note-hoisting)が高速かつ簡単に行えます
|
||||||
|
* シームレスな[ノートのバージョン管理](https://triliumnext.github.io/Docs/Wiki/note-revisions)
|
||||||
|
* ノート[属性](https://triliumnext.github.io/Docs/Wiki/Attributes)は、ノート整理、クエリ、高度な[スクリプト](https://triliumnext.github.io/Docs/Wiki/scripts)に使用できます
|
||||||
|
* 自己ホスト型同期サーバーとの[同期](https://triliumnext.github.io/Docs/Wiki/synchronization)
|
||||||
|
* [同期サーバーをホストするサードパーティ・サービス](https://trilium.cc/paid-hosting)があります
|
||||||
|
* 公開インターネットへのノートの[共有](https://triliumnext.github.io/Docs/Wiki/sharing)(公開)
|
||||||
|
* ノートごとの粒度を持つ強力な[ノート暗号化](https://triliumnext.github.io/Docs/Wiki/protected-notes)
|
||||||
|
* 組み込みの Excalidraw を使用した図のスケッチ (ノート タイプ"キャンバス")
|
||||||
|
* ノートとその関係を可視化するための[関係図](https://triliumnext.github.io/Docs/Wiki/relation-map)と[リンクマップ](https://triliumnext.github.io/Docs/Wiki/link-map)
|
||||||
|
* [スクリプティング](https://triliumnext.github.io/Docs/Wiki/scripts) - [高度なショーケース](https://triliumnext.github.io/Docs/Wiki/advanced-showcases)を参照
|
||||||
|
* 自動化のための [REST API](https://triliumnext.github.io/Docs/Wiki/etapi)
|
||||||
|
* ユーザビリティとパフォーマンスの両方で 100 000 ノート以上に拡張可能
|
||||||
|
* スマートフォンとタブレット向けのタッチ最適化[モバイルフロントエンド](https://triliumnext.github.io/Docs/Wiki/mobile-frontend)
|
||||||
|
* [ナイトテーマ](https://triliumnext.github.io/Docs/Wiki/themes)
|
||||||
|
* [Evernote](https://triliumnext.github.io/Docs/Wiki/evernote-import) と [Markdown のインポートとエクスポート](https://triliumnext.github.io/Docs/Wiki/Markdown)
|
||||||
|
* Web コンテンツを簡単に保存するための [Web クリッパー](https://triliumnext.github.io/Docs/Wiki/web-clipper)
|
||||||
|
|
||||||
|
サードパーティのテーマ、スクリプト、プラグインなどは、 [awesome-trilium](https://github.com/Nriver/awesome-trilium) をチェックしてください。
|
||||||
|
|
||||||
|
## 🏗 ビルド
|
||||||
|
|
||||||
|
Trilium は、デスクトップアプリケーション(Linux、Windows)またはサーバー上でホストされるウェブアプリケーション(Linux)として提供されます。 Mac OS のデスクトップビルドも利用可能ですが、 [unsupported](https://triliumnext.github.io/Docs/Wiki/faq#mac-os-support) となっています。
|
||||||
|
|
||||||
|
* デスクトップで Trilium を使用したい場合は、 [latest release](https://github.com/TriliumNext/Notes/releases/latest) からお使いのプラットフォームのバイナリリリースをダウンロードし、パッケージを解凍して ``trilium`` の実行ファイルを実行してください。
|
||||||
|
* サーバーに Trilium をインストールする場合は、[このページ](https://triliumnext.github.io/Docs/Wiki/server-installation)に従ってください。
|
||||||
|
* 現在、対応(動作確認)しているブラウザは、最近の Chrome と Firefox のみです。
|
||||||
|
|
||||||
|
Trilium は Flatpak としても提供されます:
|
||||||
|
|
||||||
|
[<img width="240" src="https://flathub.org/assets/badges/flathub-badge-en.png">](https://flathub.org/apps/details/com.github.zadam.trilium)
|
||||||
|
|
||||||
|
## 📝 ドキュメント
|
||||||
|
|
||||||
|
[ドキュメントページの全リストはwikiをご覧ください。](https://triliumnext.github.io/Docs/)
|
||||||
|
|
||||||
|
また、[個人的な知識基盤のパターン](https://triliumnext.github.io/Docs/Wiki/patterns-of-personal-knowledge)を読むと、 Trilium の使い方のヒントを得ることができます。
|
||||||
|
|
||||||
|
## 💻 コントリビュート
|
||||||
|
|
||||||
|
または、ローカルにクローンして実行
|
||||||
|
|
||||||
|
```shell
|
||||||
|
npm install
|
||||||
|
npm run start-server
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📢 シャウトアウト
|
||||||
|
|
||||||
|
* [CKEditor 5](https://github.com/ckeditor/ckeditor5) - 市場で最高の WYSIWYG エディター、非常にインタラクティブで聞き上手なチーム
|
||||||
|
* [FancyTree](https://github.com/mar10/fancytree) - 真の競争相手がいない、非常に機能豊富なツリーライブラリです。 Trilium Notes は、これなしでは成り立たないでしょう。
|
||||||
|
* [CodeMirror](https://github.com/codemirror/CodeMirror) - 膨大な数の言語をサポートするコードエディタ
|
||||||
|
* [jsPlumb](https://github.com/jsplumb/jsplumb) - 競合のないビジュアルコネクティビティライブラリです。[関係図](https://triliumnext.github.io/Docs/Wiki/relation-map)、[リンク図](https://triliumnext.github.io/Docs/Wiki/link-map)で使用。
|
||||||
|
|
||||||
|
## 🤝 サポート
|
||||||
|
|
||||||
|
GitHub スポンサー、[PayPal](https://paypal.me/za4am)もしくは Bitcoin (bitcoin:bc1qv3svjn40v89mnkre5vyvs2xw6y8phaltl385d2) にて Trilium をサポートすることができます。
|
||||||
|
|
||||||
|
## 🔑 ライセンス
|
||||||
|
|
||||||
|
このプログラムはフリーソフトウェアです:フリーソフトウェア財団が発行した GNU Affero General Public License のバージョン3、またはそれ以降のバージョンのいずれかに従って、再配布および/または改変することができます。
|
||||||
202
README.md
202
README.md
@@ -1,218 +1,126 @@
|
|||||||
<div align="center">
|
# TriliumNext Notes
|
||||||
<sup>Special thanks to:</sup><br />
|
|
||||||
<a href="https://go.warp.dev/Trilium" target="_blank">
|
|
||||||
<img alt="Warp sponsorship" width="400" src="https://github.com/warpdotdev/brand-assets/blob/main/Github/Sponsor/Warp-Github-LG-03.png"><br />
|
|
||||||
Warp, built for coding with multiple AI agents<br />
|
|
||||||
</a>
|
|
||||||
<sup>Available for macOS, Linux and Windows</sup>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr />
|
 
|
||||||
|
|
||||||
# Trilium Notes
|
[English](./README.md) | [Chinese](./README-ZH_CN.md) | [Russian](./README.ru.md) | [Japanese](./README.ja.md) | [Italian](./README.it.md) | [Spanish](./README.es.md)
|
||||||
|
|
||||||
 
|
TriliumNext Notes is an open-source, cross-platform hierarchical note taking application with focus on building large personal knowledge bases.
|
||||||

|
|
||||||

|
|
||||||
[](https://app.relative-ci.com/projects/Di5q7dz9daNDZ9UXi0Bp) [](https://hosted.weblate.org/engage/trilium/)
|
|
||||||
|
|
||||||
[English](./README.md) | [Chinese (Simplified)](./docs/README-ZH_CN.md) | [Chinese (Traditional)](./docs/README-ZH_TW.md) | [Russian](./docs/README-ru.md) | [Japanese](./docs/README-ja.md) | [Italian](./docs/README-it.md) | [Spanish](./docs/README-es.md)
|
|
||||||
|
|
||||||
Trilium Notes is a free and open-source, cross-platform hierarchical note taking application with focus on building large personal knowledge bases.
|
|
||||||
|
|
||||||
See [screenshots](https://triliumnext.github.io/Docs/Wiki/screenshot-tour) for quick overview:
|
See [screenshots](https://triliumnext.github.io/Docs/Wiki/screenshot-tour) for quick overview:
|
||||||
|
|
||||||
<a href="https://triliumnext.github.io/Docs/Wiki/screenshot-tour"><img src="./docs/app.png" alt="Trilium Screenshot" width="1000"></a>
|
<a href="https://triliumnext.github.io/Docs/Wiki/screenshot-tour"><img src="https://github.com/TriliumNext/Docs/blob/main/Wiki/images/screenshot.png?raw=true" alt="Trilium Screenshot" width="1000"></a>
|
||||||
|
|
||||||
## ⏬ Download
|
## ⚠️ Why TriliumNext?
|
||||||
- [Latest release](https://github.com/TriliumNext/Trilium/releases/latest) – stable version, recommended for most users.
|
|
||||||
- [Nightly build](https://github.com/TriliumNext/Trilium/releases/tag/nightly) – unstable development version, updated daily with the latest features and fixes.
|
|
||||||
|
|
||||||
## 📚 Documentation
|
[The original Trilium project is in maintenance mode](https://github.com/zadam/trilium/issues/4620)
|
||||||
|
|
||||||
**Visit our comprehensive documentation at [docs.triliumnotes.org](https://docs.triliumnotes.org/)**
|
### Migrating from Trilium?
|
||||||
|
|
||||||
Our documentation is available in multiple formats:
|
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)
|
||||||
- **Online Documentation**: Browse the full documentation at [docs.triliumnotes.org](https://docs.triliumnotes.org/)
|
|
||||||
- **In-App Help**: Press `F1` within Trilium to access the same documentation directly in the application
|
|
||||||
- **GitHub**: Navigate through the [User Guide](./docs/User%20Guide/User%20Guide/) in this repository
|
|
||||||
|
|
||||||
### Quick Links
|
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.
|
||||||
- [Getting Started Guide](https://docs.triliumnotes.org/)
|
|
||||||
- [Installation Instructions](./docs/User%20Guide/User%20Guide/Installation%20&%20Setup/Server%20Installation.md)
|
## 💬 Discuss with us
|
||||||
- [Docker Setup](./docs/User%20Guide/User%20Guide/Installation%20&%20Setup/Server%20Installation/1.%20Installing%20the%20server/Using%20Docker.md)
|
|
||||||
- [Upgrading TriliumNext](./docs/User%20Guide/User%20Guide/Installation%20%26%20Setup/Upgrading%20TriliumNext.md)
|
Feel free to join our official conversations. We would love to hear what features, suggestions, or issues you may have!
|
||||||
- [Basic Concepts and Features](./docs/User%20Guide/User%20Guide/Basic%20Concepts%20and%20Features/Notes.md)
|
|
||||||
- [Patterns of Personal Knowledge Base](https://triliumnext.github.io/Docs/Wiki/patterns-of-personal-knowledge)
|
- [Matrix](https://matrix.to/#/#triliumnext:matrix.org) (For synchronous discussions)
|
||||||
|
- The `General` Matrix room is also bridged to [XMPP](xmpp:discuss@trilium.thisgreat.party?join)
|
||||||
|
- [Github Discussions](https://github.com/TriliumNext/Notes/discussions) (For Asynchronous discussions)
|
||||||
|
- [Wiki](https://triliumnext.github.io/Docs/) (For common how-to questions and user guides)
|
||||||
|
|
||||||
## 🎁 Features
|
## 🎁 Features
|
||||||
|
|
||||||
* Notes can be arranged into arbitrarily deep tree. Single note can be placed into multiple places in the tree (see [cloning](https://triliumnext.github.io/Docs/Wiki/cloning-notes))
|
* Notes can be arranged into arbitrarily deep tree. Single note can be placed into multiple places in the tree (see [cloning](https://triliumnext.github.io/Docs/Wiki/cloning-notes))
|
||||||
* Rich WYSIWYG note editor including e.g. tables, images and [math](https://triliumnext.github.io/Docs/Wiki/text-notes) with markdown [autoformat](https://triliumnext.github.io/Docs/Wiki/text-notes#autoformat)
|
* Rich WYSIWYG note editing including e.g. tables, images and [math](https://triliumnext.github.io/Docs/Wiki/text-notes) with markdown [autoformat](https://triliumnext.github.io/Docs/Wiki/text-notes#autoformat)
|
||||||
* Support for editing [notes with source code](https://triliumnext.github.io/Docs/Wiki/code-notes), including syntax highlighting
|
* Support for editing [notes with source code](https://triliumnext.github.io/Docs/Wiki/code-notes), including syntax highlighting
|
||||||
* 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)
|
* 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)
|
* 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)
|
* 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)
|
||||||
* UI available in English, German, Spanish, French, Romanian, and Chinese (simplified and traditional)
|
|
||||||
* Direct [OpenID and TOTP integration](./docs/User%20Guide/User%20Guide/Installation%20%26%20Setup/Server%20Installation/Multi-Factor%20Authentication.md) for more secure login
|
|
||||||
* [Synchronization](https://triliumnext.github.io/Docs/Wiki/synchronization) with self-hosted sync server
|
* [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)
|
* 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
|
* [Sharing](https://triliumnext.github.io/Docs/Wiki/sharing) (publishing) notes to public internet
|
||||||
* Strong [note encryption](https://triliumnext.github.io/Docs/Wiki/protected-notes) with per-note granularity
|
* Strong [note encryption](https://triliumnext.github.io/Docs/Wiki/protected-notes) with per-note granularity
|
||||||
* Sketching diagrams, based on [Excalidraw](https://excalidraw.com/) (note type "canvas")
|
* Sketching diagrams with built-in Excalidraw (note type "canvas")
|
||||||
* [Relation maps](https://triliumnext.github.io/Docs/Wiki/relation-map) and [link maps](https://triliumnext.github.io/Docs/Wiki/link-map) for visualizing notes and their relations
|
* [Relation maps](https://triliumnext.github.io/Docs/Wiki/relation-map) and [link maps](https://triliumnext.github.io/Docs/Wiki/link-map) for visualizing notes and their relations
|
||||||
* Mind maps, based on [Mind Elixir](https://docs.mind-elixir.com/)
|
|
||||||
* [Geo maps](./docs/User%20Guide/User%20Guide/Note%20Types/Geo%20Map.md) with location pins and GPX tracks
|
|
||||||
* [Scripting](https://triliumnext.github.io/Docs/Wiki/scripts) - see [Advanced showcases](https://triliumnext.github.io/Docs/Wiki/advanced-showcases)
|
* [Scripting](https://triliumnext.github.io/Docs/Wiki/scripts) - see [Advanced showcases](https://triliumnext.github.io/Docs/Wiki/advanced-showcases)
|
||||||
* [REST API](https://triliumnext.github.io/Docs/Wiki/etapi) for automation
|
* [REST API](https://triliumnext.github.io/Docs/Wiki/etapi) for automation
|
||||||
* Scales well in both usability and performance upwards of 100 000 notes
|
* Scales well in both usability and performance upwards of 100 000 notes
|
||||||
* Touch optimized [mobile frontend](https://triliumnext.github.io/Docs/Wiki/mobile-frontend) for smartphones and tablets
|
* Touch optimized [mobile frontend](https://triliumnext.github.io/Docs/Wiki/mobile-frontend) for smartphones and tablets
|
||||||
* Built-in [dark theme](https://triliumnext.github.io/Docs/Wiki/themes), support for user themes
|
* [Night theme](https://triliumnext.github.io/Docs/Wiki/themes)
|
||||||
* [Evernote](https://triliumnext.github.io/Docs/Wiki/evernote-import) and [Markdown import & export](https://triliumnext.github.io/Docs/Wiki/markdown)
|
* [Evernote](https://triliumnext.github.io/Docs/Wiki/evernote-import) and [Markdown import & export](https://triliumnext.github.io/Docs/Wiki/markdown)
|
||||||
* [Web Clipper](https://triliumnext.github.io/Docs/Wiki/web-clipper) for easy saving of web content
|
* [Web Clipper](https://triliumnext.github.io/Docs/Wiki/web-clipper) for easy saving of web content
|
||||||
* Customizable UI (sidebar buttons, user-defined widgets, ...)
|
|
||||||
* [Metrics](./docs/User%20Guide/User%20Guide/Advanced%20Usage/Metrics.md), along with a [Grafana Dashboard](./docs/User%20Guide/User%20Guide/Advanced%20Usage/Metrics/grafana-dashboard.json)
|
|
||||||
|
|
||||||
✨ Check out the following third-party resources/communities for more TriliumNext related goodies:
|
✨ Check out the following third-party resources/communities for more TriliumNext related goodies:
|
||||||
|
|
||||||
- [awesome-trilium](https://github.com/Nriver/awesome-trilium) for 3rd party themes, scripts, plugins and more.
|
- [awesome-trilium](https://github.com/Nriver/awesome-trilium) for 3rd party themes, scripts, plugins and more.
|
||||||
- [TriliumRocks!](https://trilium.rocks/) for tutorials, guides, and much more.
|
- [TriliumRocks!](https://trilium.rocks/) for tutorials, guides, and much more.
|
||||||
|
|
||||||
## ❓Why TriliumNext?
|
|
||||||
|
|
||||||
The original Trilium developer ([Zadam](https://github.com/zadam)) has graciously given the Trilium repository to the community project which resides at https://github.com/TriliumNext
|
|
||||||
|
|
||||||
### ⬆️Migrating from Zadam/Trilium?
|
|
||||||
|
|
||||||
There are no special migration steps to migrate from a zadam/Trilium instance to a TriliumNext/Trilium instance. Simply [install TriliumNext/Trilium](#-installation) as usual and it will use your existing database.
|
|
||||||
|
|
||||||
Versions up to and including [v0.90.4](https://github.com/TriliumNext/Trilium/releases/tag/v0.90.4) are compatible with the latest zadam/trilium version of [v0.63.7](https://github.com/zadam/trilium/releases/tag/v0.63.7). Any later versions of TriliumNext/Trilium have their sync versions incremented which prevents direct migration.
|
|
||||||
|
|
||||||
## 💬 Discuss with us
|
|
||||||
|
|
||||||
Feel free to join our official conversations. We would love to hear what features, suggestions, or issues you may have!
|
|
||||||
|
|
||||||
- [Matrix](https://matrix.to/#/#triliumnext:matrix.org) (For synchronous discussions.)
|
|
||||||
- The `General` Matrix room is also bridged to [XMPP](xmpp:discuss@trilium.thisgreat.party?join)
|
|
||||||
- [Github Discussions](https://github.com/TriliumNext/Trilium/discussions) (For asynchronous discussions.)
|
|
||||||
- [Github Issues](https://github.com/TriliumNext/Trilium/issues) (For bug reports and feature requests.)
|
|
||||||
|
|
||||||
## 🏗 Installation
|
## 🏗 Installation
|
||||||
|
|
||||||
### Windows / MacOS
|
### Desktop
|
||||||
|
|
||||||
Download the binary release for your platform from the [latest release page](https://github.com/TriliumNext/Trilium/releases/latest), unzip the package and run the `trilium` executable.
|
To use TriliumNext on your desktop machine (Linux, MacOS, and Windows) you have a few options:
|
||||||
|
|
||||||
### Linux
|
* 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
|
||||||
|
|
||||||
If your distribution is listed in the table below, use your distribution's package.
|
#### 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.
|
||||||
|
|
||||||
[](https://repology.org/project/triliumnext/versions)
|
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)):
|
||||||
|
|
||||||
You may also download the binary release for your platform from the [latest release page](https://github.com/TriliumNext/Trilium/releases/latest), unzip the package and run the `trilium` executable.
|
```bash
|
||||||
|
xattr -c "/path/to/Trilium Next.app"
|
||||||
TriliumNext is also provided as a Flatpak, but not yet published on FlatHub.
|
```
|
||||||
|
|
||||||
### Browser (any OS)
|
|
||||||
|
|
||||||
If you use a server installation (see below), you can directly access the web interface (which is almost identical to the desktop app).
|
|
||||||
|
|
||||||
Currently only the latest versions of Chrome & Firefox are supported (and tested).
|
|
||||||
|
|
||||||
### Mobile
|
### Mobile
|
||||||
|
|
||||||
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).
|
To use TriliumNext on a mobile device:
|
||||||
|
|
||||||
See issue https://github.com/TriliumNext/Trilium/issues/4962 for more information on mobile app support.
|
* 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).
|
|
||||||
Note: It is best to disable automatic updates on your server installation (see below) when using TriliumDroid since the sync version must match between Trilium and TriliumDroid.
|
|
||||||
|
|
||||||
### Server
|
### Server
|
||||||
|
|
||||||
To install TriliumNext on your own server (including via Docker from [Dockerhub](https://hub.docker.com/r/triliumnext/trilium)) follow [the server installation docs](https://triliumnext.github.io/Docs/Wiki/server-installation).
|
To install TriliumNext on your own server (including via Docker from [Dockerhub](https://hub.docker.com/r/triliumnext/notes)) follow [the server installation docs](https://triliumnext.github.io/Docs/Wiki/server-installation).
|
||||||
|
|
||||||
|
## 📝 Documentation
|
||||||
|
|
||||||
|
[See wiki for complete list of documentation pages.](https://triliumnext.github.io/Docs)
|
||||||
|
|
||||||
|
You can also read [Patterns of personal knowledge base](https://triliumnext.github.io/Docs/Wiki/patterns-of-personal-knowledge) to get some inspiration on how you might use TriliumNext.
|
||||||
|
|
||||||
## 💻 Contribute
|
## 💻 Contribute
|
||||||
|
|
||||||
### Translations
|
|
||||||
|
|
||||||
If you are a native speaker, help us translate Trilium by heading over to our [Weblate page](https://hosted.weblate.org/engage/trilium/).
|
|
||||||
|
|
||||||
Here's the language coverage we have so far:
|
|
||||||
|
|
||||||
[](https://hosted.weblate.org/engage/trilium/)
|
|
||||||
|
|
||||||
### Code
|
### Code
|
||||||
|
|
||||||
Download the repository, install dependencies using `pnpm` and then run the server (available at http://localhost:8080):
|
|
||||||
```shell
|
```shell
|
||||||
git clone https://github.com/TriliumNext/Trilium.git
|
git clone https://github.com/TriliumNext/Notes.git
|
||||||
cd Trilium
|
cd Notes
|
||||||
pnpm install
|
npm install
|
||||||
pnpm run server:start
|
npm run start-server
|
||||||
```
|
```
|
||||||
|
|
||||||
### Documentation
|
### Documentation
|
||||||
|
|
||||||
Download the repository, install dependencies using `pnpm` and then run the environment required to edit the documentation:
|
Head on over to our [Docs repo](https://github.com/TriliumNext/Docs)
|
||||||
```shell
|
|
||||||
git clone https://github.com/TriliumNext/Trilium.git
|
|
||||||
cd Trilium
|
|
||||||
pnpm install
|
|
||||||
pnpm edit-docs:edit-docs
|
|
||||||
```
|
|
||||||
|
|
||||||
### Building the Executable
|
|
||||||
Download the repository, install dependencies using `pnpm` and then build the desktop app for Windows:
|
|
||||||
```shell
|
|
||||||
git clone https://github.com/TriliumNext/Trilium.git
|
|
||||||
cd Trilium
|
|
||||||
pnpm install
|
|
||||||
pnpm run --filter desktop electron-forge:make --arch=x64 --platform=win32
|
|
||||||
```
|
|
||||||
|
|
||||||
For more details, see the [development docs](https://github.com/TriliumNext/Trilium/tree/main/docs/Developer%20Guide/Developer%20Guide).
|
|
||||||
|
|
||||||
### Developer Documentation
|
|
||||||
|
|
||||||
Please view the [documentation guide](https://github.com/TriliumNext/Trilium/blob/main/docs/Developer%20Guide/Developer%20Guide/Environment%20Setup.md) for details. If you have more questions, feel free to reach out via the links described in the "Discuss with us" section above.
|
|
||||||
|
|
||||||
## 👏 Shoutouts
|
## 👏 Shoutouts
|
||||||
|
|
||||||
* [zadam](https://github.com/zadam) for the original concept and implementation of the application.
|
* [CKEditor 5](https://github.com/ckeditor/ckeditor5) - best WYSIWYG editor on the market, very interactive and listening team
|
||||||
* [Sarah Hussein](https://github.com/Sarah-Hussein) for designing the application icon.
|
* [FancyTree](https://github.com/mar10/fancytree) - very feature rich tree library without real competition. TriliumNext Notes would not be the same without it.
|
||||||
* [nriver](https://github.com/nriver) for his work on internationalization.
|
* [CodeMirror](https://github.com/codemirror/CodeMirror) - code editor with support for huge amount of languages
|
||||||
* [Thomas Frei](https://github.com/thfrei) for his original work on the Canvas.
|
* [jsPlumb](https://github.com/jsplumb/jsplumb) - visual connectivity library without competition. Used in [relation maps](https://triliumnext.github.io/Docs/Wiki/relation-map.html) and [link maps](https://triliumnext.github.io/Docs/Wiki/note-map.html#link-map)
|
||||||
* [antoniotejada](https://github.com/nriver) for the original syntax highlight widget.
|
|
||||||
* [Dosu](https://dosu.dev/) for providing us with the automated responses to GitHub issues and discussions.
|
|
||||||
* [Tabler Icons](https://tabler.io/icons) for the system tray icons.
|
|
||||||
|
|
||||||
Trilium would not be possible without the technologies behind it:
|
|
||||||
|
|
||||||
* [CKEditor 5](https://github.com/ckeditor/ckeditor5) - the visual editor behind text notes. We are grateful for being offered a set of the premium features.
|
|
||||||
* [CodeMirror](https://github.com/codemirror/CodeMirror) - code editor with support for huge amount of languages.
|
|
||||||
* [Excalidraw](https://github.com/excalidraw/excalidraw) - the infinite whiteboard used in Canvas notes.
|
|
||||||
* [Mind Elixir](https://github.com/SSShooter/mind-elixir-core) - providing the mind map functionality.
|
|
||||||
* [Leaflet](https://github.com/Leaflet/Leaflet) - for rendering geographical maps.
|
|
||||||
* [Tabulator](https://github.com/olifolkerd/tabulator) - for the interactive table used in collections.
|
|
||||||
* [FancyTree](https://github.com/mar10/fancytree) - feature-rich tree library without real competition.
|
|
||||||
* [jsPlumb](https://github.com/jsplumb/jsplumb) - visual connectivity library. Used in [relation maps](https://triliumnext.github.io/Docs/Wiki/relation-map.html) and [link maps](https://triliumnext.github.io/Docs/Wiki/note-map.html#link-map)
|
|
||||||
|
|
||||||
## 🤝 Support
|
## 🤝 Support
|
||||||
|
|
||||||
Trilium is built and maintained with [hundreds of hours of work](https://github.com/TriliumNext/Trilium/graphs/commit-activity). Your support keeps it open-source, improves features, and covers costs such as hosting.
|
You can support the original Trilium developer using GitHub Sponsors, [PayPal](https://paypal.me/za4am) or Bitcoin (bitcoin:bc1qv3svjn40v89mnkre5vyvs2xw6y8phaltl385d2).
|
||||||
|
Support for the TriliumNext organization will be possible in the near future.
|
||||||
Consider supporting the main developer ([eliandoran](https://github.com/eliandoran)) of the application via:
|
|
||||||
|
|
||||||
- [GitHub Sponsors](https://github.com/sponsors/eliandoran)
|
|
||||||
- [PayPal](https://paypal.me/eliandoran)
|
|
||||||
- [Buy Me a Coffee](https://buymeacoffee.com/eliandoran)
|
|
||||||
|
|
||||||
|
|
||||||
## 🔑 License
|
## 🔑 License
|
||||||
|
|
||||||
Copyright 2017-2025 zadam, Elian Doran, and other contributors
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||||
|
|||||||
59
README.ru.md
Normal file
59
README.ru.md
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
# 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)
|
||||||
|
|
||||||
|
Trilium Notes – это приложение для заметок с иерархической структурой, ориентированное на создание больших персональных баз знаний. Для быстрого ознакомления посмотрите [скриншот-тур](https://triliumnext.github.io/Docs/Wiki/screenshot-tour):
|
||||||
|
|
||||||
|
<a href="https://triliumnext.github.io/Docs/Wiki/screenshot-tour"><img src="https://github.com/TriliumNext/Docs/blob/main/Wiki/images/screenshot.png?raw=true" alt="Trilium Screenshot" width="1000"></a>
|
||||||
|
|
||||||
|
## 🎁 Возможности
|
||||||
|
|
||||||
|
* Заметки можно расположить в виде дерева произвольной глубины. Отдельную заметку можно разместить в нескольких местах дерева (см. [клонирование](https://triliumnext.github.io/Docs/Wiki/cloning-notes))
|
||||||
|
* Продвинутый визуальный редактор (WYSIWYG) позволяет работать с таблицами, изображениями, [формулами](https://triliumnext.github.io/Docs/Wiki/text-notes#math-support) и разметкой markdown, имеет [автоформатирование](https://triliumnext.github.io/Docs/Wiki/text-notes#autoformat)
|
||||||
|
* Редактирование [заметок с исходным кодом](https://triliumnext.github.io/Docs/Wiki/code-notes), включая подсветку синтаксиса
|
||||||
|
* Быстрая и простая [навигация между заметками](https://triliumnext.github.io/Docs/Wiki/note-navigation), полнотекстовый поиск и [выделение заметок](https://triliumnext.github.io/Docs/Wiki/note-hoisting) в отдельный блок
|
||||||
|
* Бесшовное [версионирование заметки](https://triliumnext.github.io/Docs/Wiki/note-revisions)
|
||||||
|
* Специальные [атрибуты](https://triliumnext.github.io/Docs/Wiki/attributes) позволяют гибко организовать структуру, используются для поиска и продвинутого [скриптинга](https://triliumnext.github.io/Docs/Wiki/scripts)
|
||||||
|
* [Синхронизация](https://triliumnext.github.io/Docs/Wiki/synchronization) заметок со своим сервером
|
||||||
|
* Надёжное [шифрование](https://triliumnext.github.io/Docs/Wiki/protected-notes) с детализацией по каждой заметке
|
||||||
|
* [Карты связей](https://triliumnext.github.io/Docs/Wiki/relation-map) и [карты ссылок](https://triliumnext.github.io/Docs/Wiki/link-map) для визуализации их взяимосвязей
|
||||||
|
* [Скрипты](https://triliumnext.github.io/Docs/Wiki/scripts) - см. [продвинутые примеры](https://triliumnext.github.io/Docs/Wiki/advanced-showcases)
|
||||||
|
* Хорошо масштабируется, как по удобству использования, так и по производительности до 100000 заметок
|
||||||
|
* Оптимизированный [мобильный фронтенд](https://triliumnext.github.io/Docs/Wiki/mobile-frontend) смартфонов и планшетов
|
||||||
|
* [Темная тема](https://triliumnext.github.io/Docs/Wiki/themes)
|
||||||
|
* Импорт и экпорт [Evernote](https://triliumnext.github.io/Docs/Wiki/evernote-import) и данных в [markdown](https://triliumnext.github.io/Docs/Wiki/markdown) формате
|
||||||
|
* [Web Clipper](https://triliumnext.github.io/Docs/Wiki/web-clipper) для удобного сохранения веб-контента
|
||||||
|
|
||||||
|
## 🏗 Сборки
|
||||||
|
|
||||||
|
Trilium предоставляется в виде десктопного приложения (Linux и Windows) или веб-приложения, размещенного на вашем сервере (Linux). Доступна сборка Mac OS, но она [не поддерживается](https://triliumnext.github.io/Docs/Wiki/faq#mac-os-support).
|
||||||
|
|
||||||
|
* Если вы хотите использовать Trilium на десктопе, скачайте архив для своей платформы со страницы [релизов](https://github.com/TriliumNext/Notes/releases/latest), распакуйте и запустите исполняемый файл ```trilium```.
|
||||||
|
* Если вы хотите установить Trilium на сервере, следуйте этой [инструкции](https://triliumnext.github.io/Docs/Wiki/server-installation).
|
||||||
|
* В данный момент поддерживаются (протестированы) последние версии браузеров Chrome и Firefox.
|
||||||
|
|
||||||
|
## 📝 Документация
|
||||||
|
|
||||||
|
[Полный список страниц документации доступен в Wiki.](https://triliumnext.github.io/Docs/)
|
||||||
|
|
||||||
|
Вы также можете ознакомиться с [шаблонами персональных баз знаний](https://triliumnext.github.io/Docs/Wiki/patterns-of-personal-knowledge), чтобы получить представление о том, как можно использовать Trilium.
|
||||||
|
|
||||||
|
## 💻 Участвуйте в разработке
|
||||||
|
|
||||||
|
Или склонируйте на своё устройство и запустите
|
||||||
|
|
||||||
|
```shell
|
||||||
|
npm install
|
||||||
|
npm run start-server
|
||||||
|
```
|
||||||
|
|
||||||
|
## 👏 Благодарности
|
||||||
|
|
||||||
|
* [CKEditor 5](https://github.com/ckeditor/ckeditor5) - лучший WYSIWYG редактор, очень активная и внимательная команда.
|
||||||
|
* [FancyTree](https://github.com/mar10/fancytree) - многофункциональная библиотека для создания древовидных структур. Вне конкуренции. Без него Trilium Notes не были бы таким.
|
||||||
|
* [CodeMirror](https://github.com/codemirror/CodeMirror) - редактор кода с поддержкой огромного количество языков.
|
||||||
|
* [jsPlumb](https://github.com/jsplumb/jsplumb) - библиотека для визуализации связей. Вне конкуренции. Используется в [картах связей](https://triliumnext.github.io/Docs/Wiki/relation-map) и [картах ссылок](https://triliumnext.github.io/Docs/Wiki/link-map).
|
||||||
|
|
||||||
|
## 🔑 Лицензия
|
||||||
|
|
||||||
|
Эта программа является бесплатным программным обеспечением: вы можете распространять и/или изменять ее в соответствии с условиями GNU Affero General Public License, опубликованной Free Software Foundation, либо версии 3 Лицензии, либо (по вашему выбору) любой более поздней версии.
|
||||||
13
_check_ts_progress.sh
Executable file
13
_check_ts_progress.sh
Executable file
@@ -0,0 +1,13 @@
|
|||||||
|
#!/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\|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
if [[ $# -eq 0 ]] ; then
|
|
||||||
echo "Missing argument of new version"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! command -v jq &> /dev/null; then
|
|
||||||
echo "Missing command: jq"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
VERSION=$1
|
|
||||||
|
|
||||||
if ! [[ ${VERSION} =~ ^[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,2}(-.+)?$ ]] ;
|
|
||||||
then
|
|
||||||
echo "Version ${VERSION} isn't in format X.Y.Z"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! git diff-index --quiet HEAD --; then
|
|
||||||
echo "There are uncommitted changes"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Releasing Trilium $VERSION"
|
|
||||||
|
|
||||||
jq '.version = "'$VERSION'"' package.json > package.json.tmp
|
|
||||||
mv package.json.tmp package.json
|
|
||||||
|
|
||||||
git add package.json
|
|
||||||
|
|
||||||
npm run chore:update-build-info
|
|
||||||
|
|
||||||
git add src/services/build.ts
|
|
||||||
|
|
||||||
TAG=v$VERSION
|
|
||||||
|
|
||||||
echo "Committing package.json version change"
|
|
||||||
|
|
||||||
git commit -m "chore(release): $VERSION"
|
|
||||||
git push
|
|
||||||
|
|
||||||
echo "Tagging commit with $TAG"
|
|
||||||
|
|
||||||
git tag $TAG
|
|
||||||
git push origin $TAG
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-bookmark"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M18 7v14l-6 -4l-6 4v-14a4 4 0 0 1 4 -4h4a4 4 0 0 1 4 4z" /></svg>
|
|
||||||
|
Before Width: | Height: | Size: 383 B |
@@ -1,39 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
if ! command -v magick &> /dev/null; then
|
|
||||||
echo "This tool requires ImageMagick to be installed in order to create the icons."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! command -v inkscape &> /dev/null; then
|
|
||||||
echo "This tool requires Inkscape to be render sharper SVGs than ImageMagick."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
script_dir=$(realpath $(dirname $0))
|
|
||||||
images_dir="$script_dir/../../images"
|
|
||||||
output_dir="$images_dir/app-icons/tray"
|
|
||||||
|
|
||||||
function generateDpiScaledIcons {
|
|
||||||
file=$1
|
|
||||||
suffix=$2
|
|
||||||
name="$(basename $file .svg)$suffix"
|
|
||||||
inkscape -w 16 -h 16 "$file" -o "$output_dir/$name.png"
|
|
||||||
inkscape -w 20 -h 20 "$file" -o "$output_dir/$name@1.25x.png"
|
|
||||||
inkscape -w 24 -h 24 "$file" -o "$output_dir/$name@1.5x.png"
|
|
||||||
inkscape -w 32 -h 32 "$file" -o "$output_dir/$name@2x.png"
|
|
||||||
}
|
|
||||||
|
|
||||||
generateDpiScaledIcons "$images_dir/icon-black.svg" "Template"
|
|
||||||
generateDpiScaledIcons "$images_dir/icon-color.svg"
|
|
||||||
generateDpiScaledIcons "$images_dir/icon-purple.svg"
|
|
||||||
|
|
||||||
for file in *.svg; do
|
|
||||||
name="$(basename $file .svg)Template"
|
|
||||||
generateDpiScaledIcons "$file" "Template"
|
|
||||||
magick "$output_dir/$name.png" -channel RGB -negate "$output_dir/$name-inverted.png"
|
|
||||||
magick "$output_dir/$name@1.25x.png" -channel RGB -negate "$output_dir/$name-inverted@1.25x.png"
|
|
||||||
magick "$output_dir/$name@1.5x.png" -channel RGB -negate "$output_dir/$name-inverted@1.5x.png"
|
|
||||||
magick "$output_dir/$name@2x.png" -channel RGB -negate "$output_dir/$name-inverted@2x.png"
|
|
||||||
done
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-x"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M18 6l-12 12" /><path d="M6 6l12 12" /></svg>
|
|
||||||
|
Before Width: | Height: | Size: 356 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-plus"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M12 5l0 14" /><path d="M5 12l14 0" /></svg>
|
|
||||||
|
Before Width: | Height: | Size: 357 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-history"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M12 8l0 4l2 2" /><path d="M3.05 11a9 9 0 1 1 .5 4m-.5 5v-5h5" /></svg>
|
|
||||||
|
Before Width: | Height: | Size: 387 B |
@@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-calendar-star"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M11 21h-5a2 2 0 0 1 -2 -2v-12a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v3.5" /><path d="M16 3v4" /><path d="M8 3v4" /><path d="M4 11h11" /><path d="M17.8 20.817l-2.172 1.138a.392 .392 0 0 1 -.568 -.41l.415 -2.411l-1.757 -1.707a.389 .389 0 0 1 .217 -.665l2.428 -.352l1.086 -2.193a.392 .392 0 0 1 .702 0l1.086 2.193l2.428 .352a.39 .39 0 0 1 .217 .665l-1.757 1.707l.414 2.41a.39 .39 0 0 1 -.567 .411l-2.172 -1.138z" /></svg>
|
|
||||||
|
Before Width: | Height: | Size: 734 B |
@@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>com.apple.security.cs.allow-jit</key>
|
|
||||||
<true/>
|
|
||||||
<key>com.apple.security.files.user-selected.read-write</key>
|
|
||||||
<true/>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
import eslint from "@eslint/js";
|
|
||||||
import tseslint from "typescript-eslint";
|
|
||||||
import simpleImportSort from "eslint-plugin-simple-import-sort";
|
|
||||||
|
|
||||||
export default tseslint.config(
|
|
||||||
eslint.configs.recommended,
|
|
||||||
tseslint.configs.recommended,
|
|
||||||
// consider using rules below, once we have a full TS codebase and can be more strict
|
|
||||||
// tseslint.configs.strictTypeChecked,
|
|
||||||
// tseslint.configs.stylisticTypeChecked,
|
|
||||||
// tseslint.configs.recommendedTypeChecked,
|
|
||||||
{
|
|
||||||
languageOptions: {
|
|
||||||
parserOptions: {
|
|
||||||
projectService: true,
|
|
||||||
tsconfigRootDir: import.meta.dirname
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
plugins: {
|
|
||||||
"simple-import-sort": simpleImportSort
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
rules: {
|
|
||||||
// add rule overrides here
|
|
||||||
"no-undef": "off",
|
|
||||||
"no-unused-vars": "off",
|
|
||||||
"@typescript-eslint/no-unused-vars": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
argsIgnorePattern: "^_",
|
|
||||||
varsIgnorePattern: "^_"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"simple-import-sort/imports": "error",
|
|
||||||
"simple-import-sort/exports": "error"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ignores: [
|
|
||||||
"build/*",
|
|
||||||
"dist/*",
|
|
||||||
"docs/*",
|
|
||||||
"demo/*",
|
|
||||||
"src/public/app-dist/*",
|
|
||||||
"src/public/app/doc_notes/*"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
);
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
import stylistic from "@stylistic/eslint-plugin";
|
|
||||||
import tsParser from "@typescript-eslint/parser";
|
|
||||||
|
|
||||||
// eslint config just for formatting rules
|
|
||||||
// potentially to be merged with the linting rules into one single config,
|
|
||||||
// once we have fixed the majority of lint errors
|
|
||||||
|
|
||||||
// Go to https://eslint.style/rules/default/${rule_without_prefix} to check the rule details
|
|
||||||
export const stylisticRules = {
|
|
||||||
"@stylistic/indent": [ "error", 4 ],
|
|
||||||
"@stylistic/quotes": [ "error", "double", { avoidEscape: true, allowTemplateLiterals: "always" } ],
|
|
||||||
"@stylistic/semi": [ "error", "always" ],
|
|
||||||
"@stylistic/quote-props": [ "error", "consistent-as-needed" ],
|
|
||||||
"@stylistic/max-len": [ "error", { code: 100 } ],
|
|
||||||
"@stylistic/comma-dangle": [ "error", "never" ],
|
|
||||||
"@stylistic/linebreak-style": [ "error", "unix" ],
|
|
||||||
"@stylistic/array-bracket-spacing": [ "error", "always" ],
|
|
||||||
"@stylistic/object-curly-spacing": [ "error", "always" ],
|
|
||||||
"@stylistic/padded-blocks": [ "error", { classes: "always" } ]
|
|
||||||
};
|
|
||||||
|
|
||||||
export default [
|
|
||||||
{
|
|
||||||
files: [ "**/*.{js,ts,mjs,cjs}" ],
|
|
||||||
languageOptions: {
|
|
||||||
parser: tsParser
|
|
||||||
},
|
|
||||||
plugins: {
|
|
||||||
"@stylistic": stylistic
|
|
||||||
},
|
|
||||||
rules: {
|
|
||||||
...stylisticRules
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ignores: [
|
|
||||||
"build/*",
|
|
||||||
"dist/*",
|
|
||||||
"docs/*",
|
|
||||||
"demo/*",
|
|
||||||
// TriliumNextTODO: check if we want to format packages here as well - for now skipping it
|
|
||||||
"packages/*",
|
|
||||||
"src/public/app-dist/*",
|
|
||||||
"src/public/app/doc_notes/*"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
];
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
{
|
|
||||||
"main": "./electron-main.js",
|
|
||||||
"bin": {
|
|
||||||
"trilium": "src/main.js"
|
|
||||||
},
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"server:start-safe": "cross-env TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev nodemon src/main.ts",
|
|
||||||
"server:start-no-dir": "cross-env TRILIUM_ENV=dev nodemon src/main.ts",
|
|
||||||
"server:start-test": "npm run server:switch && rimraf ./data-test && cross-env TRILIUM_DATA_DIR=./data-test TRILIUM_ENV=dev TRILIUM_PORT=9999 nodemon src/main.ts",
|
|
||||||
"server:qstart": "npm run server:switch && npm run server:start",
|
|
||||||
"server:switch": "rimraf ./node_modules/better-sqlite3 && npm install",
|
|
||||||
"electron:start-no-dir": "cross-env NODE_OPTIONS=\"--import tsx\" TRILIUM_ENV=dev TRILIUM_PORT=37742 electron --inspect=5858 .",
|
|
||||||
"electron:start-nix": "electron-rebuild --version 33.3.1 && cross-env NODE_OPTIONS=\"--import tsx\" TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev nix-shell -p electron_33 --run \"electron ./electron-main.ts --inspect=5858 .\"",
|
|
||||||
"electron:start-nix-no-dir": "electron-rebuild --version 33.3.1 && cross-env NODE_OPTIONS=\"--import tsx\" TRILIUM_ENV=dev TRILIUM_PORT=37742 nix-shell -p electron_33 --run \"electron ./electron-main.ts --inspect=5858 .\"",
|
|
||||||
"electron:start-prod-no-dir": "npm run build:prepare-dist && cross-env TRILIUM_ENV=prod electron --inspect=5858 .",
|
|
||||||
"electron:start-prod-nix": "electron-rebuild --version 33.3.1 && npm run build:prepare-dist && cross-env TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev nix-shell -p electron_33 --run \"electron ./dist/electron-main.js --inspect=5858 .\"",
|
|
||||||
"electron:start-prod-nix-no-dir": "electron-rebuild --version 33.3.1 && npm run build:prepare-dist && cross-env TRILIUM_ENV=dev nix-shell -p electron_33 --run \"electron ./dist/electron-main.js --inspect=5858 .\"",
|
|
||||||
"electron:qstart": "npm run electron:switch && npm run electron:start",
|
|
||||||
"electron:switch": "electron-rebuild",
|
|
||||||
"docs:build": "typedoc",
|
|
||||||
"test": "npm run client:test && npm run server:test",
|
|
||||||
"client:test": "cross-env TRILIUM_ENV=dev TRILIUM_DATA_DIR=./integration-tests/db TRILIUM_INTEGRATION_TEST=memory vitest --root src/public/app",
|
|
||||||
"client:coverage": "cross-env TRILIUM_ENV=dev TRILIUM_DATA_DIR=./integration-tests/db TRILIUM_INTEGRATION_TEST=memory vitest --root src/public/app --coverage",
|
|
||||||
"test:playwright": "playwright test --workers 1",
|
|
||||||
"test:integration-edit-db": "cross-env TRILIUM_INTEGRATION_TEST=edit TRILIUM_PORT=8081 TRILIUM_ENV=dev TRILIUM_DATA_DIR=./integration-tests/db nodemon src/main.ts",
|
|
||||||
"test:integration-mem-db": "cross-env nodemon src/main.ts",
|
|
||||||
"test:integration-mem-db-dev": "cross-env TRILIUM_INTEGRATION_TEST=memory TRILIUM_PORT=8082 TRILIUM_ENV=dev TRILIUM_DATA_DIR=./integration-tests/db nodemon src/main.ts",
|
|
||||||
"dev:watch-dist": "tsx ./bin/watch-dist.ts",
|
|
||||||
"dev:format-check": "eslint -c eslint.format.config.js .",
|
|
||||||
"dev:format-fix": "eslint -c eslint.format.config.js . --fix",
|
|
||||||
"dev:linter-check": "eslint .",
|
|
||||||
"dev:linter-fix": "eslint . --fix",
|
|
||||||
"chore:generate-document": "cross-env nodemon ./bin/generate_document.ts 1000",
|
|
||||||
"chore:generate-openapi": "tsx bin/generate-openapi.js"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@playwright/test": "1.57.0",
|
|
||||||
"@stylistic/eslint-plugin": "5.6.1",
|
|
||||||
"@types/express": "5.0.5",
|
|
||||||
"@types/node": "24.10.1",
|
|
||||||
"@types/yargs": "17.0.35",
|
|
||||||
"@vitest/coverage-v8": "4.0.14",
|
|
||||||
"eslint": "9.39.1",
|
|
||||||
"eslint-plugin-simple-import-sort": "12.1.1",
|
|
||||||
"esm": "3.2.25",
|
|
||||||
"jsdoc": "4.0.5",
|
|
||||||
"lorem-ipsum": "2.0.8",
|
|
||||||
"rcedit": "5.0.2",
|
|
||||||
"rimraf": "6.1.2",
|
|
||||||
"tslib": "2.8.1"
|
|
||||||
},
|
|
||||||
"optionalDependencies": {
|
|
||||||
"appdmg": "0.6.6"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
import etapi from "../support/etapi.js";
|
|
||||||
/* TriliumNextTODO: port to Vitest
|
|
||||||
etapi.describeEtapi("app_info", () => {
|
|
||||||
it("get", async () => {
|
|
||||||
const appInfo = await etapi.getEtapi("app-info");
|
|
||||||
expect(appInfo.clipperProtocolVersion).toEqual("1.0");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
import etapi from "../support/etapi.js";
|
|
||||||
|
|
||||||
/* TriliumNextTODO: port to Vitest
|
|
||||||
etapi.describeEtapi("backup", () => {
|
|
||||||
it("create", async () => {
|
|
||||||
const response = await etapi.putEtapiContent("backup/etapi_test");
|
|
||||||
expect(response.status).toEqual(204);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
import etapi from "../support/etapi.js";
|
|
||||||
import fs from "fs";
|
|
||||||
import path from "path";
|
|
||||||
import { fileURLToPath } from "url";
|
|
||||||
|
|
||||||
/* TriliumNextTODO: port to Vitest
|
|
||||||
etapi.describeEtapi("import", () => {
|
|
||||||
// temporarily skip this test since test-export.zip is missing
|
|
||||||
xit("import", async () => {
|
|
||||||
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
|
|
||||||
|
|
||||||
const zipFileBuffer = fs.readFileSync(path.resolve(scriptDir, "test-export.zip"));
|
|
||||||
|
|
||||||
const response = await etapi.postEtapiContent("notes/root/import", zipFileBuffer);
|
|
||||||
expect(response.status).toEqual(201);
|
|
||||||
|
|
||||||
const { note, branch } = await response.json();
|
|
||||||
|
|
||||||
expect(note.title).toEqual("test-export");
|
|
||||||
expect(branch.parentNoteId).toEqual("root");
|
|
||||||
|
|
||||||
const content = await (await etapi.getEtapiContent(`notes/${note.noteId}/content`)).text();
|
|
||||||
expect(content).toContain("test export content");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
import crypto from "crypto";
|
|
||||||
import etapi from "../support/etapi.js";
|
|
||||||
|
|
||||||
/* TriliumNextTODO: port to Vitest
|
|
||||||
etapi.describeEtapi("notes", () => {
|
|
||||||
it("create", async () => {
|
|
||||||
const { note, branch } = await etapi.postEtapi("create-note", {
|
|
||||||
parentNoteId: "root",
|
|
||||||
type: "text",
|
|
||||||
title: "Hello World!",
|
|
||||||
content: "Content",
|
|
||||||
prefix: "Custom prefix"
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(note.title).toEqual("Hello World!");
|
|
||||||
expect(branch.parentNoteId).toEqual("root");
|
|
||||||
expect(branch.prefix).toEqual("Custom prefix");
|
|
||||||
|
|
||||||
const rNote = await etapi.getEtapi(`notes/${note.noteId}`);
|
|
||||||
expect(rNote.title).toEqual("Hello World!");
|
|
||||||
|
|
||||||
const rContent = await (await etapi.getEtapiContent(`notes/${note.noteId}/content`)).text();
|
|
||||||
expect(rContent).toEqual("Content");
|
|
||||||
|
|
||||||
const rBranch = await etapi.getEtapi(`branches/${branch.branchId}`);
|
|
||||||
expect(rBranch.parentNoteId).toEqual("root");
|
|
||||||
expect(rBranch.prefix).toEqual("Custom prefix");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("patch", async () => {
|
|
||||||
const { note } = await etapi.postEtapi("create-note", {
|
|
||||||
parentNoteId: "root",
|
|
||||||
type: "text",
|
|
||||||
title: "Hello World!",
|
|
||||||
content: "Content"
|
|
||||||
});
|
|
||||||
|
|
||||||
await etapi.patchEtapi(`notes/${note.noteId}`, {
|
|
||||||
title: "new title",
|
|
||||||
type: "code",
|
|
||||||
mime: "text/apl",
|
|
||||||
dateCreated: "2000-01-01 12:34:56.999+0200",
|
|
||||||
utcDateCreated: "2000-01-01 10:34:56.999Z"
|
|
||||||
});
|
|
||||||
|
|
||||||
const rNote = await etapi.getEtapi(`notes/${note.noteId}`);
|
|
||||||
expect(rNote.title).toEqual("new title");
|
|
||||||
expect(rNote.type).toEqual("code");
|
|
||||||
expect(rNote.mime).toEqual("text/apl");
|
|
||||||
expect(rNote.dateCreated).toEqual("2000-01-01 12:34:56.999+0200");
|
|
||||||
expect(rNote.utcDateCreated).toEqual("2000-01-01 10:34:56.999Z");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("update content", async () => {
|
|
||||||
const { note } = await etapi.postEtapi("create-note", {
|
|
||||||
parentNoteId: "root",
|
|
||||||
type: "text",
|
|
||||||
title: "Hello World!",
|
|
||||||
content: "Content"
|
|
||||||
});
|
|
||||||
|
|
||||||
await etapi.putEtapiContent(`notes/${note.noteId}/content`, "new content");
|
|
||||||
|
|
||||||
const rContent = await (await etapi.getEtapiContent(`notes/${note.noteId}/content`)).text();
|
|
||||||
expect(rContent).toEqual("new content");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("create / update binary content", async () => {
|
|
||||||
const { note } = await etapi.postEtapi("create-note", {
|
|
||||||
parentNoteId: "root",
|
|
||||||
type: "file",
|
|
||||||
title: "Hello World!",
|
|
||||||
content: "ZZZ"
|
|
||||||
});
|
|
||||||
|
|
||||||
const updatedContent = crypto.randomBytes(16);
|
|
||||||
|
|
||||||
await etapi.putEtapiContent(`notes/${note.noteId}/content`, updatedContent);
|
|
||||||
|
|
||||||
const rContent = await (await etapi.getEtapiContent(`notes/${note.noteId}/content`)).arrayBuffer();
|
|
||||||
expect(Buffer.from(new Uint8Array(rContent))).toEqual(updatedContent);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("delete note", async () => {
|
|
||||||
const { note } = await etapi.postEtapi("create-note", {
|
|
||||||
parentNoteId: "root",
|
|
||||||
type: "text",
|
|
||||||
title: "Hello World!",
|
|
||||||
content: "Content"
|
|
||||||
});
|
|
||||||
|
|
||||||
await etapi.deleteEtapi(`notes/${note.noteId}`);
|
|
||||||
|
|
||||||
const resp = await etapi.getEtapiResponse(`notes/${note.noteId}`);
|
|
||||||
expect(resp.status).toEqual(404);
|
|
||||||
|
|
||||||
const error = await resp.json();
|
|
||||||
expect(error.status).toEqual(404);
|
|
||||||
expect(error.code).toEqual("NOTE_NOT_FOUND");
|
|
||||||
expect(error.message).toEqual(`Note '${note.noteId}' not found.`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
@@ -1,152 +0,0 @@
|
|||||||
import { describe, beforeAll, afterAll } from "vitest";
|
|
||||||
|
|
||||||
let etapiAuthToken: string | undefined;
|
|
||||||
|
|
||||||
const getEtapiAuthorizationHeader = (): string => "Basic " + Buffer.from(`etapi:${etapiAuthToken}`).toString("base64");
|
|
||||||
|
|
||||||
const PORT: string = "9999";
|
|
||||||
const HOST: string = "http://localhost:" + PORT;
|
|
||||||
|
|
||||||
type SpecDefinitionsFunc = () => void;
|
|
||||||
|
|
||||||
function describeEtapi(description: string, specDefinitions: SpecDefinitionsFunc): void {
|
|
||||||
describe(description, () => {
|
|
||||||
beforeAll(async () => {});
|
|
||||||
|
|
||||||
afterAll(() => {});
|
|
||||||
|
|
||||||
specDefinitions();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getEtapiResponse(url: string): Promise<Response> {
|
|
||||||
return await fetch(`${HOST}/etapi/${url}`, {
|
|
||||||
method: "GET",
|
|
||||||
headers: {
|
|
||||||
Authorization: getEtapiAuthorizationHeader()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getEtapi(url: string): Promise<any> {
|
|
||||||
const response = await getEtapiResponse(url);
|
|
||||||
return await processEtapiResponse(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getEtapiContent(url: string): Promise<Response> {
|
|
||||||
const response = await fetch(`${HOST}/etapi/${url}`, {
|
|
||||||
method: "GET",
|
|
||||||
headers: {
|
|
||||||
Authorization: getEtapiAuthorizationHeader()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
checkStatus(response);
|
|
||||||
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function postEtapi(url: string, data: Record<string, unknown> = {}): Promise<any> {
|
|
||||||
const response = await fetch(`${HOST}/etapi/${url}`, {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
Authorization: getEtapiAuthorizationHeader()
|
|
||||||
},
|
|
||||||
body: JSON.stringify(data)
|
|
||||||
});
|
|
||||||
return await processEtapiResponse(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function postEtapiContent(url: string, data: BodyInit): Promise<Response> {
|
|
||||||
const response = await fetch(`${HOST}/etapi/${url}`, {
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/octet-stream",
|
|
||||||
Authorization: getEtapiAuthorizationHeader()
|
|
||||||
},
|
|
||||||
body: data
|
|
||||||
});
|
|
||||||
|
|
||||||
checkStatus(response);
|
|
||||||
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function putEtapi(url: string, data: Record<string, unknown> = {}): Promise<any> {
|
|
||||||
const response = await fetch(`${HOST}/etapi/${url}`, {
|
|
||||||
method: "PUT",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
Authorization: getEtapiAuthorizationHeader()
|
|
||||||
},
|
|
||||||
body: JSON.stringify(data)
|
|
||||||
});
|
|
||||||
return await processEtapiResponse(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function putEtapiContent(url: string, data?: BodyInit): Promise<Response> {
|
|
||||||
const response = await fetch(`${HOST}/etapi/${url}`, {
|
|
||||||
method: "PUT",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/octet-stream",
|
|
||||||
Authorization: getEtapiAuthorizationHeader()
|
|
||||||
},
|
|
||||||
body: data
|
|
||||||
});
|
|
||||||
|
|
||||||
checkStatus(response);
|
|
||||||
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function patchEtapi(url: string, data: Record<string, unknown> = {}): Promise<any> {
|
|
||||||
const response = await fetch(`${HOST}/etapi/${url}`, {
|
|
||||||
method: "PATCH",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
Authorization: getEtapiAuthorizationHeader()
|
|
||||||
},
|
|
||||||
body: JSON.stringify(data)
|
|
||||||
});
|
|
||||||
return await processEtapiResponse(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function deleteEtapi(url: string): Promise<any> {
|
|
||||||
const response = await fetch(`${HOST}/etapi/${url}`, {
|
|
||||||
method: "DELETE",
|
|
||||||
headers: {
|
|
||||||
Authorization: getEtapiAuthorizationHeader()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return await processEtapiResponse(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function processEtapiResponse(response: Response): Promise<any> {
|
|
||||||
const text = await response.text();
|
|
||||||
|
|
||||||
if (response.status < 200 || response.status >= 300) {
|
|
||||||
throw new Error(`ETAPI error ${response.status}: ${text}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return text?.trim() ? JSON.parse(text) : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkStatus(response: Response): void {
|
|
||||||
if (response.status < 200 || response.status >= 300) {
|
|
||||||
throw new Error(`ETAPI error ${response.status}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
describeEtapi,
|
|
||||||
getEtapi,
|
|
||||||
getEtapiResponse,
|
|
||||||
getEtapiContent,
|
|
||||||
postEtapi,
|
|
||||||
postEtapiContent,
|
|
||||||
putEtapi,
|
|
||||||
putEtapiContent,
|
|
||||||
patchEtapi,
|
|
||||||
deleteEtapi
|
|
||||||
};
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "build-docs",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "",
|
|
||||||
"main": "src/main.ts",
|
|
||||||
"scripts": {
|
|
||||||
"start": "tsx ."
|
|
||||||
},
|
|
||||||
"keywords": [],
|
|
||||||
"author": "Elian Doran <contact@eliandoran.me>",
|
|
||||||
"license": "AGPL-3.0-only",
|
|
||||||
"packageManager": "pnpm@10.24.0",
|
|
||||||
"devDependencies": {
|
|
||||||
"@redocly/cli": "2.12.0",
|
|
||||||
"archiver": "7.0.1",
|
|
||||||
"fs-extra": "11.3.2",
|
|
||||||
"react": "19.2.0",
|
|
||||||
"react-dom": "19.2.0",
|
|
||||||
"typedoc": "0.28.15",
|
|
||||||
"typedoc-plugin-missing-exports": "4.1.2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
/**
|
|
||||||
* The backend script API is accessible to code notes with the "JS (backend)" language.
|
|
||||||
*
|
|
||||||
* The entire API is exposed as a single global: {@link api}
|
|
||||||
*
|
|
||||||
* @module Backend Script API
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This file creates the entrypoint for TypeDoc that simulates the context from within a
|
|
||||||
* script note on the server side.
|
|
||||||
*
|
|
||||||
* Make sure to keep in line with backend's `script_context.ts`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
export type { default as AbstractBeccaEntity } from "../../server/src/becca/entities/abstract_becca_entity.js";
|
|
||||||
export type { default as BAttachment } from "../../server/src/becca/entities/battachment.js";
|
|
||||||
export type { default as BAttribute } from "../../server/src/becca/entities/battribute.js";
|
|
||||||
export type { default as BBranch } from "../../server/src/becca/entities/bbranch.js";
|
|
||||||
export type { default as BEtapiToken } from "../../server/src/becca/entities/betapi_token.js";
|
|
||||||
export type { BNote };
|
|
||||||
export type { default as BOption } from "../../server/src/becca/entities/boption.js";
|
|
||||||
export type { default as BRecentNote } from "../../server/src/becca/entities/brecent_note.js";
|
|
||||||
export type { default as BRevision } from "../../server/src/becca/entities/brevision.js";
|
|
||||||
|
|
||||||
import BNote from "../../server/src/becca/entities/bnote.js";
|
|
||||||
import BackendScriptApi, { type Api } from "../../server/src/services/backend_script_api.js";
|
|
||||||
|
|
||||||
export type { Api };
|
|
||||||
|
|
||||||
const fakeNote = new BNote();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The `api` global variable allows access to the backend script API, which is documented in {@link Api}.
|
|
||||||
*/
|
|
||||||
export const api: Api = new BackendScriptApi(fakeNote, {});
|
|
||||||
@@ -1,147 +0,0 @@
|
|||||||
process.env.TRILIUM_INTEGRATION_TEST = "memory-no-store";
|
|
||||||
process.env.TRILIUM_RESOURCE_DIR = "../server/src";
|
|
||||||
process.env.NODE_ENV = "development";
|
|
||||||
|
|
||||||
import cls from "@triliumnext/server/src/services/cls.js";
|
|
||||||
import { dirname, join, resolve } from "path";
|
|
||||||
import * as fs from "fs/promises";
|
|
||||||
import * as fsExtra from "fs-extra";
|
|
||||||
import archiver from "archiver";
|
|
||||||
import { WriteStream } from "fs";
|
|
||||||
import { execSync } from "child_process";
|
|
||||||
import BuildContext from "./context.js";
|
|
||||||
|
|
||||||
const DOCS_ROOT = "../../../docs";
|
|
||||||
const OUTPUT_DIR = "../../site";
|
|
||||||
|
|
||||||
async function importAndExportDocs(sourcePath: string, outputSubDir: string) {
|
|
||||||
const note = await importData(sourcePath);
|
|
||||||
|
|
||||||
// Use a meaningful name for the temporary zip file
|
|
||||||
const zipName = outputSubDir || "user-guide";
|
|
||||||
const zipFilePath = `output-${zipName}.zip`;
|
|
||||||
try {
|
|
||||||
const { exportToZip } = (await import("@triliumnext/server/src/services/export/zip.js")).default;
|
|
||||||
const branch = note.getParentBranches()[0];
|
|
||||||
const taskContext = new (await import("@triliumnext/server/src/services/task_context.js")).default(
|
|
||||||
"no-progress-reporting",
|
|
||||||
"export",
|
|
||||||
null
|
|
||||||
);
|
|
||||||
const fileOutputStream = fsExtra.createWriteStream(zipFilePath);
|
|
||||||
await exportToZip(taskContext, branch, "share", fileOutputStream);
|
|
||||||
await waitForStreamToFinish(fileOutputStream);
|
|
||||||
|
|
||||||
// Output to root directory if outputSubDir is empty, otherwise to subdirectory
|
|
||||||
const outputPath = outputSubDir ? join(OUTPUT_DIR, outputSubDir) : OUTPUT_DIR;
|
|
||||||
await extractZip(zipFilePath, outputPath);
|
|
||||||
} finally {
|
|
||||||
if (await fsExtra.exists(zipFilePath)) {
|
|
||||||
await fsExtra.rm(zipFilePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function buildDocsInner() {
|
|
||||||
const i18n = await import("@triliumnext/server/src/services/i18n.js");
|
|
||||||
await i18n.initializeTranslations();
|
|
||||||
|
|
||||||
const sqlInit = (await import("../../server/src/services/sql_init.js")).default;
|
|
||||||
await sqlInit.createInitialDatabase(true);
|
|
||||||
|
|
||||||
// Wait for becca to be loaded before importing data
|
|
||||||
const beccaLoader = await import("../../server/src/becca/becca_loader.js");
|
|
||||||
await beccaLoader.beccaLoaded;
|
|
||||||
|
|
||||||
// Build User Guide
|
|
||||||
console.log("Building User Guide...");
|
|
||||||
await importAndExportDocs(join(__dirname, DOCS_ROOT, "User Guide"), "user-guide");
|
|
||||||
|
|
||||||
// Build Developer Guide
|
|
||||||
console.log("Building Developer Guide...");
|
|
||||||
await importAndExportDocs(join(__dirname, DOCS_ROOT, "Developer Guide"), "developer-guide");
|
|
||||||
|
|
||||||
// Copy favicon.
|
|
||||||
await fs.copyFile("../../apps/website/src/assets/favicon.ico", join(OUTPUT_DIR, "favicon.ico"));
|
|
||||||
await fs.copyFile("../../apps/website/src/assets/favicon.ico", join(OUTPUT_DIR, "user-guide", "favicon.ico"));
|
|
||||||
await fs.copyFile("../../apps/website/src/assets/favicon.ico", join(OUTPUT_DIR, "developer-guide", "favicon.ico"));
|
|
||||||
|
|
||||||
console.log("Documentation built successfully!");
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function importData(path: string) {
|
|
||||||
const buffer = await createImportZip(path);
|
|
||||||
const importService = (await import("../../server/src/services/import/zip.js")).default;
|
|
||||||
const TaskContext = (await import("../../server/src/services/task_context.js")).default;
|
|
||||||
const context = new TaskContext("no-progress-reporting", "importNotes", null);
|
|
||||||
const becca = (await import("../../server/src/becca/becca.js")).default;
|
|
||||||
|
|
||||||
const rootNote = becca.getRoot();
|
|
||||||
if (!rootNote) {
|
|
||||||
throw new Error("Missing root note for import.");
|
|
||||||
}
|
|
||||||
return await importService.importZip(context, buffer, rootNote, {
|
|
||||||
preserveIds: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function createImportZip(path: string) {
|
|
||||||
const inputFile = "input.zip";
|
|
||||||
const archive = archiver("zip", {
|
|
||||||
zlib: { level: 0 }
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log("Archive path is ", resolve(path))
|
|
||||||
archive.directory(path, "/");
|
|
||||||
|
|
||||||
const outputStream = fsExtra.createWriteStream(inputFile);
|
|
||||||
archive.pipe(outputStream);
|
|
||||||
archive.finalize();
|
|
||||||
await waitForStreamToFinish(outputStream);
|
|
||||||
|
|
||||||
try {
|
|
||||||
return await fsExtra.readFile(inputFile);
|
|
||||||
} finally {
|
|
||||||
await fsExtra.rm(inputFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function waitForStreamToFinish(stream: WriteStream) {
|
|
||||||
return new Promise<void>((res, rej) => {
|
|
||||||
stream.on("finish", () => res());
|
|
||||||
stream.on("error", (err) => rej(err));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function extractZip(zipFilePath: string, outputPath: string, ignoredFiles?: Set<string>) {
|
|
||||||
const { readZipFile, readContent } = (await import("@triliumnext/server/src/services/import/zip.js"));
|
|
||||||
await readZipFile(await fs.readFile(zipFilePath), async (zip, entry) => {
|
|
||||||
// We ignore directories since they can appear out of order anyway.
|
|
||||||
if (!entry.fileName.endsWith("/") && !ignoredFiles?.has(entry.fileName)) {
|
|
||||||
const destPath = join(outputPath, entry.fileName);
|
|
||||||
const fileContent = await readContent(zip, entry);
|
|
||||||
|
|
||||||
await fsExtra.mkdirs(dirname(destPath));
|
|
||||||
await fs.writeFile(destPath, fileContent);
|
|
||||||
}
|
|
||||||
|
|
||||||
zip.readEntry();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export default async function buildDocs({ gitRootDir }: BuildContext) {
|
|
||||||
// Build the share theme.
|
|
||||||
execSync(`pnpm run --filter share-theme build`, {
|
|
||||||
stdio: "inherit",
|
|
||||||
cwd: gitRootDir
|
|
||||||
});
|
|
||||||
|
|
||||||
// Trigger the actual build.
|
|
||||||
await new Promise((res, rej) => {
|
|
||||||
cls.init(() => {
|
|
||||||
buildDocsInner()
|
|
||||||
.catch(rej)
|
|
||||||
.then(res);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
export default interface BuildContext {
|
|
||||||
gitRootDir: string;
|
|
||||||
baseDir: string;
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
/**
|
|
||||||
* The front script API is accessible to code notes with the "JS (frontend)" language.
|
|
||||||
*
|
|
||||||
* The entire API is exposed as a single global: {@link api}
|
|
||||||
*
|
|
||||||
* @module Frontend Script API
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This file creates the entrypoint for TypeDoc that simulates the context from within a
|
|
||||||
* script note.
|
|
||||||
*
|
|
||||||
* Make sure to keep in line with frontend's `script_context.ts`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
export type { default as BasicWidget } from "../../client/src/widgets/basic_widget.js";
|
|
||||||
export type { default as FAttachment } from "../../client/src/entities/fattachment.js";
|
|
||||||
export type { default as FAttribute } from "../../client/src/entities/fattribute.js";
|
|
||||||
export type { default as FBranch } from "../../client/src/entities/fbranch.js";
|
|
||||||
export type { default as FNote } from "../../client/src/entities/fnote.js";
|
|
||||||
export type { Api } from "../../client/src/services/frontend_script_api.js";
|
|
||||||
export type { default as NoteContextAwareWidget } from "../../client/src/widgets/note_context_aware_widget.js";
|
|
||||||
export type { default as RightPanelWidget } from "../../client/src/widgets/right_panel_widget.js";
|
|
||||||
|
|
||||||
import FrontendScriptApi, { type Api } from "../../client/src/services/frontend_script_api.js";
|
|
||||||
|
|
||||||
//@ts-expect-error
|
|
||||||
export const api: Api = new FrontendScriptApi();
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="refresh" content="0; url=/user-guide">
|
|
||||||
<title>Redirecting...</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<p>If you are not redirected automatically, <a href="/user-guide">click here</a>.</p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
import { join } from "path";
|
|
||||||
import BuildContext from "./context";
|
|
||||||
import buildSwagger from "./swagger";
|
|
||||||
import { cpSync, existsSync, mkdirSync, rmSync } from "fs";
|
|
||||||
import buildDocs from "./build-docs";
|
|
||||||
import buildScriptApi from "./script-api";
|
|
||||||
|
|
||||||
const context: BuildContext = {
|
|
||||||
gitRootDir: join(__dirname, "../../../"),
|
|
||||||
baseDir: join(__dirname, "../../../site")
|
|
||||||
};
|
|
||||||
|
|
||||||
async function main() {
|
|
||||||
// Clean input dir.
|
|
||||||
if (existsSync(context.baseDir)) {
|
|
||||||
rmSync(context.baseDir, { recursive: true });
|
|
||||||
}
|
|
||||||
mkdirSync(context.baseDir);
|
|
||||||
|
|
||||||
// Start building.
|
|
||||||
await buildDocs(context);
|
|
||||||
buildSwagger(context);
|
|
||||||
buildScriptApi(context);
|
|
||||||
|
|
||||||
// Copy index and 404 files.
|
|
||||||
cpSync(join(__dirname, "index.html"), join(context.baseDir, "index.html"));
|
|
||||||
cpSync(join(context.baseDir, "user-guide/404.html"), join(context.baseDir, "404.html"));
|
|
||||||
}
|
|
||||||
|
|
||||||
main();
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
import { execSync } from "child_process";
|
|
||||||
import BuildContext from "./context";
|
|
||||||
import { join } from "path";
|
|
||||||
|
|
||||||
export default function buildScriptApi({ baseDir, gitRootDir }: BuildContext) {
|
|
||||||
// Generate types
|
|
||||||
execSync(`pnpm typecheck`, { stdio: "inherit", cwd: gitRootDir });
|
|
||||||
|
|
||||||
for (const config of [ "backend", "frontend" ]) {
|
|
||||||
const outDir = join(baseDir, "script-api", config);
|
|
||||||
execSync(`pnpm typedoc --options typedoc.${config}.json --html "${outDir}"`, {
|
|
||||||
stdio: "inherit"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
import BuildContext from "./context";
|
|
||||||
import { join } from "path";
|
|
||||||
import { execSync } from "child_process";
|
|
||||||
import { mkdirSync } from "fs";
|
|
||||||
|
|
||||||
interface BuildInfo {
|
|
||||||
specPath: string;
|
|
||||||
outDir: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const DIR_PREFIX = "rest-api";
|
|
||||||
|
|
||||||
const buildInfos: BuildInfo[] = [
|
|
||||||
{
|
|
||||||
// Paths are relative to Git root.
|
|
||||||
specPath: "apps/server/internal.openapi.yaml",
|
|
||||||
outDir: `${DIR_PREFIX}/internal`
|
|
||||||
},
|
|
||||||
{
|
|
||||||
specPath: "apps/server/etapi.openapi.yaml",
|
|
||||||
outDir: `${DIR_PREFIX}/etapi`
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
export default function buildSwagger({ baseDir, gitRootDir }: BuildContext) {
|
|
||||||
for (const { specPath, outDir } of buildInfos) {
|
|
||||||
const absSpecPath = join(gitRootDir, specPath);
|
|
||||||
const targetDir = join(baseDir, outDir);
|
|
||||||
mkdirSync(targetDir, { recursive: true });
|
|
||||||
execSync(`pnpm redocly build-docs ${absSpecPath} -o ${targetDir}/index.html`, { stdio: "inherit" });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "../../tsconfig.base.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"module": "ESNext",
|
|
||||||
"moduleResolution": "bundler",
|
|
||||||
"target": "ES2020",
|
|
||||||
"outDir": "dist",
|
|
||||||
"strict": false,
|
|
||||||
"types": [
|
|
||||||
"node",
|
|
||||||
"express"
|
|
||||||
],
|
|
||||||
"rootDir": "src",
|
|
||||||
"tsBuildInfoFile": "dist/tsconfig.app.tsbuildinfo"
|
|
||||||
},
|
|
||||||
"include": [
|
|
||||||
"src/**/*.ts",
|
|
||||||
"../server/src/*.d.ts"
|
|
||||||
],
|
|
||||||
"exclude": [
|
|
||||||
"eslint.config.js",
|
|
||||||
"eslint.config.cjs",
|
|
||||||
"eslint.config.mjs"
|
|
||||||
],
|
|
||||||
"references": [
|
|
||||||
{
|
|
||||||
"path": "../server/tsconfig.app.json"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "../desktop/tsconfig.app.json"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "../client/tsconfig.app.json"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "../../tsconfig.base.json",
|
|
||||||
"include": [],
|
|
||||||
"references": [
|
|
||||||
{
|
|
||||||
"path": "../server"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "../client"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "./tsconfig.app.json"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "https://typedoc.org/schema.json",
|
|
||||||
"name": "Trilium Backend API",
|
|
||||||
"entryPoints": [
|
|
||||||
"src/backend_script_entrypoint.ts"
|
|
||||||
],
|
|
||||||
"plugin": [
|
|
||||||
"typedoc-plugin-missing-exports"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "https://typedoc.org/schema.json",
|
|
||||||
"name": "Trilium Frontend API",
|
|
||||||
"entryPoints": [
|
|
||||||
"src/frontend_script_entrypoint.ts"
|
|
||||||
],
|
|
||||||
"plugin": [
|
|
||||||
"typedoc-plugin-missing-exports"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
# The development license key for premium CKEditor features.
|
|
||||||
# Note: This key must only be used for the Trilium Notes project.
|
|
||||||
VITE_CKEDITOR_KEY=eyJhbGciOiJFUzI1NiJ9.eyJleHAiOjE3ODcyNzA0MDAsImp0aSI6IjkyMWE1MWNlLTliNDMtNGRlMC1iOTQwLTc5ZjM2MDBkYjg1NyIsImRpc3RyaWJ1dGlvbkNoYW5uZWwiOiJ0cmlsaXVtIiwiZmVhdHVyZXMiOlsiVFJJTElVTSJdLCJ2YyI6ImU4YzRhMjBkIn0.hny77p-U4-jTkoqbwPytrEar5ylGCWBN7Ez3SlB8i6_mJCBIeCSTOlVQk_JMiOEq3AGykUMHzWXzjdMFwgniOw
|
|
||||||
VITE_CKEDITOR_ENABLE_INSPECTOR=false
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
VITE_CKEDITOR_ENABLE_INSPECTOR=false
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"jsc": {
|
|
||||||
"parser": {
|
|
||||||
"syntax": "typescript"
|
|
||||||
},
|
|
||||||
"target": "es2016"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
import baseConfig from "../../eslint.config.mjs";
|
|
||||||
|
|
||||||
export default [
|
|
||||||
...baseConfig
|
|
||||||
];
|
|
||||||
@@ -1,82 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@triliumnext/client",
|
|
||||||
"version": "0.100.0",
|
|
||||||
"description": "JQuery-based client for TriliumNext, used for both web and desktop (via Electron)",
|
|
||||||
"private": true,
|
|
||||||
"license": "AGPL-3.0-only",
|
|
||||||
"author": {
|
|
||||||
"name": "Trilium Notes Team",
|
|
||||||
"email": "contact@eliandoran.me",
|
|
||||||
"url": "https://github.com/TriliumNext/Trilium"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"build": "cross-env NODE_OPTIONS=--max-old-space-size=4096 vite build",
|
|
||||||
"test": "vitest",
|
|
||||||
"circular-deps": "dpdm -T src/**/*.ts --tree=false --warning=false --skip-dynamic-imports=circular"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@eslint/js": "9.39.1",
|
|
||||||
"@excalidraw/excalidraw": "0.18.0",
|
|
||||||
"@fullcalendar/core": "6.1.19",
|
|
||||||
"@fullcalendar/daygrid": "6.1.19",
|
|
||||||
"@fullcalendar/interaction": "6.1.19",
|
|
||||||
"@fullcalendar/list": "6.1.19",
|
|
||||||
"@fullcalendar/multimonth": "6.1.19",
|
|
||||||
"@fullcalendar/timegrid": "6.1.19",
|
|
||||||
"@maplibre/maplibre-gl-leaflet": "0.1.3",
|
|
||||||
"@mermaid-js/layout-elk": "0.2.0",
|
|
||||||
"@mind-elixir/node-menu": "5.0.1",
|
|
||||||
"@popperjs/core": "2.11.8",
|
|
||||||
"@triliumnext/ckeditor5": "workspace:*",
|
|
||||||
"@triliumnext/codemirror": "workspace:*",
|
|
||||||
"@triliumnext/commons": "workspace:*",
|
|
||||||
"@triliumnext/highlightjs": "workspace:*",
|
|
||||||
"@triliumnext/share-theme": "workspace:*",
|
|
||||||
"@triliumnext/split.js": "workspace:*",
|
|
||||||
"autocomplete.js": "0.38.1",
|
|
||||||
"bootstrap": "5.3.8",
|
|
||||||
"boxicons": "2.1.4",
|
|
||||||
"clsx": "2.1.1",
|
|
||||||
"color": "5.0.3",
|
|
||||||
"debounce": "3.0.0",
|
|
||||||
"draggabilly": "3.0.0",
|
|
||||||
"force-graph": "1.51.0",
|
|
||||||
"globals": "16.5.0",
|
|
||||||
"i18next": "25.6.3",
|
|
||||||
"i18next-http-backend": "3.0.2",
|
|
||||||
"jquery": "3.7.1",
|
|
||||||
"jquery.fancytree": "2.38.5",
|
|
||||||
"jsplumb": "2.15.6",
|
|
||||||
"katex": "0.16.25",
|
|
||||||
"knockout": "3.5.1",
|
|
||||||
"leaflet": "1.9.4",
|
|
||||||
"leaflet-gpx": "2.2.0",
|
|
||||||
"mark.js": "8.11.1",
|
|
||||||
"marked": "17.0.1",
|
|
||||||
"mermaid": "11.12.1",
|
|
||||||
"mind-elixir": "5.3.7",
|
|
||||||
"normalize.css": "8.0.1",
|
|
||||||
"panzoom": "9.4.3",
|
|
||||||
"preact": "10.27.2",
|
|
||||||
"react-i18next": "16.3.5",
|
|
||||||
"reveal.js": "5.2.1",
|
|
||||||
"svg-pan-zoom": "3.6.2",
|
|
||||||
"tabulator-tables": "6.3.1",
|
|
||||||
"vanilla-js-wheel-zoom": "9.0.4"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@ckeditor/ckeditor5-inspector": "5.0.0",
|
|
||||||
"@preact/preset-vite": "2.10.2",
|
|
||||||
"@types/bootstrap": "5.2.10",
|
|
||||||
"@types/jquery": "3.5.33",
|
|
||||||
"@types/leaflet": "1.9.21",
|
|
||||||
"@types/leaflet-gpx": "1.3.8",
|
|
||||||
"@types/mark.js": "8.11.12",
|
|
||||||
"@types/reveal.js": "5.2.1",
|
|
||||||
"@types/tabulator-tables": "6.3.0",
|
|
||||||
"copy-webpack-plugin": "13.0.1",
|
|
||||||
"happy-dom": "20.0.11",
|
|
||||||
"script-loader": "0.7.2",
|
|
||||||
"vite-plugin-static-copy": "3.1.4"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
import packageJson from "../package.json" with { type: "json" };
|
|
||||||
|
|
||||||
export default `assets/v${packageJson.version}`;
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 10 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user