mirror of
https://github.com/zadam/trilium.git
synced 2025-06-06 09:58:32 +02:00
use electron 8 spellchecker instead of electron-spellchecker, WIP
This commit is contained in:
parent
a2d6a5c3e9
commit
16f42dd4ab
@ -1,4 +1,4 @@
|
||||
FROM node:12.16.0-alpine
|
||||
FROM node:12.16.1-alpine
|
||||
|
||||
# Create app directory
|
||||
WORKDIR /usr/src/app
|
||||
|
@ -11,11 +11,9 @@ echo "Copying required linux-x64 binaries"
|
||||
|
||||
rm -r $SRC_DIR/node_modules/sqlite3/lib/binding/*
|
||||
rm -r $SRC_DIR/node_modules/pngquant-bin/vendor/*
|
||||
rm -r $SRC_DIR/node_modules/@felixrieseberg/spellchecker/build/Release/*
|
||||
|
||||
cp -r bin/deps/linux-x64/sqlite/* $SRC_DIR/node_modules/sqlite3/lib/binding/
|
||||
cp bin/deps/linux-x64/image/pngquant $SRC_DIR/node_modules/pngquant-bin/vendor/
|
||||
cp bin/deps/linux-x64/spellchecker/* $SRC_DIR/node_modules/@felixrieseberg/spellchecker/build/Release/
|
||||
|
||||
./node_modules/.bin/electron-packager $SRC_DIR --asar --out=dist --executable-name=trilium --platform=linux --arch=x64 --overwrite
|
||||
|
||||
|
@ -13,15 +13,11 @@ rm -r $SRC_DIR/node_modules/sqlite3/lib/binding/*
|
||||
rm -r $SRC_DIR/node_modules/mozjpeg/vendor/*
|
||||
rm -r $SRC_DIR/node_modules/pngquant-bin/vendor/*
|
||||
rm -r $SRC_DIR/node_modules/giflossy/vendor/*
|
||||
rm -r $SRC_DIR/node_modules/@felixrieseberg/spellchecker/build/Release/*
|
||||
rm -r $SRC_DIR/node_modules/keyboard-layout/build/Release/*
|
||||
|
||||
cp -r bin/deps/mac-x64/sqlite/* $SRC_DIR/node_modules/sqlite3/lib/binding/
|
||||
cp bin/deps/mac-x64/image/cjpeg $SRC_DIR/node_modules/mozjpeg/vendor/
|
||||
cp bin/deps/mac-x64/image/pngquant $SRC_DIR/node_modules/pngquant-bin/vendor/
|
||||
cp bin/deps/mac-x64/image/gifsicle $SRC_DIR/node_modules/giflossy/vendor/
|
||||
cp bin/deps/mac-x64/spellchecker/* $SRC_DIR/node_modules/@felixrieseberg/spellchecker/build/Release/
|
||||
cp bin/deps/mac-x64/keyboard-layout-manager.node $SRC_DIR/node_modules/keyboard-layout/build/Release/
|
||||
|
||||
./node_modules/.bin/electron-packager $SRC_DIR --asar --out=dist --executable-name=trilium --platform=darwin --arch=x64 --overwrite --icon=images/app-icons/mac/icon.icns
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
PKG_DIR=dist/trilium-linux-x64-server
|
||||
NODE_VERSION=12.16.0
|
||||
NODE_VERSION=12.16.1
|
||||
|
||||
if [ "$1" != "DONTCOPY" ]
|
||||
then
|
||||
|
@ -13,16 +13,11 @@ rm -r $SRC_DIR/node_modules/sqlite3/lib/binding/*
|
||||
rm -r $SRC_DIR/node_modules/mozjpeg/vendor/*
|
||||
rm -r $SRC_DIR/node_modules/pngquant-bin/vendor/*
|
||||
rm -r $SRC_DIR/node_modules/giflossy/vendor/*
|
||||
rm -r $SRC_DIR/node_modules/@felixrieseberg/spellchecker/build/Release/*
|
||||
rm -r $SRC_DIR/node_modules/keyboard-layout/build/Release/*
|
||||
rm -r $SRC_DIR/node_modules/cld/build/Release/*
|
||||
|
||||
cp -r bin/deps/win-x64/sqlite/* $SRC_DIR/node_modules/sqlite3/lib/binding/
|
||||
cp bin/deps/win-x64/image/cjpeg.exe $SRC_DIR/node_modules/mozjpeg/vendor/
|
||||
cp bin/deps/win-x64/image/pngquant.exe $SRC_DIR/node_modules/pngquant-bin/vendor/
|
||||
cp bin/deps/win-x64/image/gifsicle.exe $SRC_DIR/node_modules/giflossy/vendor/
|
||||
cp bin/deps/win-x64/spellchecker/* $SRC_DIR/node_modules/@felixrieseberg/spellchecker/build/Release/
|
||||
cp bin/deps/win-x64/keyboard-layout-manager.node $SRC_DIR/node_modules/keyboard-layout/build/Release/
|
||||
|
||||
./node_modules/.bin/electron-packager $SRC_DIR --asar --out=dist --executable-name=trilium --platform=win32 --arch=x64 --overwrite --icon=images/app-icons/win/icon.ico
|
||||
|
||||
|
@ -26,7 +26,4 @@ cp -r electron.js $DIR/
|
||||
# run in subshell (so we return to original dir)
|
||||
(cd $DIR && npm install --only=prod)
|
||||
|
||||
rm -r $DIR/node_modules/cld/deps
|
||||
|
||||
find $DIR/libraries -name "*.map" -type f -delete
|
||||
find $DIR/libraries -name "hunspell.lib" -type f -delete
|
||||
find $DIR/libraries -name "*.map" -type f -delete
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
6
package-lock.json
generated
6
package-lock.json
generated
@ -2669,9 +2669,9 @@
|
||||
"integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA=="
|
||||
},
|
||||
"electron": {
|
||||
"version": "9.0.0-beta.3",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-9.0.0-beta.3.tgz",
|
||||
"integrity": "sha512-se2XiC3sc6o8EUL/uE7bOknW7/gh37mQ+7uX8idugfYyK1oCISfr5CqtVXOMNTwMtx0opdFQ1HFC+W2ckNiPXg==",
|
||||
"version": "9.0.0-beta.4",
|
||||
"resolved": "https://registry.npmjs.org/electron/-/electron-9.0.0-beta.4.tgz",
|
||||
"integrity": "sha512-XznzkZ8nWTclg7B/Bue8PgXPyaYygZvtIqiNSmI3mgJ710F69RO2IrM3Rs1ULS3qWA3sTDY6PO0UPyUeTxhP7g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@electron/get": "^1.0.1",
|
||||
|
@ -33,7 +33,6 @@
|
||||
"electron-debug": "3.0.1",
|
||||
"electron-dl": "3.0.0",
|
||||
"electron-find": "1.0.6",
|
||||
"electron-spellchecker": "2.2.1",
|
||||
"electron-window-state": "5.0.3",
|
||||
"express": "4.17.1",
|
||||
"express-session": "1.17.0",
|
||||
@ -75,7 +74,7 @@
|
||||
"ws": "7.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "9.0.0-beta.3",
|
||||
"electron": "9.0.0-beta.4",
|
||||
"electron-builder": "22.3.2",
|
||||
"electron-packager": "14.2.1",
|
||||
"electron-rebuild": "1.10.0",
|
||||
|
@ -66,6 +66,7 @@ import RenderTypeWidget from "./widgets/type_widgets/render.js";
|
||||
import RelationMapTypeWidget from "./widgets/type_widgets/relation_map.js";
|
||||
import ProtectedSessionTypeWidget from "./widgets/type_widgets/protected_session.js";
|
||||
import BookTypeWidget from "./widgets/type_widgets/book.js";
|
||||
import contextMenuService from "./services/context_menu.js";
|
||||
|
||||
if (utils.isElectron()) {
|
||||
require('electron').ipcRenderer.on('globalShortcut', async function(event, actionName) {
|
||||
@ -83,4 +84,44 @@ appContext.start();
|
||||
|
||||
noteTooltipService.setupGlobalTooltip();
|
||||
|
||||
noteAutocompleteService.init();
|
||||
noteAutocompleteService.init();
|
||||
|
||||
if (utils.isElectron()) {
|
||||
const {webContents} = require('electron').remote.getCurrentWindow();
|
||||
|
||||
webContents.on('context-menu', (event, params) => {
|
||||
const items = [
|
||||
{title: "Hello", cmd: "openNoteInNewTab", uiIcon: "arrow-up-right"}
|
||||
];
|
||||
|
||||
if (params.misspelledWord) {
|
||||
items.push({
|
||||
title: `Misspelled "<strong>${params.misspelledWord}</strong>"`,
|
||||
cmd: "openNoteInNewTab",
|
||||
uiIcon: ""
|
||||
});
|
||||
|
||||
for (const suggestion of params.dictionarySuggestions) {
|
||||
items.push({
|
||||
title: suggestion,
|
||||
command: "replaceMisspelling",
|
||||
spellingSuggestion: suggestion,
|
||||
uiIcon: ""
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
contextMenuService.initContextMenu({
|
||||
x: params.x,
|
||||
y: params.y,
|
||||
items,
|
||||
selectContextMenuItem: (e, {command, spellingSuggestion}) => {
|
||||
if (command === 'replaceMisspelling') {
|
||||
console.log("Replacing missspeling", spellingSuggestion);
|
||||
|
||||
require('electron').remote.getCurrentWindow().webContents.insertText(spellingSuggestion);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
@ -16,11 +16,11 @@ const TPL = `
|
||||
<br/>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="spell-check-language-code">Language code</label>
|
||||
<label for="spell-check-language-code">Language code(s)</label>
|
||||
<input type="text" class="form-control" id="spell-check-language-code" placeholder="for example "en-US", "de-AT"">
|
||||
</div>
|
||||
|
||||
<p>Changes to the spell check options will take effect after application restart.</p>
|
||||
<p>Multiple languages can be separated by comman. Changes to the spell check options will take effect after application restart.</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
@ -21,9 +21,7 @@ function initAttributeNameAutocomplete({ $el, attributeType, open }) {
|
||||
const type = typeof attributeType === "function" ? attributeType() : attributeType;
|
||||
|
||||
const names = await server.get(`attributes/names/?type=${type}&query=${encodeURIComponent(term)}`);
|
||||
const result = names.map(name => {
|
||||
return {name};
|
||||
});
|
||||
const result = names.map(name => ({name}));
|
||||
|
||||
cb(result);
|
||||
}
|
||||
@ -44,7 +42,7 @@ async function initLabelValueAutocomplete({ $el, open }) {
|
||||
}
|
||||
|
||||
const attributeValues = (await server.get('attributes/values/' + encodeURIComponent(attributeName)))
|
||||
.map(attribute => { return { value: attribute }; });
|
||||
.map(attribute => ({ value: attribute }));
|
||||
|
||||
if (attributeValues.length === 0) {
|
||||
return;
|
||||
|
@ -3,15 +3,7 @@ const $contextMenuContainer = $("#context-menu-container");
|
||||
|
||||
let dateContextMenuOpenedMs = 0;
|
||||
|
||||
/**
|
||||
* @param event - originating click event (used to get coordinates to display menu at position)
|
||||
* @param {object} contextMenu - needs to have getContextMenuItems() and selectContextMenuItem(e, cmd)
|
||||
*/
|
||||
async function initContextMenu(event, contextMenu) {
|
||||
event.stopPropagation();
|
||||
|
||||
$contextMenuContainer.empty();
|
||||
|
||||
async function initContextMenu(options) {
|
||||
function addItems($parent, items) {
|
||||
for (const item of items) {
|
||||
if (item.title === '----') {
|
||||
@ -33,15 +25,14 @@ async function initContextMenu(event, contextMenu) {
|
||||
const $item = $("<li>")
|
||||
.addClass("dropdown-item")
|
||||
.append($link)
|
||||
.attr("data-cmd", item.cmd)
|
||||
.on('click', function (e) {
|
||||
const cmd = $(e.target).closest(".dropdown-item").attr("data-cmd");
|
||||
.on('mousedown', function (e) {
|
||||
e.stopPropagation();
|
||||
|
||||
hideContextMenu();
|
||||
|
||||
e.originalTarget = event.target;
|
||||
|
||||
contextMenu.selectContextMenuItem(e, cmd);
|
||||
|
||||
hideContextMenu();
|
||||
options.selectContextMenuItem(e, item);
|
||||
|
||||
// it's important to stop the propagation especially for sub-menus, otherwise the event
|
||||
// might be handled again by top-level menu
|
||||
@ -68,21 +59,22 @@ async function initContextMenu(event, contextMenu) {
|
||||
}
|
||||
}
|
||||
|
||||
addItems($contextMenuContainer, await contextMenu.getContextMenuItems());
|
||||
$contextMenuContainer.empty();
|
||||
|
||||
addItems($contextMenuContainer, options.items);
|
||||
|
||||
keyboardActionService.updateDisplayedShortcuts($contextMenuContainer);
|
||||
|
||||
// code below tries to detect when dropdown would overflow from page
|
||||
// in such case we'll position it above click coordinates so it will fit into client
|
||||
const clickPosition = event.pageY;
|
||||
const clientHeight = document.documentElement.clientHeight;
|
||||
const contextMenuHeight = $contextMenuContainer.outerHeight() + 30;
|
||||
let top;
|
||||
|
||||
if (clickPosition + contextMenuHeight > clientHeight) {
|
||||
if (options.y + contextMenuHeight > clientHeight) {
|
||||
top = clientHeight - contextMenuHeight - 10;
|
||||
} else {
|
||||
top = event.pageY - 10;
|
||||
top = options.y - 10;
|
||||
}
|
||||
|
||||
dateContextMenuOpenedMs = Date.now();
|
||||
@ -90,7 +82,7 @@ async function initContextMenu(event, contextMenu) {
|
||||
$contextMenuContainer.css({
|
||||
display: "block",
|
||||
top: top,
|
||||
left: event.pageX - 20
|
||||
left: options.x - 20
|
||||
}).addClass("show");
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import options from "./options.js";
|
||||
|
||||
export async function initSpellCheck() {
|
||||
export async function initSpellCheck() {return;
|
||||
const {SpellCheckHandler, ContextMenuListener, ContextMenuBuilder} = require('electron-spellchecker');
|
||||
const {remote, shell} = require('electron');
|
||||
|
||||
|
@ -120,10 +120,10 @@ export default class NoteTreeWidget extends TabAwareWidget {
|
||||
|
||||
node.setSelected(true);
|
||||
|
||||
const notes = this.getSelectedNodes().map(node => { return {
|
||||
const notes = this.getSelectedNodes().map(node => ({
|
||||
noteId: node.data.noteId,
|
||||
title: node.title
|
||||
}});
|
||||
}));
|
||||
|
||||
data.dataTransfer.setData("text", JSON.stringify(notes));
|
||||
|
||||
|
@ -125,7 +125,7 @@ export default class PromotedAttributesWidget extends TabAwareWidget {
|
||||
return;
|
||||
}
|
||||
|
||||
attributeValues = attributeValues.map(attribute => { return { value: attribute }; });
|
||||
attributeValues = attributeValues.map(attribute => ({ value: attribute }));
|
||||
|
||||
$input.autocomplete({
|
||||
appendTo: document.querySelector('body'),
|
||||
|
@ -114,12 +114,10 @@ export default class TextTypeWidget extends TypeWidget {
|
||||
const codeBlockLanguages =
|
||||
(await mimeTypesService.getMimeTypes())
|
||||
.filter(mt => mt.enabled)
|
||||
.map(mt => {
|
||||
return {
|
||||
.map(mt => ({
|
||||
language: mt.mime.toLowerCase().replace(/[\W_]+/g,"-"),
|
||||
label: mt.title
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
// CKEditor since version 12 needs the element to be visible before initialization. At the same time
|
||||
// we want to avoid flicker - i.e. show editor only once everything is ready. That's why we have separate
|
||||
|
@ -43,6 +43,7 @@ body {
|
||||
min-height: 0;
|
||||
padding-left: 10px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
|
@ -133,12 +133,12 @@ async function getRelationMap(req) {
|
||||
|
||||
resp.relations = resp.relations.concat((await note.getRelations())
|
||||
.filter(relation => noteIds.includes(relation.value))
|
||||
.map(relation => { return {
|
||||
.map(relation => ({
|
||||
attributeId: relation.attributeId,
|
||||
sourceNoteId: relation.noteId,
|
||||
targetNoteId: relation.value,
|
||||
name: relation.name
|
||||
}; }));
|
||||
})));
|
||||
|
||||
for (const relationDefinition of await note.getRelationDefinitions()) {
|
||||
if (relationDefinition.value.inverseRelation) {
|
||||
|
@ -121,15 +121,13 @@ async function exportToTar(taskContext, branch, format, res) {
|
||||
type: note.type,
|
||||
mime: note.mime,
|
||||
// we don't export utcDateCreated and utcDateModified of any entity since that would be a bit misleading
|
||||
attributes: (await note.getOwnedAttributes()).map(attribute => {
|
||||
return {
|
||||
attributes: (await note.getOwnedAttributes()).map(attribute => ({
|
||||
type: attribute.type,
|
||||
name: attribute.name,
|
||||
value: attribute.value,
|
||||
isInheritable: attribute.isInheritable,
|
||||
position: attribute.position
|
||||
};
|
||||
})
|
||||
}))
|
||||
};
|
||||
|
||||
taskContext.increaseProgressCount();
|
||||
|
@ -102,13 +102,11 @@ async function initStartupOptions() {
|
||||
function getKeyboardDefaultOptions() {
|
||||
return keyboardActions.DEFAULT_KEYBOARD_ACTIONS
|
||||
.filter(ka => !!ka.actionName)
|
||||
.map(ka => {
|
||||
return {
|
||||
name: "keyboardShortcuts" + ka.actionName.charAt(0).toUpperCase() + ka.actionName.slice(1),
|
||||
value: JSON.stringify(ka.defaultShortcuts),
|
||||
isSynced: false
|
||||
};
|
||||
});
|
||||
.map(ka => ({
|
||||
name: "keyboardShortcuts" + ka.actionName.charAt(0).toUpperCase() + ka.actionName.slice(1),
|
||||
value: JSON.stringify(ka.defaultShortcuts),
|
||||
isSynced: false
|
||||
}));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
@ -23,6 +23,8 @@ async function createMainWindow() {
|
||||
defaultHeight: 800
|
||||
});
|
||||
|
||||
const spellcheckEnabled = await optionService.getOptionBool('spellCheckEnabled');
|
||||
|
||||
const {BrowserWindow} = require('electron'); // should not be statically imported
|
||||
mainWindow = new BrowserWindow({
|
||||
x: mainWindowState.x,
|
||||
@ -31,7 +33,8 @@ async function createMainWindow() {
|
||||
height: mainWindowState.height,
|
||||
title: 'Trilium Notes',
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
nodeIntegration: true,
|
||||
spellcheck: spellcheckEnabled
|
||||
},
|
||||
frame: await optionService.getOptionBool('nativeTitleBarVisible'),
|
||||
icon: getIcon()
|
||||
@ -43,15 +46,17 @@ async function createMainWindow() {
|
||||
mainWindow.loadURL('http://127.0.0.1:' + await port);
|
||||
mainWindow.on('closed', () => mainWindow = null);
|
||||
|
||||
mainWindow.webContents.on('new-window', (e, url) => {
|
||||
if (url !== mainWindow.webContents.getURL()) {
|
||||
const {webContents} = mainWindow;
|
||||
|
||||
webContents.on('new-window', (e, url) => {
|
||||
if (url !== webContents.getURL()) {
|
||||
e.preventDefault();
|
||||
require('electron').shell.openExternal(url);
|
||||
}
|
||||
});
|
||||
|
||||
// prevent drag & drop to navigate away from trilium
|
||||
mainWindow.webContents.on('will-navigate', (ev, targetUrl) => {
|
||||
webContents.on('will-navigate', (ev, targetUrl) => {
|
||||
const parsedUrl = url.parse(targetUrl);
|
||||
|
||||
// we still need to allow internal redirects from setup and migration pages
|
||||
@ -59,6 +64,14 @@ async function createMainWindow() {
|
||||
ev.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
if (spellcheckEnabled) {
|
||||
const languageCodes = (await optionService.getOption('spellCheckLanguageCode'))
|
||||
.split('/')
|
||||
.map(code => code.trim());
|
||||
|
||||
webContents.session.setSpellCheckerLanguages(languageCodes);
|
||||
}
|
||||
}
|
||||
|
||||
function getIcon() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user