Merge branch 'main' into history_diff

This commit is contained in:
SiriusXT 2025-09-04 17:37:00 +08:00
commit 7eeb43a83b
138 changed files with 1675 additions and 6233 deletions

1
.env
View File

@ -1 +0,0 @@
NODE_OPTIONS=--max_old_space_size=4096

View File

@ -86,7 +86,7 @@ runs:
APPLE_ID_PASSWORD: ${{ env.APPLE_ID_PASSWORD }}
WINDOWS_SIGN_EXECUTABLE: ${{ env.WINDOWS_SIGN_EXECUTABLE }}
TRILIUM_ARTIFACT_NAME_HINT: TriliumNotes-${{ github.ref_name }}-${{ inputs.os }}-${{ inputs.arch }}
run: pnpm nx --project=desktop electron-forge:make -- --arch=${{ inputs.arch }} --platform=${{ inputs.forge_platform }}
run: pnpm run --filter desktop electron-forge:make --arch=${{ inputs.arch }} --platform=${{ inputs.forge_platform }}
# Add DMG signing step
- name: Sign DMG

View File

@ -23,7 +23,7 @@ runs:
shell: bash
run: |
pnpm run chore:update-build-info
pnpm nx --project=server package
pnpm run --filter server package
- name: Prepare artifacts
shell: bash
run: |

View File

@ -1,40 +0,0 @@
---
applyTo: '**'
---
// This file is automatically generated by Nx Console
You are in an nx workspace using Nx 21.3.9 and pnpm as the package manager.
You have access to the Nx MCP server and the tools it provides. Use them. Follow these guidelines in order to best help the user:
# General Guidelines
- When answering questions, use the nx_workspace tool first to gain an understanding of the workspace architecture
- For questions around nx configuration, best practices or if you're unsure, use the nx_docs tool to get relevant, up-to-date docs!! Always use this instead of assuming things about nx configuration
- If the user needs help with an Nx configuration or project graph error, use the 'nx_workspace' tool to get any errors
- To help answer questions about the workspace structure or simply help with demonstrating how tasks depend on each other, use the 'nx_visualize_graph' tool
# Generation Guidelines
If the user wants to generate something, use the following flow:
- learn about the nx workspace and any specifics the user needs by using the 'nx_workspace' tool and the 'nx_project_details' tool if applicable
- get the available generators using the 'nx_generators' tool
- decide which generator to use. If no generators seem relevant, check the 'nx_available_plugins' tool to see if the user could install a plugin to help them
- get generator details using the 'nx_generator_schema' tool
- you may use the 'nx_docs' tool to learn more about a specific generator or technology if you're unsure
- decide which options to provide in order to best complete the user's request. Don't make any assumptions and keep the options minimalistic
- open the generator UI using the 'nx_open_generate_ui' tool
- wait for the user to finish the generator
- read the generator log file using the 'nx_read_generator_log' tool
- use the information provided in the log file to answer the user's question or continue with what they were doing
# Running Tasks Guidelines
If the user wants help with tasks or commands (which include keywords like "test", "build", "lint", or other similar actions), use the following flow:
- Use the 'nx_current_running_tasks_details' tool to get the list of tasks (this can include tasks that were completed, stopped or failed).
- If there are any tasks, ask the user if they would like help with a specific task then use the 'nx_current_running_task_output' tool to get the terminal output for that task/command
- Use the terminal output from 'nx_current_running_task_output' to see what's wrong and help the user fix their problem. Use the appropriate tools if necessary
- If the user would like to rerun the task or command, always use `nx run <taskId>` to rerun in the terminal. This will ensure that the task will run in the nx context and will be run the same way it originally executed
- If the task was marked as "continuous" do not offer to rerun the task. This task is already running and the user can see the output in the terminal. You can use 'nx_current_running_task_output' to get the output of the task to verify the output.

View File

@ -19,33 +19,9 @@ permissions:
pull-requests: write # for PR comments
jobs:
check-affected:
name: Check affected jobs (NX)
runs-on: ubuntu-latest
steps:
- name: Checkout the repository
uses: actions/checkout@v5
with:
fetch-depth: 0 # needed for https://github.com/marketplace/actions/nx-set-shas
- uses: pnpm/action-setup@v4
- name: Set up node & dependencies
uses: actions/setup-node@v4
with:
node-version: 22
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- uses: nrwl/nx-set-shas@v4
- name: Check affected
run: pnpm nx affected --verbose -t typecheck build rebuild-deps test-build
test_dev:
name: Test development
runs-on: ubuntu-latest
needs:
- check-affected
steps:
- name: Checkout the repository
uses: actions/checkout@v5
@ -66,7 +42,6 @@ jobs:
runs-on: ubuntu-latest
needs:
- test_dev
- check-affected
steps:
- uses: actions/checkout@v5
- uses: pnpm/action-setup@v4
@ -75,7 +50,7 @@ jobs:
- name: Update build info
run: pnpm run chore:update-build-info
- name: Trigger client build
run: pnpm nx run client:build
run: pnpm client:build
- name: Send client bundle stats to RelativeCI
if: false
uses: relative-ci/agent-action@v3
@ -83,7 +58,7 @@ jobs:
webpackStatsFile: ./apps/client/dist/webpack-stats.json
key: ${{ secrets.RELATIVE_CI_CLIENT_KEY }}
- name: Trigger server build
run: pnpm nx run server:build
run: pnpm run server:build
- uses: docker/setup-buildx-action@v3
- uses: docker/build-push-action@v6
with:
@ -95,7 +70,6 @@ jobs:
runs-on: ubuntu-latest
needs:
- build_docker
- check-affected
strategy:
matrix:
include:
@ -112,7 +86,7 @@ jobs:
- name: Update build info
run: pnpm run chore:update-build-info
- name: Trigger build
run: pnpm nx run server:build
run: pnpm server:build
- name: Set IMAGE_NAME to lowercase
run: echo "IMAGE_NAME=${IMAGE_NAME,,}" >> $GITHUB_ENV

View File

@ -82,7 +82,7 @@ jobs:
require-healthy: true
- name: Run Playwright tests
run: TRILIUM_DOCKER=1 TRILIUM_PORT=8082 pnpm exec nx run server-e2e:e2e
run: TRILIUM_DOCKER=1 TRILIUM_PORT=8082 pnpm --filter=server-e2e e2e
- name: Upload Playwright trace
if: failure()

View File

@ -57,7 +57,6 @@ jobs:
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- uses: nrwl/nx-set-shas@v4
- name: Update nightly version
run: npm run chore:ci-update-nightly-version
- name: Run the build

View File

@ -19,12 +19,6 @@ jobs:
filter: tree:0
fetch-depth: 0
# This enables task distribution via Nx Cloud
# Run this command as early as possible, before dependencies are installed
# Learn more at https://nx.dev/ci/reference/nx-cloud-cli#npx-nxcloud-startcirun
# Connect your workspace by running "nx connect" and uncomment this line to enable task distribution
# - run: npx nx-cloud start-ci-run --distribute-on="3 linux-medium-js" --stop-agents-after="e2e-ci"
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
@ -34,10 +28,12 @@ jobs:
- name: Install dependencies
run: pnpm install --frozen-lockfile
- run: pnpm exec playwright install --with-deps
- uses: nrwl/nx-set-shas@v4
# Prepend any command with "nx-cloud record --" to record its logs to Nx Cloud
# - run: npx nx-cloud record -- echo Hello World
# Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected
# When you enable task distribution, run the e2e-ci task instead of e2e
- run: pnpm exec nx affected -t e2e --exclude desktop-e2e
- run: pnpm --filter server-e2e e2e
- name: Upload test report
if: failure()
uses: actions/upload-artifact@v4
with:
name: e2e report
path: apps/server-e2e/test-output

View File

@ -41,7 +41,6 @@ jobs:
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- uses: nrwl/nx-set-shas@v4
- name: Run the build
uses: ./.github/actions/build-electron
with:

6
.gitignore vendored
View File

@ -1,4 +1,5 @@
# See https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files for more about ignoring files.
/.cache
# compiled output
dist
@ -32,14 +33,11 @@ testem.log
.DS_Store
Thumbs.db
.nx/cache
.nx/workspace-data
vite.config.*.timestamp*
vitest.config.*.timestamp*
test-output
apps/*/data
apps/*/data*
apps/*/out
upload

View File

@ -5,7 +5,6 @@
"lokalise.i18n-ally",
"ms-azuretools.vscode-docker",
"ms-playwright.playwright",
"nrwl.angular-console",
"redhat.vscode-yaml",
"tobermory.es6-string-html",
"vitest.explorer",

8
.vscode/mcp.json vendored
View File

@ -1,8 +0,0 @@
{
"servers": {
"nx-mcp": {
"type": "http",
"url": "http://localhost:9461/mcp"
}
}
}

View File

@ -35,6 +35,5 @@
"docs/**/*.png": true,
"apps/server/src/assets/doc_notes/**": true,
"apps/edit-docs/demo/**": true
},
"nxConsole.generateAiAgentRules": true
}
}

View File

