use electron 8 spellchecker instead of electron-spellchecker, WIP

This commit is contained in:
zadam
2020-02-28 22:07:08 +01:00
parent a2d6a5c3e9
commit 16f42dd4ab
30 changed files with 98 additions and 74 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
FROM node:12.16.0-alpine
FROM node:12.16.1-alpine
# Create app directory
WORKDIR /usr/src/app
-2
View File
@@ -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
-4
View File
@@ -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 -1
View File
@@ -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
-5
View File
@@ -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
+1 -4
View File
@@ -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.
+3 -3
View File
@@ -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",
+1 -2
View File
@@ -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",
+42 -1
View File
@@ -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 &quot;en-US&quot;, &quot;de-AT&quot;">
</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;
+12 -20
View File
@@ -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');
+2 -2
View File
@@ -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
+1
View File
@@ -43,6 +43,7 @@ body {
min-height: 0;
padding-left: 10px;
width: 100%;
height: 100%;
}
.dropdown-menu {
+2 -2
View File
@@ -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) {
+2 -4
View File
@@ -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();
+5 -7
View File
@@ -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 = {
+17 -4
View File
@@ -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() {