@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## 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 NX, with multiple applications and shared packages.
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
@ -14,12 +14,9 @@ Trilium Notes is a hierarchical note-taking application with advanced features l
### Running Applications
- `pnpm run server:start` - Start development server (http://localhost:8080)
- `pnpm nx run server:serve` - Alternative server start command
- `pnpm nx run desktop:serve` - Run desktop Electron app
- `pnpm run server:start-prod` - Run server in production mode
### Building
- `pnpm nx build <project>` - Build specific project (server, client, desktop, etc.)
- `pnpm run client:build` - Build client application
- `pnpm run server:build` - Build server application
- `pnpm run electron:build` - Build desktop application
@ -28,13 +25,8 @@ Trilium Notes is a hierarchical note-taking application with advanced features l
- `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 nx test <project>` - Run tests for specific project
- `pnpm coverage` - Generate coverage reports
### Linting & Type Checking
- `pnpm nx run <project>:lint` - Lint specific project
- `pnpm nx run <project>:typecheck` - Type check specific project
## Architecture Overview
### Monorepo Structure
@ -94,7 +86,6 @@ Frontend uses a widget system (`apps/client/src/widgets/`):
- `apps/server/src/assets/db/schema.sql` - Core database structure
4. **Configuration**:
- `nx.json` - NX workspace configuration
- `package.json` - Project dependencies and scripts
## Note Types and Features
@ -154,7 +145,7 @@ Trilium provides powerful user scripting capabilities:
- Update schema in `apps/server/src/assets/db/schema.sql`
## Build System Notes
- Uses NX for monorepo management with build caching
- Uses pnpm for monorepo management
- Vite for fast development builds
- ESBuild for production optimization
- pnpm workspaces for dependency management

View File

@ -142,7 +142,7 @@ Download the repository, install dependencies using `pnpm` and then run the envi
git clone https://github.com/TriliumNext/Trilium.git
cd Trilium
pnpm install
pnpm nx run edit-docs:edit-docs
pnpm edit-docs:edit-docs
```
### Building the Executable
@ -151,7 +151,7 @@ Download the repository, install dependencies using `pnpm` and then build the de
git clone https://github.com/TriliumNext/Trilium.git
cd Trilium
pnpm install
pnpm nx --project=desktop electron-forge:make -- --arch=x64 --platform=win32
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).

View File

@ -9,6 +9,11 @@
"email": "contact@eliandoran.me",
"url": "https://github.com/TriliumNext/Notes"
},
"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.34.0",
"@excalidraw/excalidraw": "0.18.0",
@ -71,18 +76,5 @@
"happy-dom": "18.0.1",
"script-loader": "0.7.2",
"vite-plugin-static-copy": "3.1.2"
},
"nx": {
"name": "client",
"targets": {
"serve": {
"dependsOn": [
"^build"
]
},
"circular-deps": {
"command": "pnpx dpdm -T {projectRoot}/src/**/*.ts --tree=false --warning=false --skip-dynamic-imports=circular"
}
}
}
}

View File

@ -10,7 +10,7 @@ import { t } from "./services/i18n.js";
import options from "./services/options.js";
import type ElectronRemote from "@electron/remote";
import type Electron from "electron";
import "./stylesheets/bootstrap.scss";
import "bootstrap/dist/css/bootstrap.min.css";
import "boxicons/css/boxicons.min.css";
import "autocomplete.js/index_jquery.js";

View File

@ -1,4 +1,4 @@
import "./stylesheets/bootstrap.scss";
import "bootstrap/dist/css/bootstrap.min.css";
// @ts-ignore - module = undefined
// Required for correct loading of scripts in Electron

View File

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

View File

@ -48,6 +48,6 @@ function getUrl(docNameValue: string, language: string) {
// Cannot have spaces in the URL due to how JQuery.load works.
docNameValue = docNameValue.replaceAll(" ", "%20");
const basePath = window.glob.isDev ? new URL(window.glob.assetPath).pathname : window.glob.assetPath;
const basePath = window.glob.isDev ? window.glob.assetPath + "/.." : window.glob.assetPath;
return `${basePath}/doc_notes/${language}/${docNameValue}.html`;
}

View File

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

View File

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

View File

@ -1,6 +1,6 @@
import "normalize.css";
import "boxicons/css/boxicons.min.css";
import "@triliumnext/ckeditor5/content.css";
import "@triliumnext/ckeditor5/src/theme/ck-content.css";
import "@triliumnext/share-theme/styles/index.css";
import "@triliumnext/share-theme/scripts/index.js";

View File

@ -1,2 +0,0 @@
/* Import all of Bootstrap's CSS */
@use "bootstrap/scss/bootstrap";

View File

@ -1134,6 +1134,7 @@ a.external:not(.no-arrow):after, a[href^="http://"]:not(.no-arrow):after, a[href
.toast-body {
white-space: preserve-breaks;
overflow: hidden;
}
.ck-mentions .ck-button {
@ -1463,7 +1464,7 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
cursor: pointer;
border: none;
color: var(--launcher-pane-text-color);
background-color: var(--launcher-pane-background-color);
background: transparent;
flex-shrink: 0;
}
@ -2366,3 +2367,12 @@ footer.webview-footer button {
content: "\ec24";
transform: rotate(180deg);
}
/* CK Edito */
/* Insert text snippet: limit the width of the listed items to avoid overly long names */
:root body.desktop div.ck-template-form li.ck-list__item .ck-template-form__text-part > span {
max-width: 25vw;
overflow: hidden;
text-overflow: ellipsis;
}

View File

@ -18,7 +18,7 @@
--main-text-color: #ccc;
--main-border-color: #454545;
--subtle-border-color: #313131;
--dropdown-border-color: #292929;
--dropdown-border-color: #404040;
--dropdown-shadow-opacity: 0.6;
--dropdown-item-icon-destructive-color: #de6e5b;
--disabled-tooltip-icon-color: #7fd2ef;

View File

@ -115,7 +115,7 @@
--quick-search-focus-border: #00000029;
--quick-search-focus-background: #ffffff80;
--quick-search-focus-color: #000;
--quick-search-result-content-background: #00000017;
--quick-search-result-content-background: #0000000f;
--quick-search-result-highlight-color: #c65050;
--left-pane-collapsed-border-color: #0000000d;

View File

@ -329,6 +329,8 @@ body.mobile .dropdown-menu .dropdown-item.submenu-open .dropdown-toggle::after {
#toast-container .toast .toast-body {
flex-grow: 1;
overflow: hidden;
text-overflow: ellipsis;
}
/*

View File

@ -5,7 +5,8 @@
button.btn.btn-primary,
button.btn.btn-secondary,
button.btn.btn-sm:not(.select-button),
button.btn.btn-success {
button.btn.btn-success,
button.ck.ck-button:is(.ck-button-action, .ck-button-save, .ck-button-cancel, .ck-button-replaceall, .ck-button-replace).ck-button_with-text {
display: inline-flex;
align-items: center;
justify-content: center;
@ -21,7 +22,8 @@ button.btn.btn-success {
button.btn.btn-primary:hover,
button.btn.btn-secondary:hover,
button.btn.btn-sm:not(.select-button):hover,
button.btn.btn-success:hover {
button.btn.btn-success:hover,
button.ck.ck-button:is(.ck-button-action, .ck-button-save, .ck-button-cancel, .ck-button-replaceall, .ck-button-replace).ck-button_with-text:not(.ck-disabled):hover {
background: var(--cmd-button-hover-background-color);
color: var(--cmd-button-hover-text-color);
}
@ -29,7 +31,8 @@ button.btn.btn-success:hover {
button.btn.btn-primary:active,
button.btn.btn-secondary:active,
button.btn.btn-sm:not(.select-button):active,
button.btn.btn-success:active {
button.btn.btn-success:active,
button.ck.ck-button:is(.ck-button-action, .ck-button-save, .ck-button-cancel, .ck-button-replaceall, .ck-button-replace).ck-button_with-text:not(.ck-disabled):active {
opacity: 0.85;
box-shadow: unset;
background: var(--cmd-button-background-color) !important;
@ -40,14 +43,16 @@ button.btn.btn-success:active {
button.btn.btn-primary:disabled,
button.btn.btn-secondary:disabled,
button.btn.btn-sm:not(.select-button):disabled,
button.btn.btn-success:disabled {
button.btn.btn-success:disabled,
button.ck.ck-button:is(.ck-button-action, .ck-button-save, .ck-button-cancel, .ck-button-replaceall, .ck-button-replace).ck-button_with-text.ck-disabled {
opacity: var(--cmd-button-disabled-opacity);
}
button.btn.btn-primary:focus-visible,
button.btn.btn-secondary:focus-visible,
button.btn.btn-sm:not(.select-button):focus-visible,
button.btn.btn-success:focus-visible {
button.btn.btn-success:focus-visible,
button.ck.ck-button:is(.ck-button-action, .ck-button-save, .ck-button-cancel, .ck-button-replaceall, .ck-button-replace).ck-button_with-text:not(.ck-disabled):focus-visible {
outline: 2px solid var(--input-focus-outline-color);
}
@ -149,8 +154,11 @@ input[type="password"],
input[type="date"],
input[type="time"],
input[type="datetime-local"],
:root input.ck.ck-input-text,
:root input.ck.ck-input-number,
textarea.form-control,
textarea,
:root textarea.ck.ck-textarea,
.tn-input-field {
outline: 3px solid transparent;
outline-offset: 6px;
@ -167,8 +175,11 @@ input[type="password"]:hover,
input[type="date"]:hover,
input[type="time"]:hover,
input[type="datetime-local"]:hover,
:root input.ck.ck-input-text:not([readonly="true"]):hover,
:root input.ck.ck-input-number:not([readonly="true"]):hover,
textarea.form-control:hover,
textarea:hover,
:root textarea.ck.ck-textarea:hover,
.tn-input-field:hover {
background: var(--input-hover-background);
color: var(--input-hover-color);
@ -181,8 +192,11 @@ input[type="password"]:focus,
input[type="date"]:focus,
input[type="time"]:focus,
input[type="datetime-local"]:focus,
:root input.ck.ck-input-text:focus,
:root input.ck.ck-input-number:focus,
textarea.form-control:focus,
textarea:focus,
:root textarea.ck.ck-textarea:focus,
.tn-input-field:focus,
.tn-input-field:focus-within {
box-shadow: unset;

View File

@ -4,6 +4,7 @@
:root {
--ck-font-face: var(--main-font-family);
--ck-input-label-height: 1.5em;
}
/*
@ -307,6 +308,11 @@
fill: black !important;
}
/* Hex color input box prefix */
:root .ck.ck-color-selector .ck-color-picker__hash-view {
margin-top: var(--ck-input-label-height);
}
/* Numbered list */
:root .ck.ck-list-properties_with-numbered-properties .ck.ck-list-styles-list {
@ -363,19 +369,86 @@
color: var(--accent);
}
/* Action buttons */
/* Text snippet dropdown */
:root .ck-link-actions button.ck-button,
:root .ck-link-form button.ck-button {
--ck-border-radius: 6px;
background: transparent;
box-shadow: unset;
div.ck-template-form {
padding: 8px;
}
:root .ck-link-actions button.ck-button:hover,
:root .ck-link-form button.ck-button:hover {
background: var(--hover-item-background-color);
div.ck-template-form .ck-labeled-field-view {
margin-bottom: 8px;
}
/* Template item */
:root div.ck-template-form li.ck-list__item button.ck-template-button {
padding: 4px 8px;
}
/* Template icon */
:root .ck-template-form .ck-button__icon {
--ck-spacing-medium: 2px;
}
:root div.ck-template-form .note-icon {
color: var(--menu-item-icon-color);
}
/* Template name */
div.ck-template-form .ck-template-form__text-part {
color: var(--hover-item-text-color);
font-size: .9rem;
}
div.ck-template-form .ck-template-form__text-part mark {
background: unset;
color: var(--quick-search-result-highlight-color);
font-weight: bold;
}
/* Template description */
:root div.ck-template-form .ck-template-form__description {
opacity: .5;
font-size: .9em;
}
/* Messages */
div.ck-template-form .ck-search__info > span {
line-height: initial;
color: var(--muted-text-color);
}
div.ck-template-form .ck-search__info span:nth-child(2) {
display: block;
opacity: .5;
margin-top: 8px;
font-size: .9em;
}
/* Link dropdown */
:root .ck.ck-form.ck-link-form ul.ck-link-form__providers-list {
border-top: none;
}
/* Math popup */
.ck-math-form .ck-labeled-field-view {
--ck-input-label-height: 0;
margin-inline-end: 8px;
}
/* Emoji dropdown */
.ck-emoji-picker-form .ck-emoji__search .ck-button_with-text:not(.ck-list-item-button) {
margin-top: var(--ck-input-label-height);
}
/* Find and replace dialog */
.ck-find-and-replace-form .ck-find-and-replace-form__inputs button {
margin-top: var(--ck-input-label-height);
}
/* Mention list (the autocompletion list for emojis, labels and relations) */
@ -392,6 +465,58 @@
background: transparent;
}
/*
* FORMS
*/
/*
* Buttons
*/
button.ck.ck-button:is(.ck-button-action, .ck-button-save, .ck-button-cancel).ck-button_with-text {
--ck-color-text: var(--cmd-button-text-color);
min-width: 60px;
font-weight: 500;
}
/*
* Text boxes
*/
.ck.ck-labeled-field-view {
padding-top: var(--ck-input-label-height) !important; /* Create space for the label */
}
.ck.ck-labeled-field-view > .ck.ck-labeled-field-view__input-wrapper > label.ck.ck-label {
/* Move the label above the text box regardless of the text box state */
transform: translate(0, calc(-.2em - var(--ck-input-label-height))) !important;
padding-left: 0 !important;
background: transparent;
font-size: .85em;
font-weight: 600;
}
:root input.ck.ck-input-text[readonly="true"] {
cursor: not-allowed;
background: var(--input-background-color);
}
/* Forms */
:root .ck.ck-form__row.ck-form__row_with-submit > :not(:first-child) {
margin-inline-start: 16px;
}
.ck.ck-form__row_with-submit button {
margin-top: var(--ck-input-label-height);
}
.ck.ck-form__header {
border-bottom: none;
}
/*
* EDITOR'S CONTENT
*/

View File

@ -59,8 +59,7 @@ body.background-effects.platform-win32.layout-vertical {
}
body.background-effects.platform-win32,
body.background-effects.platform-win32 #root-widget,
body.background-effects.platform-win32 #launcher-pane .launcher-button {
body.background-effects.platform-win32 #root-widget {
background: transparent !important;
}
@ -575,31 +574,20 @@ div.quick-search .search-button.show {
* Quick search results
*/
div.quick-search .dropdown-menu {
--quick-search-item-delimiter-color: transparent;
--menu-item-icon-vert-offset: -.065em;
}
/* Item */
.quick-search .dropdown-menu *.dropdown-item {
padding: 8px 12px !important;
}
/* Note icon */
.quick-search .dropdown-menu .dropdown-item > .bx {
position: relative;
top: 1px;
}
.quick-search .quick-search-item-icon {
vertical-align: text-bottom;
}
/* Note title */
.quick-search .dropdown-menu .dropdown-item > a {
color: var(--menu-text-color);
}
.quick-search .dropdown-menu .dropdown-item > a:hover {
--hover-item-background-color: transparent;
text-decoration: underline;
}
/* Note path */
.quick-search .dropdown-menu small {
display: block;
@ -622,9 +610,8 @@ div.quick-search .search-button.show {
font-weight: 600;
}
/* Divider line */
.quick-search .dropdown-item::after {
display: none;
.quick-search div.dropdown-divider {
margin: 8px 0;
}
/*
@ -899,6 +886,80 @@ body.layout-horizontal .tab-row-container {
border-bottom: 1px solid var(--launcher-pane-horiz-border-color);
}
body.electron.background-effects.layout-horizontal .tab-row-container {
border-bottom: unset !important;
}
body.electron.background-effects.layout-horizontal .note-tab-wrapper {
top: 1px;
}
body.electron.background-effects.layout-horizontal .tab-row-container .toggle-button {
position: relative;
}
body.electron.background-effects.layout-horizontal .tab-row-container .toggle-button:after {
content: "";
position: absolute;
bottom: 0;
left: -10px;
right: -10px;
top: 29px;
height: 1px;
border-bottom: 1px solid var(--launcher-pane-horiz-border-color);
}
body.electron.background-effects.layout-horizontal .tab-row-container .tab-scroll-button-left,
body.electron.background-effects.layout-horizontal .tab-row-container .tab-scroll-button-right {
position: relative;
}
body.electron.background-effects.layout-horizontal .tab-row-container .tab-scroll-button-left:after,
body.electron.background-effects.layout-horizontal .tab-row-container .tab-scroll-button-right:after {
content: "";
position: absolute;
bottom: 0;
left: 0px;
right: 0px;
height: 1px;
border-bottom: 1px solid var(--launcher-pane-horiz-border-color);
}
body.electron.background-effects.layout-horizontal .tab-row-container .note-tab[active]:before {
content: "";
position: absolute;
bottom: 0;
left: -32768px;
top: var(--tab-height);
right: calc(100% - 1px);
height: 1px;
border-bottom: 1px solid var(--launcher-pane-horiz-border-color);
}
body.electron.background-effects.layout-horizontal .tab-row-container .note-tab[active]:after {
content: "";
position: absolute;
bottom: 0;
left: 100%;
top: var(--tab-height);
right: 0;
width: 100vw;
height: 1px;
border-bottom: 1px solid var(--launcher-pane-horiz-border-color);
}
body.electron.background-effects.layout-horizontal .tab-row-container .note-new-tab:before {
content: "";
position: absolute;
bottom: 0;
left: -4px;
top: calc(var(--tab-height), -1);
right: 0;
width: 100vw;
height: 1px;
border-bottom: 1px solid var(--launcher-pane-horiz-border-color);
}
body.layout-vertical.electron.platform-darwin .tab-row-container {
border-bottom: 1px solid var(--subtle-border-color);
}

View File

@ -15,13 +15,15 @@ const TPL = /*html*/`
padding: 10px 10px 10px 0px;
height: 50px;
}
.quick-search button, .quick-search input {
border: 0;
font-size: 100% !important;
}
.quick-search .dropdown-menu {
--quick-search-item-delimiter-color: var(--dropdown-border-color);
max-height: 80vh;
min-width: 400px;
max-width: 720px;
@ -38,14 +40,14 @@ const TPL = /*html*/`
position: relative;
}
.quick-search .dropdown-item:not(:last-child)::after {
.quick-search .dropdown-item + .dropdown-item::after {
content: '';
position: absolute;
left: 0;
bottom: 0;
top: 0;
width: 100%;
height: 1px;
background: var(--dropdown-border-color);
border-bottom: 1px solid var(--quick-search-item-delimiter-color);
}
.quick-search .dropdown-item:last-child::after {
@ -92,6 +94,8 @@ const TPL = /*html*/`
background-color: var(--accented-background-color);
color: var(--main-text-color);
font-size: .85em;
overflow: hidden;
text-overflow: ellipsis;
}
/* Search result highlighting */
@ -106,6 +110,10 @@ const TPL = /*html*/`
margin: 0;
}
.quick-search .bx-loader {
margin-inline-end: 4px;
}
</style>
<div class="input-group-prepend">
@ -220,7 +228,11 @@ export default class QuickSearchWidget extends BasicWidget {
this.isLoadingMore = false;
this.$dropdownMenu.empty();
this.$dropdownMenu.append(`<span class="dropdown-item disabled"><span class="bx bx-loader bx-spin"></span>${t("quick-search.searching")}</span>`);
this.$dropdownMenu.append(`
<span class="dropdown-item disabled">
<span class="bx bx-loader bx-spin"></span>
${t("quick-search.searching")}
</span>`);
const { searchResultNoteIds, searchResults, error } = await server.get<QuickSearchResponse>(`quick-search/${encodeURIComponent(searchString)}`);

View File

@ -388,7 +388,7 @@ async function setupFonts() {
if (!glob.isDev) {
path = `${window.location.pathname}/node_modules/@excalidraw/excalidraw/dist/prod`;
} else {
path = (await import("../../../node_modules/@excalidraw/excalidraw/dist/prod/fonts/Excalifont/Excalifont-Regular-a88b72a24fb54c9f94e3b5fdaa7481c9.woff2?url")).default;
path = (await import("../../../../../node_modules/@excalidraw/excalidraw/dist/prod/fonts/Excalifont/Excalifont-Regular-a88b72a24fb54c9f94e3b5fdaa7481c9.woff2?url")).default;
let pathComponents = path.split("/");
path = pathComponents.slice(0, pathComponents.length - 2).join("/");
}

View File

@ -4,7 +4,7 @@ import { buildExtraCommands, type EditorConfig, PREMIUM_PLUGINS } from "@trilium
import { getHighlightJsNameForMime } from "../../../services/mime_types.js";
import options from "../../../services/options.js";
import { ensureMimeTypesForHighlighting, isSyntaxHighlightEnabled } from "../../../services/syntax_highlight.js";
import emojiDefinitionsUrl from "@triliumnext/ckeditor5/emoji_definitions/en.json?url";
import emojiDefinitionsUrl from "@triliumnext/ckeditor5/src/emoji_definitions/en.json?url";
import { copyTextWithToast } from "../../../services/clipboard_ext.js";
import getTemplates from "./snippets.js";
import { t } from "../../../services/i18n.js";

View File

@ -1,5 +1,6 @@
import utils from "../../../services/utils.js";
import options from "../../../services/options.js";
import IconAlignCenter from "@ckeditor/ckeditor5-icons/theme/icons/align-center.svg?raw";
const TEXT_FORMATTING_GROUP = {
label: "Text formatting",
@ -77,7 +78,7 @@ export function buildClassicToolbar(multilineToolbar: boolean) {
items: ["imageUpload", "|", "link", "bookmark", "internallink", "includeNote", "|", "specialCharacters", "emoji", "math", "mermaid", "horizontalLine", "pageBreak", "dateTime"]
},
"|",
"alignment",
buildAlignmentToolbar(),
"outdent",
"indent",
"|",
@ -134,7 +135,7 @@ export function buildFloatingToolbar() {
items: ["link", "bookmark", "internallink", "includeNote", "|", "math", "mermaid", "horizontalLine", "pageBreak", "dateTime"]
},
"|",
"alignment",
buildAlignmentToolbar(),
"outdent",
"indent",
"|",
@ -147,3 +148,11 @@ export function buildFloatingToolbar() {
]
};
}
function buildAlignmentToolbar() {
return {
label: "Alignment",
icon: IconAlignCenter,
items: ["alignment:left", "alignment:center", "alignment:right", "|", "alignment:justify"]
};
}

View File

@ -12,7 +12,6 @@ import { buildSelectedBackgroundColor } from "../../components/touch_bar.js";
import { buildConfig, BuildEditorOptions, OPEN_SOURCE_LICENSE_KEY } from "./ckeditor/config.js";
import type FNote from "../../entities/fnote.js";
import { PopupEditor, ClassicEditor, EditorWatchdog, type CKTextEditor, type MentionFeed, type WatchdogConfig, EditorConfig } from "@triliumnext/ckeditor5";
import "@triliumnext/ckeditor5/index.css";
import { updateTemplateCache } from "./ckeditor/snippets.js";
const TPL = /*html*/`

View File

@ -2,26 +2,23 @@
import { join, resolve } from 'path';
import { defineConfig, type Plugin } from 'vite';
import { viteStaticCopy } from 'vite-plugin-static-copy'
import asset_path from './src/asset_path';
import webpackStatsPlugin from 'rollup-plugin-webpack-stats';
import preact from "@preact/preset-vite";
const assets = [ "assets", "stylesheets", "fonts", "translations" ];
export default defineConfig(() => ({
root: __dirname,
cacheDir: '../../node_modules/.vite/apps/client',
base: process.env.NODE_ENV === "production" ? "" : asset_path,
server: {
port: 4200,
host: 'localhost',
},
preview: {
port: 4300,
host: 'localhost',
},
plugins: [
preact(),
const isDev = process.env.NODE_ENV === "development";
let plugins: any = [
preact({
babel: {
compact: !isDev
}
})
];
if (!isDev) {
plugins = [
...plugins,
viteStaticCopy({
targets: assets.map((asset) => ({
src: `src/${asset}/*`,
@ -32,20 +29,22 @@ export default defineConfig(() => ({
structured: true,
targets: [
{
src: "node_modules/@excalidraw/excalidraw/dist/prod/fonts/*",
src: "../../node_modules/@excalidraw/excalidraw/dist/prod/fonts/*",
dest: "",
}
]
}),
webpackStatsPlugin()
] as Plugin[],
]
}
export default defineConfig(() => ({
root: __dirname,
cacheDir: '../../node_modules/.vite/apps/client',
base: "",
plugins,
resolve: {
alias: [
// Force the use of dist in development mode because upstream ESM is broken (some hybrid between CJS and ESM, will be improved in upcoming versions).
{
find: "@triliumnext/highlightjs",
replacement: resolve(__dirname, "node_modules/@triliumnext/highlightjs/dist")
},
{
find: "react",
replacement: "preact/compat"
@ -63,10 +62,6 @@ export default defineConfig(() => ({
"preact/hooks"
]
},
// Uncomment this if you are using workers.
// worker: {
// plugins: [ nxViteTsPaths() ],
// },
build: {
target: "esnext",
outDir: './dist',
@ -105,18 +100,6 @@ export default defineConfig(() => ({
"./src/test/setup.ts"
]
},
optimizeDeps: {
exclude: [
"@triliumnext/highlightjs"
]
},
css: {
preprocessorOptions: {
scss: {
quietDeps: true
}
}
},
commonjsOptions: {
transformMixedEsModules: true,
},

View File

@ -6,12 +6,12 @@
To build and run manually:
```sh
nx build db-compare
pnpm build db-compare
node ./apps/db-compare/dist/compare.js
```
To serve development build with arguments:
```sh
nx serve db-compare --args "apps/server/spec/db/document_v214.db" --args "apps/server/spec/db/document_v214_migrated.db"
pnpm dev --args "apps/server/spec/db/document_v214.db" --args "apps/server/spec/db/document_v214_migrated.db"
```

View File

@ -9,63 +9,8 @@
"sqlite": "5.1.1",
"sqlite3": "5.1.7"
},
"nx": {
"name": "db-compare",
"targets": {
"build": {
"executor": "@nx/esbuild:esbuild",
"outputs": [
"{options.outputPath}"
],
"defaultConfiguration": "production",
"options": {
"platform": "node",
"outputPath": "apps/db-compare/dist",
"format": [
"cjs"
],
"bundle": false,
"main": "apps/db-compare/src/compare.ts",
"tsConfig": "apps/db-compare/tsconfig.app.json",
"assets": [],
"esbuildOptions": {
"sourcemap": true,
"outExtension": {
".js": ".js"
}
}
},
"configurations": {
"development": {},
"production": {
"esbuildOptions": {
"sourcemap": false,
"outExtension": {
".js": ".js"
}
}
}
}
},
"serve": {
"executor": "@nx/js:node",
"defaultConfiguration": "development",
"dependsOn": [
"build"
],
"options": {
"buildTarget": "db-compare:build",
"runBuildTargetDependencies": false
},
"configurations": {
"development": {
"buildTarget": "db-compare:build:development"
},
"production": {
"buildTarget": "db-compare:build:production"
}
}
}
}
"scripts": {
"dev": "tsx src/compare.ts",
"build": "esbuild --platform=node --format=cjs --outdir=dist src/compare.ts"
}
}

View File

@ -1,3 +0,0 @@
TRILIUM_INTEGRATION_TEST=memory-no-store
TRILIUM_PORT=8082
TRILIUM_DATA_DIR=data

View File

@ -1,15 +0,0 @@
import playwright from "eslint-plugin-playwright";
import baseConfig from "../../eslint.config.mjs";
export default [
playwright.configs["flat/recommended"],
...baseConfig,
{
files: [
"**/*.ts",
"**/*.js"
],
// Override or add rules here
rules: {}
}
];

View File

@ -1,24 +0,0 @@
{
"name": "@triliumnext/desktop-e2e",
"version": "0.0.1",
"private": true,
"nx": {
"name": "desktop-e2e",
"implicitDependencies": [
"client",
"desktop"
],
"targets": {
"e2e": {
"dependsOn": [
"desktop:build",
"desktop:rebuild-deps"
]
}
}
},
"devDependencies": {
"dotenv": "17.2.1",
"electron": "37.4.0"
}
}

View File

@ -1,25 +0,0 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"allowJs": true,
"outDir": "out-tsc/playwright",
"sourceMap": false
},
"include": [
"**/*.ts",
"**/*.js",
"playwright.config.ts",
"src/**/*.spec.ts",
"src/**/*.spec.js",
"src/**/*.test.ts",
"src/**/*.test.js",
"src/**/*.d.ts"
],
"exclude": [
"out-tsc",
"test-output",
"eslint.config.js",
"eslint.config.mjs",
"eslint.config.cjs"
]
}

View File

@ -1 +0,0 @@
node-linker = hoisted

View File

@ -1 +0,0 @@
TRILIUM_PORT=37743

View File

@ -1,3 +0,0 @@
TRILIUM_PORT=37741
TRILIUM_DATA_DIR=../data
NODE_OPTIONS=--enable-source-maps

View File

@ -60,7 +60,7 @@ test('First setup', async () => {
// Verify the shared link is valid
const requestContext = await request.newContext();
const response = await requestContext.get(linkUrl!);
expect(response).toBeOK();
await expect(response).toBeOK();
await mainWindow.waitForTimeout(5000);
});

View File

@ -3,7 +3,23 @@
"version": "0.98.1",
"description": "Build your personal knowledge base with Trilium Notes",
"private": true,
"main": "main.cjs",
"main": "src/main.ts",
"license": "AGPL-3.0-only",
"author": {
"name": "Trilium Notes Team",
"email": "contact@eliandoran.me",
"url": "https://github.com/TriliumNext/Notes"
},
"scripts": {
"dev": "cross-env TRILIUM_PORT=37741 TRILIUM_DATA_DIR=data tsx ../../scripts/electron-start.mts src/main.ts",
"start-no-dir": "cross-env TRILIUM_PORT=37743 tsx ../../scripts/electron-start.mts src/main.ts",
"build": "tsx scripts/build.ts",
"start-prod": "pnpm build && cross-env TRILIUM_DATA_DIR=data TRILIUM_PORT=37841 ELECTRON_IS_DEV=0 electron dist",
"electron-forge:make": "pnpm build && cross-env electron-forge make dist",
"electron-forge:package": "pnpm build && electron-forge package dist",
"electron-forge:start": "pnpm build && electron-forge start dist",
"e2e": "pnpm build && cross-env TRILIUM_INTEGRATION_TEST=memory-no-store TRILIUM_PORT=8082 TRILIUM_DATA_DIR=data-e2e ELECTRON_IS_DEV=0 playwright test"
},
"dependencies": {
"@electron/remote": "2.1.3",
"better-sqlite3": "^12.0.0",
@ -15,6 +31,7 @@
},
"devDependencies": {
"@types/electron-squirrel-startup": "1.0.2",
"@triliumnext/commons": "workspace:*",
"@triliumnext/server": "workspace:*",
"copy-webpack-plugin": "13.0.1",
"electron": "37.4.0",
@ -27,174 +44,5 @@
"@electron-forge/maker-zip": "7.8.3",
"@electron-forge/plugin-auto-unpack-natives": "7.8.3",
"prebuild-install": "^7.1.1"
},
"config": {
"forge": "./electron-forge/forge.config.ts"
},
"scripts": {
"start-prod": "nx build desktop && cross-env TRILIUM_DATA_DIR=data TRILIUM_RESOURCE_DIR=dist TRILIUM_PORT=37841 electron dist/main.js"
},
"license": "AGPL-3.0-only",
"author": {
"name": "Trilium Notes Team",
"email": "contact@eliandoran.me",
"url": "https://github.com/TriliumNext/Notes"
},
"nx": {
"name": "desktop",
"targets": {
"build": {
"executor": "@nx/esbuild:esbuild",
"outputs": [
"{options.outputPath}"
],
"defaultConfiguration": "production",
"configurations": {
"production": {
"minify": true,
"sourcemap": false
},
"development": {
"minify": false,
"sourcemap": true
}
},
"options": {
"main": "apps/desktop/src/electron-main.ts",
"outputPath": "apps/desktop/dist",
"outputFileName": "main.js",
"tsConfig": "apps/desktop/tsconfig.app.json",
"platform": "node",
"external": [
"electron",
"@electron/remote",
"better-sqlite3",
"./xhr-sync-worker.js"
],
"format": [
"cjs"
],
"thirdParty": true,
"declaration": false,
"esbuildOptions": {
"splitting": false,
"loader": {
".css": "text"
}
},
"assets": [
{
"glob": "**/*",
"input": "apps/server/dist/node_modules",
"output": "node_modules"
},
{
"glob": "**/*",
"input": "apps/desktop/node_modules/@electron/remote",
"output": "node_modules/@electron/remote"
},
{
"glob": "**/*",
"input": "apps/server/dist/assets",
"output": "assets"
},
{
"glob": "**/*",
"input": "packages/share-theme/src/templates",
"output": "share-theme/templates"
},
{
"glob": "**/*",
"input": "apps/desktop/src/assets",
"output": "assets"
},
{
"glob": "**/*",
"input": "apps/server/dist/public",
"output": "public"
},
{
"glob": "xhr-sync-worker.js",
"input": "apps/server/node_modules/jsdom/lib/jsdom/living/xhr",
"output": ""
}
],
"declarationRootDir": "apps/desktop/src"
}
},
"rebuild-deps": {
"executor": "nx:run-commands",
"dependsOn": [
"build"
],
"defaultConfiguration": "default",
"cache": false,
"configurations": {
"default": {
"command": "cross-env DEBUG=* tsx scripts/electron-rebuild.mts {projectRoot}/dist"
},
"nixos": {
"command": "cross-env DEBUG=* tsx scripts/electron-rebuild.mts {projectRoot}/dist $(nix-shell -p electron_35 --run \"electron --version\")"
}
}
},
"serve": {
"executor": "nx:run-commands",
"dependsOn": [
"rebuild-deps"
],
"defaultConfiguration": "default",
"configurations": {
"default": {
"command": "electron main.cjs",
"cwd": "{projectRoot}/dist"
},
"nixos": {
"command": "nix-shell -p electron_35 --run \"electron {projectRoot}/dist/main.cjs\"",
"cwd": ".",
"forwardAllArgs": false
}
}
},
"serve-nodir": {
"executor": "nx:run-commands",
"dependsOn": [
"rebuild-deps"
],
"defaultConfiguration": "default",
"configurations": {
"default": {
"command": "electron main.cjs",
"cwd": "{projectRoot}/dist"
},
"nixos": {
"command": "nix-shell -p electron_35 --run \"electron {projectRoot}/dist/main.cjs\"",
"cwd": ".",
"forwardAllArgs": false
}
}
},
"electron-forge:make": {
"dependsOn": [
"build",
"rebuild-deps"
],
"command": "pnpm -C apps/desktop exec cross-env NODE_INSTALLER=npm electron-forge make dist"
},
"electron-forge:package": {
"dependsOn": [
"build",
"rebuild-deps"
],
"command": "pnpm -C apps/desktop exec cross-env NODE_INSTALLER=npm electron-forge package dist"
},
"electron-forge:start": {
"dependsOn": [
"build",
"rebuild-deps"
],
"command": "pnpm -C apps/desktop exec cross-env NODE_INSTALLER=npm TRILIUM_DATA_DIR=./data electron-forge start dist"
}
}
}
}
}

View File

@ -1,10 +1,5 @@
import { defineConfig, devices } from '@playwright/test';
require('dotenv').config({
path: __dirname + "/" + ".env"
});
/**
* See https://playwright.dev/docs/test-configuration.
*/
@ -14,6 +9,8 @@ export default defineConfig({
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
},
testDir: "e2e",
outputDir: "test-output",
projects: [
{
name: "chromium",

View File

@ -0,0 +1,46 @@
import { join } from "path";
import BuildHelper from "../../../scripts/build-utils";
import originalPackageJson from "../package.json" with { type: "json" };
import { writeFileSync } from "fs";
const build = new BuildHelper("apps/desktop");
async function main() {
await build.buildBackend([ "src/main.ts"]);
// Copy assets.
build.copy("src/assets", "assets/");
build.copy("/apps/server/src/assets", "assets/");
build.copy("/packages/share-theme/src/templates", "share-theme/templates/");
// Copy node modules dependencies
build.copyNodeModules([ "better-sqlite3", "bindings", "file-uri-to-path", "@electron/remote" ]);
build.copy("/node_modules/jsdom/lib/jsdom/living/xhr/xhr-sync-worker.js", "xhr-sync-worker.js");
// Integrate the client.
build.triggerBuildAndCopyTo("apps/client", "public/");
build.deleteFromOutput("public/webpack-stats.json");
generatePackageJson();
}
function generatePackageJson() {
const { version, author, license, description, dependencies, devDependencies } = originalPackageJson;
const packageJson = {
name: "trilium",
main: "main.cjs",
version, author, license, description,
dependencies: {
"better-sqlite3": dependencies["better-sqlite3"],
},
devDependencies: {
electron: devDependencies.electron
},
config: {
forge: "../electron-forge/forge.config.ts"
}
};
writeFileSync(join(build.outDir, "package.json"), JSON.stringify(packageJson, null, "\t"), "utf-8");
}
main();

View File

@ -15,65 +15,8 @@
"@types/mime-types": "^3.0.0",
"@types/yargs": "^17.0.33"
},
"nx": {
"name": "dump-db",
"targets": {
"build": {
"executor": "@nx/esbuild:esbuild",
"outputs": [
"{options.outputPath}"
],
"defaultConfiguration": "production",
"options": {
"platform": "node",
"outputPath": "apps/dump-db/dist",
"format": [
"cjs"
],
"bundle": false,
"main": "apps/dump-db/src/main.ts",
"tsConfig": "apps/dump-db/tsconfig.app.json",
"assets": [
"apps/dump-db/src/assets"
],
"esbuildOptions": {
"sourcemap": true,
"outExtension": {
".js": ".js"
}
}
},
"configurations": {
"development": {},
"production": {
"esbuildOptions": {
"sourcemap": false,
"outExtension": {
".js": ".js"
}
}
}
}
},
"serve": {
"executor": "@nx/js:node",
"defaultConfiguration": "development",
"dependsOn": [
"build"
],
"options": {
"buildTarget": "dump-db:build",
"runBuildTargetDependencies": false
},
"configurations": {
"development": {
"buildTarget": "dump-db:build:development"
},
"production": {
"buildTarget": "dump-db:build:production"
}
}
}
}
"scripts": {
"dev": "tsx src/main.ts",
"build": "esbuild --platform=node --format=cjs --outdir=dist src/main.ts"
}
}

View File

@ -1,7 +0,0 @@
TRILIUM_DATA_DIR=../data
TRILIUM_INTEGRATION_TEST=memory-no-store
TRILIUM_PORT=37741
# Paths are relative to dist root
DOCS_ROOT=../../../docs
USER_GUIDE_ROOT=../../../apps/server/src/assets/doc_notes/en/User Guide

View File

@ -15,120 +15,8 @@
"electron": "37.4.0",
"fs-extra": "11.3.1"
},
"nx": {
"name": "edit-docs",
"implicitDependencies": [
"server"
],
"targets": {
"build": {
"executor": "@nx/esbuild:esbuild",
"outputs": [
"{options.outputPath}"
],
"options": {
"main": "apps/edit-docs/src/edit-docs.ts",
"outputPath": "apps/edit-docs/dist",
"tsConfig": "apps/edit-docs/tsconfig.app.json",
"platform": "node",
"additionalEntryPoints": [
"apps/edit-docs/src/edit-demo.ts"
],
"external": [
"electron",
"@electron/remote",
"better-sqlite3",
"./xhr-sync-worker.js"
],
"format": [
"cjs"
],
"minify": false,
"thirdParty": true,
"declaration": false,
"esbuildOptions": {
"splitting": false,
"loader": {
".css": "text"
}
},
"assets": [
{
"glob": "**/*",
"input": "apps/server/dist/node_modules",
"output": "node_modules"
},
{
"glob": "**/*",
"input": "apps/server/dist/assets",
"output": "assets"
},
{
"glob": "**/*",
"input": "apps/server/dist/public",
"output": "public"
},
{
"glob": "xhr-sync-worker.js",
"input": "apps/server/node_modules/jsdom/lib/jsdom/living/xhr",
"output": ""
}
],
"declarationRootDir": "apps/edit-docs/src"
}
},
"rebuild-deps": {
"executor": "nx:run-commands",
"dependsOn": [
"build"
],
"defaultConfiguration": "default",
"cache": true,
"configurations": {
"default": {
"command": "cross-env DEBUG=* tsx scripts/electron-rebuild.mts {projectRoot}/dist"
},
"nixos": {
"command": "cross-env DEBUG=* tsx scripts/electron-rebuild.mts {projectRoot}/dist $(nix-shell -p electron_35 --run \"electron --version\")"
}
}
},
"edit-docs": {
"executor": "nx:run-commands",
"dependsOn": [
"rebuild-deps"
],
"defaultConfiguration": "default",
"configurations": {
"default": {
"command": "electron edit-docs.cjs",
"cwd": "{projectRoot}/dist"
},
"nixos": {
"command": "nix-shell -p electron_35 --run \"electron {projectRoot}/dist/edit-docs.cjs\"",
"cwd": ".",
"forwardAllArgs": false
}
}
},
"edit-demo": {
"executor": "nx:run-commands",
"dependsOn": [
"rebuild-deps"
],
"defaultConfiguration": "default",
"configurations": {
"default": {
"command": "electron edit-demo.cjs",
"cwd": "{projectRoot}/dist"
},
"nixos": {
"command": "nix-shell -p electron_35 --run \"electron {projectRoot}/dist/edit-demo.cjs\"",
"cwd": ".",
"forwardAllArgs": false
}
}
}
}
}
"scripts": {
"edit-docs": "cross-env TRILIUM_PORT=37741 TRILIUM_DATA_DIR=data TRILIUM_INTEGRATION_TEST=memory-no-store DOCS_ROOT=../../../docs USER_GUIDE_ROOT=\"../../server/src/assets/doc_notes/en/User Guide\" tsx ../../scripts/electron-start.mts src/edit-docs.ts",
"edit-demo": "cross-env TRILIUM_PORT=37741 TRILIUM_DATA_DIR=data TRILIUM_INTEGRATION_TEST=memory-no-store DOCS_ROOT=../../../docs USER_GUIDE_ROOT=\"../../server/src/assets/doc_notes/en/User Guide\" tsx ../../scripts/electron-start.mts src/edit-demo.ts"
}
}

View File

@ -1,3 +0,0 @@
TRILIUM_INTEGRATION_TEST=memory
TRILIUM_PORT=8082
TRILIUM_DATA_DIR=apps/server/spec/db

View File

@ -2,21 +2,10 @@
"name": "@triliumnext/server-e2e",
"version": "0.0.1",
"private": true,
"nx": {
"name": "server-e2e",
"implicitDependencies": [
"client",
"server"
],
"targets": {
"e2e": {
"dependsOn": [
"server:build"
]
}
}
"scripts": {
"e2e": "playwright test"
},
"devDependencies": {
"dotenv": "17.2.1"
"dotenv": "17.2.2"
}
}

View File

@ -1,68 +1,44 @@
import { defineConfig, devices } from '@playwright/test';
import { nxE2EPreset } from '@nx/playwright/preset';
import { workspaceRoot } from '@nx/devkit';
require('dotenv').config({
path: __dirname + "/" + ".env"
});
import { join } from 'path';
// For CI, you may want to set BASE_URL to the deployed application.
const port = process.env['TRILIUM_PORT'];
const port = process.env['TRILIUM_PORT'] ?? "8082";
const baseURL = process.env['BASE_URL'] || `http://127.0.0.1:${port}`;
/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
...nxE2EPreset(__filename, { testDir: './src' }),
testDir: "src",
reporter: [["list"], ["html", { outputFolder: "test-output" }]],
outputDir: "test-output",
retries: 3,
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
baseURL,
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
},
/* Run your local dev server before starting the tests */
webServer: !process.env.TRILIUM_DOCKER ? {
command: 'pnpm server:start-prod',
command: 'pnpm start-prod-no-dir',
url: baseURL,
reuseExistingServer: !process.env.CI,
cwd: workspaceRoot,
cwd: join(__dirname, "../server"),
env: {
TRILIUM_DATA_DIR: "spec/db",
TRILIUM_PORT: port,
TRILIUM_INTEGRATION_TEST: "memory"
},
timeout: 5 * 60 * 1000
} : undefined,
projects: [
{
name: "chromium",
use: { ...devices["Desktop Chrome"] },
},
// {
// name: "firefox",
// use: { ...devices["Desktop Firefox"] },
// },
// {
// name: "webkit",
// use: { ...devices["Desktop Safari"] },
// },
// Uncomment for mobile browsers support
/* {
name: 'Mobile Chrome',
use: { ...devices['Pixel 5'] },
},
{
name: 'Mobile Safari',
use: { ...devices['iPhone 12'] },
}, */
// Uncomment for branded browsers
/* {
name: 'Microsoft Edge',
use: { ...devices['Desktop Edge'], channel: 'msedge' },
},
{
name: 'Google Chrome',
use: { ...devices['Desktop Chrome'], channel: 'chrome' },
} */
],
}
]
});

View File

@ -79,7 +79,7 @@ test("Tabs are restored in right order", async ({ page, context }) => {
// Refresh the page and check the order.
await app.goto( { preserveTabs: true });
await expect(app.getTab(0)).toContainText("Code notes");
await expect(app.getTab(0)).toContainText("Code notes", { timeout: 15_000 });
await expect(app.getTab(1)).toContainText("Text notes");
await expect(app.getTab(2)).toContainText("Mermaid");

View File

@ -1,6 +0,0 @@
TRILIUM_ENV=dev
TRILIUM_DATA_DIR=./apps/server/spec/db
TRILIUM_RESOURCE_DIR=./apps/server/dist
TRILIUM_PUBLIC_SERVER=http://localhost:4200
TRILIUM_PORT=8086
TRILIUM_INTEGRATION_TEST=edit

View File

@ -1,3 +0,0 @@
TRILIUM_ENV=dev
TRILIUM_RESOURCE_DIR=./apps/server/dist
TRILIUM_PUBLIC_SERVER=http://localhost:4200

View File

@ -1,4 +0,0 @@
TRILIUM_ENV=dev
TRILIUM_DATA_DIR=./apps/server/data
TRILIUM_RESOURCE_DIR=./apps/server/dist
TRILIUM_PUBLIC_SERVER=http://localhost:4200

View File

@ -1,3 +0,0 @@
TRILIUM_ENV=production
TRILIUM_DATA_DIR=./apps/server/data
TRILIUM_PORT=8082

View File

@ -1,4 +0,0 @@
TRILIUM_ENV=dev
TRILIUM_DATA_DIR=./spec/db
TRILIUM_PUBLIC_SERVER=http://localhost:4200
TRILIUM_INTEGRATION_TEST=memory

View File

@ -3,11 +3,38 @@
"version": "0.98.1",
"description": "The server-side component of TriliumNext, which exposes the client via the web, allows for sync and provides a REST API for both internal and external use.",
"private": true,
"main": "./src/main.ts",
"scripts": {
"dev": "cross-env NODE_ENV=development TRILIUM_ENV=dev TRILIUM_DATA_DIR=data TRILIUM_RESOURCE_DIR=src tsx watch --ignore '../client/node_modules/.vite-temp' ./src/main.ts",
"start-no-dir": "cross-env NODE_ENV=development TRILIUM_ENV=dev TRILIUM_RESOURCE_DIR=src tsx watch --ignore '../client/node_modules/.vite-temp' ./src/main.ts",
"edit-integration-db": "cross-env NODE_ENV=development TRILIUM_PORT=8086 TRILIUM_ENV=dev TRILIUM_DATA_DIR=spec/db TRILIUM_INTEGRATION_TEST=edit TRILIUM_RESOURCE_DIR=src tsx watch --ignore '../client/node_modules/.vite-temp' ./src/main.ts",
"build": "tsx scripts/build.ts",
"package": "pnpm build && bash scripts/build-server.sh",
"test": "vitest",
"test-build": "vitest --config vitest.build.config.mts",
"start-prod": "cross-env TRILIUM_DATA_DIR=data pnpm start-prod-no-dir",
"start-prod-no-dir": "pnpm build && cross-env TRILIUM_ENV=production TRILIUM_PORT=8082 node dist/main.cjs",
"circular-deps": "dpdm -T src/**/*.ts --tree=false --warning=false --skip-dynamic-imports=circular",
"docker-build-debian": "pnpm build && docker build . -t triliumnext-debian -f Dockerfile",
"docker-build-alpine": "pnpm build && docker build . -t triliumnext-alpine -f Dockerfile.alpine",
"docker-build-rootless-debian": "pnpm build && docker build . -t triliumnext-rootless-debian -f Dockerfile.rootless",
"docker-build-rootless-alpine": "pnpm build && docker build . -t triliumnext-rootless-alpine -f Dockerfile.alpine.rootless",
"docker-start-debian": "pnpm docker-build-debian && docker run -p 8081:8080 triliumnext-debian",
"docker-start-alpine": "pnpm docker-build-alpine && docker run -p 8081:8080 triliumnext-alpine",
"docker-start-rootless-debian": "pnpm docker-build-rootless-debian && docker run -p 8081:8080 triliumnext-rootless-debian",
"docker-start-rootless-alpine": "pnpm docker-build-rootless-alpine && docker run -p 8081:8080 triliumnext-rootless-alpine"
},
"dependencies": {
"better-sqlite3": "12.2.0"
},
"devDependencies": {
"@anthropic-ai/sdk": "0.60.0",
"@braintree/sanitize-url": "7.1.1",
"@electron/remote": "2.1.3",
"@preact/preset-vite": "2.10.2",
"@triliumnext/commons": "workspace:*",
"@triliumnext/express-partial-content": "workspace:*",
"@triliumnext/turndown-plugin-gfm": "workspace:*",
"@types/archiver": "6.0.3",
"@types/better-sqlite3": "7.6.13",
"@types/cls-hooked": "4.3.9",
@ -38,16 +65,11 @@
"@types/turndown": "5.0.5",
"@types/ws": "8.18.1",
"@types/xml2js": "0.4.14",
"express-http-proxy": "2.1.1",
"@anthropic-ai/sdk": "0.60.0",
"@braintree/sanitize-url": "7.1.1",
"@triliumnext/commons": "workspace:*",
"@triliumnext/express-partial-content": "workspace:*",
"@triliumnext/turndown-plugin-gfm": "workspace:*",
"archiver": "7.0.1",
"async-mutex": "0.5.0",
"axios": "1.11.0",
"bindings": "1.5.0",
"bootstrap": "5.3.8",
"chardet": "2.1.0",
"cheerio": "1.1.2",
"chokidar": "4.0.3",
@ -64,6 +86,7 @@
"electron-window-state": "5.0.3",
"escape-html": "1.0.3",
"express": "5.1.0",
"express-http-proxy": "2.1.1",
"express-openid-connect": "^2.17.1",
"express-rate-limit": "8.0.1",
"express-session": "1.18.2",
@ -105,272 +128,9 @@
"tmp": "0.2.5",
"turndown": "7.2.1",
"unescape": "1.0.1",
"vite": "^7.1.3",
"ws": "8.18.3",
"xml2js": "0.6.2",
"yauzl": "3.2.0"
},
"nx": {
"name": "server",
"implicitDependencies": [
"share-theme"
],
"targets": {
"serve": {
"executor": "@nx/js:node",
"dependsOn": [
{
"projects": [
"client"
],
"target": "serve"
},
"build-without-client"
],
"continuous": true,
"options": {
"buildTarget": "server:build-without-client:development",
"runBuildTargetDependencies": false
}
},
"serve-nodir": {
"executor": "@nx/js:node",
"dependsOn": [
{
"projects": [
"client"
],
"target": "serve"
},
"build-without-client"
],
"continuous": true,
"options": {
"buildTarget": "server:build-without-client:development",
"runBuildTargetDependencies": false
}
},
"edit-integration-db": {
"executor": "@nx/js:node",
"dependsOn": [
{
"projects": [
"client"
],
"target": "serve"
},
"build-without-client"
],
"continuous": true,
"options": {
"buildTarget": "server:build-without-client:development",
"runBuildTargetDependencies": false
}
},
"package": {
"dependsOn": [
"build"
],
"command": "bash apps/server/scripts/build-server.sh"
},
"start-prod": {
"dependsOn": [
"build"
],
"command": "node apps/server/dist/main.cjs"
},
"docker-build": {
"dependsOn": [
"build"
],
"options": {
"cwd": "{projectRoot}"
},
"executor": "nx:run-commands",
"defaultConfiguration": "alpine",
"configurations": {
"debian": {
"command": "docker build . -t triliumnext-debian -f Dockerfile"
},
"alpine": {
"command": "docker build . -t triliumnext-alpine -f Dockerfile.alpine"
},
"rootless-debian": {
"command": "docker build . -t triliumnext-rootless-debian -f Dockerfile.rootless"
},
"rootless-alpine": {
"command": "docker build . -t triliumnext-rootless-alpine -f Dockerfile.alpine.rootless"
}
}
},
"docker-start": {
"dependsOn": [
"docker-build"
],
"executor": "nx:run-commands",
"defaultConfiguration": "alpine",
"configurations": {
"debian": {
"command": "docker run -p 8081:8080 triliumnext-debian"
},
"alpine": {
"command": "docker run -p 8081:8080 triliumnext-alpine"
},
"rootless-debian": {
"command": "docker run -p 8081:8080 triliumnext-rootless-debian"
},
"rootless-alpine": {
"command": "docker run -p 8081:8080 triliumnext-rootless-alpine"
}
}
},
"build-without-client": {
"executor": "@nx/esbuild:esbuild",
"outputs": [
"{options.outputPath}"
],
"options": {
"main": "apps/server/src/main.ts",
"outputPath": "apps/server/dist",
"outputFileName": "main.js",
"tsConfig": "apps/server/tsconfig.app.json",
"platform": "node",
"format": [
"cjs"
],
"esbuildOptions": {
"loader": {
".css": "text",
".ejs": "text"
}
},
"declarationRootDir": "apps/server/src",
"minify": false,
"sourcemap": true,
"assets": [
{
"glob": "**/*",
"input": "apps/server/src/assets",
"output": "assets"
},
{
"glob": "**/*",
"input": "packages/share-theme/src/templates",
"output": "share-theme/templates"
}
]
}
},
"build": {
"executor": "@nx/esbuild:esbuild",
"outputs": [
"{options.outputPath}"
],
"dependsOn": [
"^build",
"client:build"
],
"defaultConfiguration": "production",
"configurations": {
"production": {
"minify": true,
"sourcemap": false
},
"development": {
"minify": false,
"sourcemap": true
}
},
"options": {
"main": "apps/server/src/main.ts",
"outputPath": "apps/server/dist",
"tsConfig": "apps/server/tsconfig.app.json",
"platform": "node",
"external": [
"electron",
"@electron/remote",
"better-sqlite3",
"./xhr-sync-worker.js"
],
"format": [
"cjs"
],
"declarationRootDir": "apps/server/src",
"thirdParty": true,
"declaration": false,
"esbuildOptions": {
"splitting": false,
"loader": {
".css": "text",
".ejs": "text"
}
},
"additionalEntryPoints": [
"apps/server/src/docker_healthcheck.ts"
],
"assets": [
{
"glob": "**/*",
"input": "apps/server/src/assets",
"output": "assets"
},
{
"glob": "**/*",
"input": "packages/share-theme/src/templates",
"output": "share-theme/templates"
},
{
"glob": "**/*",
"input": "apps/client/dist",
"output": "public",
"ignore": [
"webpack-stats.json"
]
},
{
"glob": "**/*",
"input": "apps/server/node_modules/better-sqlite3",
"output": "node_modules/better-sqlite3"
},
{
"glob": "**/*",
"input": "apps/server/node_modules/bindings",
"output": "node_modules/bindings"
},
{
"glob": "**/*",
"input": "apps/server/node_modules/file-uri-to-path",
"output": "node_modules/file-uri-to-path"
},
{
"glob": "xhr-sync-worker.js",
"input": "apps/server/node_modules/jsdom/lib/jsdom/living/xhr",
"output": ""
}
]
}
},
"test-build": {
"dependsOn": [
"build"
],
"command": "vitest --config {projectRoot}/vitest.build.config.mts"
},
"circular-deps": {
"command": "pnpx dpdm -T {projectRoot}/src/**/*.ts --tree=false --warning=false --skip-dynamic-imports=circular"
}
}
},
"exports": {
"./package.json": "./package.json",
"./src/*": "./src/*",
".": {
"development": "./src/main.ts",
"types": "./dist/main.d.ts",
"import": "./dist/main.js",
"default": "./dist/main.js"
}
},
"types": "./dist/main.d.ts",
"module": "./dist/main.js",
"main": "./dist/main.js"
}
}

View File

@ -0,0 +1,22 @@
import BuildHelper from "../../../scripts/build-utils";
const build = new BuildHelper("apps/server");
async function main() {
await build.buildBackend([ "src/main.ts", "src/docker_healthcheck.ts" ])
// Copy assets
build.copy("src/assets", "assets/");
build.copy("/packages/share-theme/src/templates", "share-theme/templates/");
// Copy node modules dependencies
build.copyNodeModules([ "better-sqlite3", "bindings", "file-uri-to-path" ]);
build.copy("/node_modules/jsdom/lib/jsdom/living/xhr/xhr-sync-worker.js", "xhr-sync-worker.js");
build.copy("/node_modules/ckeditor5/dist/ckeditor5-content.css", "ckeditor5-content.css");
// Integrate the client.
build.triggerBuildAndCopyTo("apps/client", "public/");
build.deleteFromOutput("public/webpack-stats.json");
}
main();

View File

@ -30,5 +30,5 @@ describe("etapi/import", () => {
.expect(201);
expect(response.body.note.title).toStrictEqual("Journal");
expect(response.body.branch.parentNoteId).toStrictEqual("root");
});
}, 10_000);
});

View File

@ -3,7 +3,6 @@ import path from "path";
import express from "express";
import { getResourceDir, isDev } from "../services/utils.js";
import type serveStatic from "serve-static";
import proxy from "express-http-proxy";
import { existsSync } from "fs";
const persistentCacheStatic = (root: string, options?: serveStatic.ServeStaticOptions<express.Response<unknown, Record<string, unknown>>>) => {
@ -17,17 +16,22 @@ const persistentCacheStatic = (root: string, options?: serveStatic.ServeStaticOp
};
async function register(app: express.Application) {
const srcRoot = path.join(__dirname, "..");
const srcRoot = path.join(__dirname, "..", "..");
const resourceDir = getResourceDir();
if (isDev) {
const publicUrl = process.env.TRILIUM_PUBLIC_SERVER;
if (!publicUrl) {
throw new Error("Missing TRILIUM_PUBLIC_SERVER");
}
app.use("/" + assetUrlFragment + `/@fs`, proxy(publicUrl, {
proxyReqPathResolver: (req) => "/" + assetUrlFragment + `/@fs` + req.url
}));
if (process.env.NODE_ENV === "development") {
const { createServer: createViteServer } = await import("vite");
const vite = await createViteServer({
server: { middlewareMode: true },
appType: "custom",
cacheDir: path.join(srcRoot, "../../.cache/vite"),
base: `/${assetUrlFragment}/`,
root: path.join(srcRoot, "../client")
});
app.use(`/${assetUrlFragment}/`, (req, res, next) => {
req.url = `/${assetUrlFragment}` + req.url;
vite.middlewares(req, res, next);
});
} else {
const publicDir = path.join(resourceDir, "public");
if (!existsSync(publicDir)) {

View File

@ -1,3 +1,4 @@
import assetPath from "./asset_path.js";
import { isDev } from "./utils.js";
export default assetPath + "/src";
export default isDev ? assetPath : assetPath + "/src";

View File

@ -1,7 +1,14 @@
import packageJson from "../../package.json" with { type: "json" };
import { isDev } from "./utils";
/**
* The URL prefix for assets (e.g. `assets/v1.2.3`).
*/
export const assetUrlFragment = `assets/v${packageJson.version}`;
const assetPath = isDev ? `http://localhost:4200/${assetUrlFragment}` : assetUrlFragment;
/**
* Similar to the {@link assetUrlFragment}, but on dev mode it also contains the `/src` suffix.
*/
const assetPath = isDev ? assetUrlFragment + "/src" : assetUrlFragment;
export default assetPath;

View File

@ -6,7 +6,7 @@ import path from "path";
import mimeTypes from "mime-types";
import mdService from "./markdown.js";
import packageInfo from "../../../package.json" with { type: "json" };
import { getContentDisposition, escapeHtml, getResourceDir } from "../utils.js";
import { getContentDisposition, escapeHtml, getResourceDir, isDev } from "../utils.js";
import protectedSessionService from "../protected_session.js";
import sanitize from "sanitize-filename";
import fs from "fs";
@ -21,7 +21,6 @@ import type AttributeMeta from "../meta/attribute_meta.js";
import type BBranch from "../../becca/entities/bbranch.js";
import type { Response } from "express";
import type { NoteMetaFile } from "../meta/note_meta.js";
import cssContent from "@triliumnext/ckeditor5/content.css";
type RewriteLinksFn = (content: string, noteMeta: NoteMeta) => string;
@ -515,7 +514,11 @@ ${markdownContent}`;
return;
}
archive.append(cssContent, { name: cssMeta.dataFileName });
const cssFile = isDev
? path.join(__dirname, "../../../../../node_modules/ckeditor5/dist/ckeditor5-content.css")
: path.join(getResourceDir(), "ckeditor5-content.css");
archive.append(fs.readFileSync(cssFile, "utf-8"), { name: cssMeta.dataFileName });
}
try {

View File

@ -1,4 +1,3 @@
import log from "./log.js";
import path from "path";
import fs from "fs";
@ -10,7 +9,7 @@ const ELECTRON_APP_ROOT_DIR = path.resolve(RESOURCE_DIR, "../..");
const DB_INIT_DIR = path.resolve(RESOURCE_DIR, "db");
if (!fs.existsSync(DB_INIT_DIR)) {
log.error(`Could not find DB initialization directory: ${DB_INIT_DIR}`);
console.error(`Could not find DB initialization directory: ${DB_INIT_DIR}`);
process.exit(1);
}

View File

@ -15,6 +15,10 @@ import becca_loader from "../becca/becca_loader.js";
import entity_changes from "./entity_changes.js";
import config from "./config.js";
const dbOpts: Database.Options = {
nativeBinding: process.env.BETTERSQLITE3_NATIVE_PATH || undefined
};
let dbConnection: DatabaseType = buildDatabase();
let statementCache: Record<string, Statement> = {};
@ -23,15 +27,18 @@ function buildDatabase() {
if (process.env.TRILIUM_INTEGRATION_TEST === "memory") {
return buildIntegrationTestDatabase();
} else if (process.env.TRILIUM_INTEGRATION_TEST === "memory-no-store") {
return new Database(":memory:");
return new Database(":memory:", dbOpts);
}
return new Database(dataDir.DOCUMENT_PATH, { readonly: config.General.readOnly });
return new Database(dataDir.DOCUMENT_PATH, {
...dbOpts,
readonly: config.General.readOnly
});
}
function buildIntegrationTestDatabase(dbPath?: string) {
const dbBuffer = fs.readFileSync(dbPath ?? dataDir.DOCUMENT_PATH);
return new Database(dbBuffer);
return new Database(dbBuffer, dbOpts);
}
function rebuildIntegrationTestDatabase(dbPath?: string) {

View File

@ -29,12 +29,21 @@ function getTrayIconPath() {
name = "icon-color";
}
return path.resolve(path.join(getResourceDir(), "assets", "images", "tray", `${name}.png`));
if (process.env.NODE_ENV === "development") {
return path.join(__dirname, "../../../desktop/src/assets/images/tray", `${name}.png`);
} else {
return path.resolve(path.join(getResourceDir(), "assets", "images", "tray", `${name}.png`));
}
}
function getIconPath(name: string) {
const suffix = !isMac && electron.nativeTheme.shouldUseDarkColors ? "-inverted" : "";
return path.resolve(path.join(getResourceDir(), "assets", "images", "tray", `${name}Template${suffix}.png`));
if (process.env.NODE_ENV === "development") {
return path.join(__dirname, "../../../desktop/src/assets/images/tray", `${name}Template${suffix}.png`);
} else {
return path.resolve(path.join(getResourceDir(), "assets", "images", "tray", `${name}Template${suffix}.png`));
}
}
function registerVisibilityListener(window: BrowserWindow) {

View File

@ -224,7 +224,7 @@ function getWindowExtraOpts() {
}
async function configureWebContents(webContents: WebContents, spellcheckEnabled: boolean) {
const remoteMain = (await import("@electron/remote/main/index.js")).default;
const remoteMain = (await import("@electron/remote/main/index.js"));
remoteMain.enable(webContents);
webContents.setWindowOpenHandler((details) => {
@ -257,7 +257,11 @@ async function configureWebContents(webContents: WebContents, spellcheckEnabled:
}
function getIcon() {
return path.join(RESOURCE_DIR, "../public/assets/icon.png");
if (process.env.NODE_ENV === "development") {
return path.join(__dirname, "../../../desktop/electron-forge/app-icon/png/256x256-dev.png");
} else {
return path.join(RESOURCE_DIR, "../public/assets/icon.png");
}
}
async function createSetupWindow() {

View File

@ -18,6 +18,7 @@ import utils, { isDev, safeExtractMessageAndStackFromError } from "../services/u
import options from "../services/options.js";
import { t } from "i18next";
import ejs from "ejs";
import { join } from "path";
function getSharedSubTreeRoot(note: SNote): { note?: SNote; branch?: SBranch } {
if (note.noteId === shareRoot.SHARE_ROOT_NOTE_ID) {
@ -401,7 +402,9 @@ function register(router: Router) {
function renderDefault(res: Response<any, Record<string, any>>, template: "page" | "404", opts: any = {}) {
// Path is relative to apps/server/dist/assets/views
const shareThemePath = `../../share-theme/templates/${template}.ejs`;
const shareThemePath = process.env.NODE_ENV === "development"
? join(__dirname, `../../../../packages/share-theme/src/templates/${template}.ejs`)
: `../../share-theme/templates/${template}.ejs`;
res.render(shareThemePath, opts);
}

View File

@ -7,7 +7,10 @@ import sql_init from "../services/sql_init.js";
let dbConnection!: Database.Database;
sql_init.dbReady.then(() => {
dbConnection = new Database(dataDir.DOCUMENT_PATH, { readonly: true });
dbConnection = new Database(dataDir.DOCUMENT_PATH, {
readonly: true,
nativeBinding: process.env.BETTERSQLITE3_NATIVE_PATH || undefined
});
[`exit`, `SIGINT`, `SIGUSR1`, `SIGUSR2`, `SIGTERM`].forEach((eventType) => {
process.on(eventType, () => {

View File

@ -10,6 +10,11 @@ export default defineConfig(() => ({
globals: true,
setupFiles: ["./spec/setup.ts"],
environment: "node",
env: {
NODE_ENV: "development",
TRILIUM_DATA_DIR: "./spec/db",
TRILIUM_INTEGRATION_TEST: "memory"
},
include: ['{src,spec}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
exclude: [
"spec/build-checks/**",

View File

@ -4,8 +4,8 @@ Landing page for Trilium Notes powered by [Svelte](https://github.com/sveltejs/c
## Developing
To run a dev server that will hot-reload changes: `pnpm nx run website:dev`
To run a dev server that will hot-reload changes: `pnpm dev`
## Building
To create a production build: `pnpm nx run website:build`
To create a production build: `pnpm build`

View File

@ -33,14 +33,5 @@
},
"dependencies": {
"@inlang/paraglide-js": "^2.0.0"
},
"nx": {
"targets": {
"typecheck": {
"dependsOn": [
"build"
]
}
}
}
}

View File

@ -139,7 +139,7 @@ pnpm run server:start
git clone https://github.com/TriliumNext/Trilium.git
cd Trilium
pnpm install
pnpm nx run edit-docs:edit-docs
pnpm run edit-docs:edit-docs
```
### 建置桌面可执行文件
@ -149,7 +149,7 @@ pnpm nx run edit-docs:edit-docs
git clone https://github.com/TriliumNext/Trilium.git
cd Trilium
pnpm install
pnpm nx --project=desktop electron-forge:make -- --arch=x64 --platform=win32
pnpm --filter=desktop electron-forge:make --arch=x64 --platform=win32
```
更多细节请参见[开发文件](https://github.com/TriliumNext/Notes/blob/develop/docs/Developer%20Guide/Developer%20Guide/Building%20and%20deployment/Running%20a%20development%20build.md)。

View File

@ -139,7 +139,7 @@ pnpm run server:start
git clone https://github.com/TriliumNext/Trilium.git
cd Trilium
pnpm install
pnpm nx run edit-docs:edit-docs
pnpm edit-docs:edit-docs
```
### 建置桌面可執行檔
@ -149,7 +149,7 @@ pnpm nx run edit-docs:edit-docs
git clone https://github.com/TriliumNext/Trilium.git
cd Trilium
pnpm install
pnpm nx --project=desktop electron-forge:make -- --arch=x64 --platform=win32
pnpm --filter=desktop electron-forge:make --arch=x64 --platform=win32
```
更多細節請參見[開發文件](https://github.com/TriliumNext/Notes/blob/develop/docs/Developer%20Guide/Developer%20Guide/Building%20and%20deployment/Running%20a%20development%20build.md)。

View File

@ -1,60 +0,0 @@
import nx from "@nx/eslint-plugin";
import reactHooks from "eslint-plugin-react-hooks";
export default [
...nx.configs["flat/base"],
...nx.configs["flat/typescript"],
...nx.configs["flat/javascript"],
{
files: ['**/*.{ts,tsx}'],
plugins: { 'react-hooks': reactHooks },
rules: {
'react-hooks/rules-of-hooks': 'error',
}
},
{
"ignores": [
"**/dist",
"**/vite.config.*.timestamp*",
"**/vitest.config.*.timestamp*"
]
},
{
files: [
"**/*.tsx",
],
rules: {
"@nx/enforce-module-boundaries": [
"error",
{
enforceBuildableLibDependency: true,
allow: [
"^.*/eslint(\\.base)?\\.config\\.[cm]?js$"
],
depConstraints: [
{
sourceTag: "*",
onlyDependOnLibsWithTags: [
"*"
]
}
]
}
]
}
},
{
files: [
"**/*.ts",
"**/*.tsx",
"**/*.cts",
"**/*.mts",
"**/*.js",
"**/*.jsx",
"**/*.cjs",
"**/*.mjs"
],
// Override or add rules here
rules: {}
}
];

View File

@ -36,6 +36,7 @@
stdenv
wrapGAppsHook3
xcodebuild
which
;
fullCleanSourceFilter =
@ -46,8 +47,7 @@
baseName = baseNameOf (toString name);
in
# No need to copy the flake.
# Don't copy local development instance of NX cache.
baseName != "flake.nix" && baseName != "flake.lock" && baseName != ".nx"
baseName != "flake.nix" && baseName != "flake.lock"
);
fullCleanSource =
src:
@ -93,19 +93,15 @@
postConfigure =
''
chmod +x node_modules/.pnpm/electron@*/node_modules/electron/install.js
chmod +x node_modules/electron/install.js
patchShebangs --build node_modules
''
+ lib.optionalString stdenv.hostPlatform.isLinux ''
patchelf --set-interpreter $(cat $NIX_CC/nix-support/dynamic-linker) \
node_modules/.pnpm/sass-embedded-linux-x64@*/node_modules/sass-embedded-linux-x64/dart-sass/src/dart
'';
extraNativeBuildInputs =
[
moreutils # sponge
nodejs.python
removeReferencesTo
removeReferencesTo
]
++ lib.optionals (app == "desktop") [
copyDesktopItems
@ -113,6 +109,10 @@
# https://github.com/NixOS/nixpkgs/issues/172583
makeShellWrapper
wrapGAppsHook3
# For determining the Electron version to rebuild for:
which
electron
]
++ lib.optionals (app == "server") [
makeBinaryWrapper
@ -129,7 +129,7 @@
${preBuildCommands}
'';
scriptFull = "pnpm nx ${buildTask} --outputStyle stream --verbose";
scriptFull = "pnpm run ${buildTask}";
installPhase = ''
runHook preInstall
@ -181,12 +181,12 @@
desktop = makeApp {
app = "desktop";
preBuildCommands = "export npm_config_nodedir=${electron.headers}";
buildTask = "run desktop:rebuild-deps";
preBuildCommands = "export npm_config_nodedir=${electron.headers}; pnpm postinstall";
buildTask = "desktop:build";
mainProgram = "trilium";
installCommands = ''
remove-references-to -t ${electron.headers} apps/desktop/dist/node_modules/better-sqlite3/build/config.gypi
remove-references-to -t ${nodejs.python} apps/desktop/dist/node_modules/better-sqlite3/build/config.gypi
#remove-references-to -t ${electron.headers} apps/desktop/dist/node_modules/better-sqlite3/build/config.gypi
#remove-references-to -t ${nodejs.python} apps/desktop/dist/node_modules/better-sqlite3/build/config.gypi
mkdir -p $out/{bin,share/icons/hicolor/512x512/apps,opt/trilium}
cp --archive apps/desktop/dist/* $out/opt/trilium
@ -203,11 +203,11 @@
server = makeApp {
app = "server";
preBuildCommands = "pushd apps/server; pnpm rebuild; popd";
buildTask = "--project=server build";
buildTask = "server:build";
mainProgram = "trilium-server";
installCommands = ''
remove-references-to -t ${nodejs.python} apps/server/dist/node_modules/better-sqlite3/build/config.gypi
remove-references-to -t ${pnpm} apps/server/dist/node_modules/better-sqlite3/build/config.gypi
#remove-references-to -t ${nodejs.python} apps/server/dist/node_modules/better-sqlite3/build/config.gypi
#remove-references-to -t ${pnpm} apps/server/dist/node_modules/better-sqlite3/build/config.gypi
pushd apps/server/dist
rm -rf node_modules/better-sqlite3/build/Release/obj \

94
nx.json
View File

@ -1,94 +0,0 @@
{
"$schema": "./node_modules/nx/schemas/nx-schema.json",
"defaultBase": "main",
"namedInputs": {
"default": [
"{projectRoot}/**/*",
"sharedGlobals"
],
"production": [
"default",
"!{projectRoot}/.eslintrc.json",
"!{projectRoot}/eslint.config.mjs",
"!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)",
"!{projectRoot}/tsconfig.spec.json",
"!{projectRoot}/src/test-setup.[jt]s"
],
"sharedGlobals": [
"{workspaceRoot}/.github/workflows/release.yml",
"{workspaceRoot}/.github/workflows/playwright.yml"
]
},
"plugins": [
{
"plugin": "@nx/js/typescript",
"options": {
"typecheck": {
"targetName": "typecheck"
},
"build": {
"targetName": "build",
"configName": "tsconfig.lib.json",
"buildDepsName": "build-deps",
"watchDepsName": "watch-deps"
}
}
},
{
"plugin": "@nx/eslint/plugin",
"options": {
"targetName": "lint"
}
},
{
"plugin": "@nx/vite/plugin",
"options": {
"buildTargetName": "build",
"testTargetName": "test",
"serveTargetName": "serve",
"devTargetName": "dev",
"previewTargetName": "preview",
"serveStaticTargetName": "serve-static",
"typecheckTargetName": "typecheck",
"buildDepsTargetName": "build-deps",
"watchDepsTargetName": "watch-deps"
}
},
{
"plugin": "@nx/playwright/plugin",
"options": {
"targetName": "e2e"
}
}
],
"targetDefaults": {
"test": {
"dependsOn": [
"^build"
]
},
"@nx/esbuild:esbuild": {
"cache": true,
"dependsOn": [
"^build"
],
"inputs": [
"production",
"^production"
]
},
"e2e-ci--**/*": {
"dependsOn": [
"^build"
]
}
},
"generators": {
"@nx/web:application": {
"style": "css",
"linter": "eslint",
"unitTestRunner": "vitest",
"e2eTestRunner": "playwright"
}
}
}

View File

@ -6,37 +6,34 @@
"doc": "docs"
},
"scripts": {
"client:test": "nx test client",
"client:build": "nx build client",
"client:coverage": "nx test client --coverage",
"server:test": "nx test server",
"server:build": "nx build server",
"server:coverage": "nx test server --coverage",
"server:start": "nx run server:serve --outputStyle stream",
"server:start-prod": "nx run server:start-prod",
"electron:build": "nx build desktop",
"client:test": "pnpm run --filter client test",
"client:build": "pnpm run --filter client build",
"client:coverage": "pnpm run --filter client test --coverage",
"server:test": "pnpm run --filter server test",
"server:build": "pnpm run --filter server build",
"server:coverage": "pnpm run --filter server test --coverage",
"server:start": "pnpm run --filter server dev",
"server:start-prod": "pnpm run --filter server start-prod",
"desktop:start": "pnpm run --filter desktop dev",
"desktop:build": "pnpm run --filter desktop build",
"desktop:start-prod": "pnpm run --filter desktop start-prod",
"electron:build": "pnpm desktop:build",
"electron:start": "pnpm desktop:start",
"electron:start-prod": "pnpm desktop:start-prod",
"chore:ci-update-nightly-version": "tsx ./scripts/update-nightly-version.ts",
"chore:generate-openapi": "tsx ./scripts/generate-openapi.ts",
"chore:update-build-info": "tsx ./scripts/update-build-info.ts",
"chore:update-version": "tsx ./scripts/update-version.ts",
"edit-docs:edit-docs": "pnpm run --filter edit-docs edit-docs",
"edit-docs:edit-demo": "pnpm run --filter edit-docs edit-demo",
"test:all": "pnpm test:parallel && pnpm test:sequential",
"test:parallel": "pnpm nx run-many -t test --all --exclude=server,ckeditor5-mermaid,ckeditor5-math --parallel",
"test:sequential": "pnpm nx run-many -t test --projects=server,ckeditor5-mermaid,ckeditor5-math --parallel=1",
"coverage": "pnpm nx run-many -t coverage"
"test:parallel": "pnpm --filter=!server --filter=!ckeditor5-mermaid --filter=!ckeditor5-math --parallel test",
"test:sequential": "pnpm --filter=server --filter=ckeditor5-mermaid --filter=ckeditor5-math --sequential test",
"postinstall": "tsx scripts/electron-rebuild.mts"
},
"private": true,
"devDependencies": {
"@electron/rebuild": "4.0.1",
"@nx/devkit": "21.3.11",
"@nx/esbuild": "21.3.11",
"@nx/eslint": "21.3.11",
"@nx/eslint-plugin": "21.3.11",
"@nx/express": "21.3.11",
"@nx/js": "21.3.11",
"@nx/node": "21.3.11",
"@nx/playwright": "21.3.11",
"@nx/vite": "21.3.11",
"@nx/web": "21.3.11",
"@playwright/test": "^1.36.0",
"@triliumnext/server": "workspace:*",
"@types/express": "^5.0.0",
@ -55,7 +52,6 @@
"jiti": "2.5.1",
"jsdom": "~26.1.0",
"jsonc-eslint-parser": "^2.1.0",
"nx": "21.3.11",
"react-refresh": "^0.17.0",
"rollup-plugin-webpack-stats": "2.1.4",
"tslib": "^2.3.0",
@ -86,8 +82,7 @@
"patchedDependencies": {
"@ckeditor/ckeditor5-mention": "patches/@ckeditor__ckeditor5-mention.patch",
"@ckeditor/ckeditor5-code-block": "patches/@ckeditor__ckeditor5-code-block.patch",
"ckeditor5": "patches/ckeditor5.patch",
"@nx/js": "patches/@nx__js.patch"
"ckeditor5": "patches/ckeditor5.patch"
},
"overrides": {
"mermaid": "11.10.1",
@ -120,11 +115,7 @@
"esbuild",
"fs-xattr",
"macos-alias",
"nx",
"utf-8-validate"
]
},
"nx": {
"name": "triliumnext"
}
}

View File

@ -11,18 +11,7 @@
"ckeditor5-package-generator"
],
"type": "module",
"main": "dist/index.ts",
"module": "dist/index.js",
"types": "dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
},
"./*": "./dist/*",
"./browser/*": null,
"./package.json": "./package.json"
},
"main": "src/index.ts",
"engines": {
"node": ">=18.0.0",
"npm": ">=5.7.1"
@ -35,7 +24,7 @@
"@ckeditor/ckeditor5-dev-build-tools": "43.1.0",
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
"@ckeditor/ckeditor5-package-tools": "^4.0.0",
"@typescript-eslint/eslint-plugin": "~8.41.0",
"@typescript-eslint/eslint-plugin": "~8.42.0",
"@typescript-eslint/parser": "^8.0.0",
"@vitest/browser": "^3.0.5",
"@vitest/coverage-istanbul": "^3.0.5",
@ -78,13 +67,5 @@
"**/*.css": [
"stylelint --quiet --allow-empty-input"
]
},
"nx": {
"name": "ckeditor5-admonition",
"targets": {
"build": {
"cache": "true"
}
}
}
}

View File

@ -10,7 +10,7 @@
import { Plugin, addListToDropdown, createDropdown, ListDropdownItemDefinition, SplitButtonView, ViewModel } from 'ckeditor5';
import '../theme/blockquote.css';
import admonitionIcon from '../theme/icons/admonition.svg';
import admonitionIcon from '../theme/icons/admonition.svg?raw';
import { AdmonitionType } from './admonitioncommand.js';
import { Collection } from 'ckeditor5';

View File

@ -1,4 +1,4 @@
import admonitionIcon from '../theme/icons/admonition.svg';
import admonitionIcon from '../theme/icons/admonition.svg?raw';
import './augmentation.js';
import "../theme/blockquote.css";

View File

@ -1,4 +1,4 @@
declare module '*.svg' {
declare module '*.svg?raw' {
const content: string;
export default content;
}

View File

@ -11,18 +11,7 @@
"ckeditor5-package-generator"
],
"type": "module",
"main": "dist/index.ts",
"module": "dist/index.js",
"types": "dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
},
"./*": "./dist/*",
"./browser/*": null,
"./package.json": "./package.json"
},
"main": "src/index.ts",
"license": "ISC",
"engines": {
"node": ">=18.0.0",
@ -36,7 +25,7 @@
"@ckeditor/ckeditor5-dev-build-tools": "43.1.0",
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
"@ckeditor/ckeditor5-package-tools": "^4.0.0",
"@typescript-eslint/eslint-plugin": "~8.41.0",
"@typescript-eslint/eslint-plugin": "~8.42.0",
"@typescript-eslint/parser": "^8.0.0",
"@vitest/browser": "^3.0.5",
"@vitest/coverage-istanbul": "^3.0.5",
@ -77,13 +66,5 @@
"**/*.css": [
"stylelint --quiet --allow-empty-input"
]
},
"nx": {
"name": "ckeditor5-footnotes",
"targets": {
"build": {
"cache": "true"
}
}
}
}

View File

@ -6,7 +6,7 @@ import {
ELEMENTS,
TOOLBAR_COMPONENT_NAME
} from './constants.js';
import insertFootnoteIcon from '../theme/icons/insert-footnote.svg';
import insertFootnoteIcon from '../theme/icons/insert-footnote.svg?raw';
import { modelQueryElement, modelQueryElementsAll } from './utils.js';
export default class FootnoteUI extends Plugin {

View File

@ -1,4 +1,4 @@
import insertFootnoteIcon from './../theme/icons/insert-footnote.svg';
import insertFootnoteIcon from './../theme/icons/insert-footnote.svg?raw';
import './augmentation.js';
import "../theme/footnote.css";

View File

@ -1,4 +1,4 @@
declare module '*.svg' {
declare module '*.svg?raw' {
const content: string;
export default content;
}

View File

@ -11,18 +11,7 @@
"ckeditor5-package-generator"
],
"type": "module",
"main": "dist/index.ts",
"module": "dist/index.js",
"types": "dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
},
"./*": "./dist/*",
"./browser/*": null,
"./package.json": "./package.json"
},
"main": "src/index.ts",
"author": "Marek Lewandowski",
"license": "GPL-3.0",
"homepage": "https://github.com/mlewand/ckeditor5-keyboard-marker",
@ -38,7 +27,7 @@
"@ckeditor/ckeditor5-dev-build-tools": "43.1.0",
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
"@ckeditor/ckeditor5-package-tools": "^4.0.0",
"@typescript-eslint/eslint-plugin": "~8.41.0",
"@typescript-eslint/eslint-plugin": "~8.42.0",
"@typescript-eslint/parser": "^8.0.0",
"@vitest/browser": "^3.0.5",
"@vitest/coverage-istanbul": "^3.0.5",
@ -79,13 +68,5 @@
"**/*.css": [
"stylelint --quiet --allow-empty-input"
]
},
"nx": {
"name": "ckeditor5-keyboard-marker",
"targets": {
"build": {
"cache": "true"
}
}
}
}

View File

@ -1,4 +1,4 @@
import kbdIcon from '../theme/icons/kbd.svg';
import kbdIcon from '../theme/icons/kbd.svg?raw';
import './augmentation.js';
export { default as Kbd } from './kbd.js';

View File

@ -1,5 +1,5 @@
import { AttributeCommand, ButtonView, Plugin } from 'ckeditor5';
import kbdIcon from '../theme/icons/kbd.svg';
import kbdIcon from '../theme/icons/kbd.svg?raw';
const KBD = 'kbd';

View File

@ -1,4 +1,4 @@
declare module '*.svg' {
declare module '*.svg?raw' {
const content: string;
export default content;
}

View File

@ -12,18 +12,7 @@
"katex"
],
"type": "module",
"main": "dist/index.ts",
"module": "dist/index.js",
"types": "dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
},
"./*": "./dist/*",
"./browser/*": null,
"./package.json": "./package.json"
},
"main": "src/index.ts",
"author": "Sauli Anto",
"license": "ISC",
"engines": {
@ -39,7 +28,7 @@
"@ckeditor/ckeditor5-dev-utils": "43.1.0",
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
"@ckeditor/ckeditor5-package-tools": "^4.0.0",
"@typescript-eslint/eslint-plugin": "~8.41.0",
"@typescript-eslint/eslint-plugin": "~8.42.0",
"@typescript-eslint/parser": "^8.0.0",
"@vitest/browser": "^3.0.5",
"@vitest/coverage-istanbul": "^3.0.5",
@ -81,14 +70,6 @@
"stylelint --quiet --allow-empty-input"
]
},
"nx": {
"name": "ckeditor5-math",
"targets": {
"build": {
"cache": "true"
}
}
},
"dependencies": {
"@ckeditor/ckeditor5-icons": "46.0.2"
}

View File

@ -1,4 +1,4 @@
import ckeditor from './../theme/icons/math.svg';
import ckeditor from './../theme/icons/math.svg?raw';
import './augmentation.js';
import "../theme/mathform.css";

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