mirror of
https://github.com/zadam/trilium.git
synced 2025-11-18 03:00:41 +01:00
Merge remote-tracking branch 'origin/develop' into develop
This commit is contained in:
@@ -9,7 +9,7 @@ import BUILTIN_ATTRIBUTES from "./builtin_attributes.js";
|
||||
import BNote from "../becca/entities/bnote.js";
|
||||
import { AttributeRow } from '../becca/entities/rows.js';
|
||||
|
||||
const ATTRIBUTE_TYPES = ['label', 'relation'];
|
||||
const ATTRIBUTE_TYPES = new Set(['label', 'relation']);
|
||||
|
||||
function getNotesWithLabel(name: string, value?: string): BNote[] {
|
||||
const query = attributeFormatter.formatAttrForSearch({type: 'label', name, value}, value !== undefined);
|
||||
@@ -99,7 +99,7 @@ function getAttributeNames(type: string, nameLike: string) {
|
||||
}
|
||||
|
||||
function isAttributeType(type: string): boolean {
|
||||
return ATTRIBUTE_TYPES.includes(type);
|
||||
return ATTRIBUTE_TYPES.has(type);
|
||||
}
|
||||
|
||||
function isAttributeDangerous(type: string, name: string): boolean {
|
||||
|
||||
@@ -754,7 +754,7 @@ class ConsistencyChecks {
|
||||
const attrNames = sql.getColumn<string>(`SELECT DISTINCT name FROM attributes`);
|
||||
|
||||
for (const origName of attrNames) {
|
||||
const fixedName = sanitizeAttributeName.sanitizeAttributeName(origName);
|
||||
const fixedName = sanitizeAttributeName(origName);
|
||||
|
||||
if (fixedName !== origName) {
|
||||
if (this.autoFix) {
|
||||
|
||||
@@ -151,7 +151,7 @@ function importEnex(taskContext: TaskContext, file: File, parentNote: BNote): Pr
|
||||
labelName = 'pageUrl';
|
||||
}
|
||||
|
||||
labelName = sanitizeAttributeName.sanitizeAttributeName(labelName || "");
|
||||
labelName = sanitizeAttributeName(labelName || "");
|
||||
|
||||
if (note.attributes) {
|
||||
note.attributes.push({
|
||||
@@ -202,7 +202,7 @@ function importEnex(taskContext: TaskContext, file: File, parentNote: BNote): Pr
|
||||
} else if (currentTag === 'tag' && note.attributes) {
|
||||
note.attributes.push({
|
||||
type: 'label',
|
||||
name: sanitizeAttributeName.sanitizeAttributeName(text),
|
||||
name: sanitizeAttributeName(text),
|
||||
value: ''
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
import optionService from "./options.js";
|
||||
import log from "./log.js";
|
||||
import { isElectron as getIsElectron } from "./utils.js";
|
||||
import { isElectron as getIsElectron, isMac as getIsMac } from "./utils.js";
|
||||
import { KeyboardShortcut } from './keyboard_actions_interface.js';
|
||||
import { t } from "i18next";
|
||||
|
||||
const isMac = process.platform === "darwin";
|
||||
const isMac = getIsMac();
|
||||
const isElectron = getIsElectron();
|
||||
|
||||
function getDefaultKeyboardActions() {
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Request, Response } from "express";
|
||||
import fs from "fs";
|
||||
import dataDir from "./data_dir.js";
|
||||
import cls from "./cls.js";
|
||||
import { isWindows } from "./utils.js";
|
||||
|
||||
if (!fs.existsSync(dataDir.LOG_DIR)) {
|
||||
fs.mkdirSync(dataDir.LOG_DIR, 0o700);
|
||||
@@ -16,7 +17,7 @@ const MINUTE = 60 * SECOND;
|
||||
const HOUR = 60 * MINUTE;
|
||||
const DAY = 24 * HOUR;
|
||||
|
||||
const NEW_LINE = process.platform === "win32" ? '\r\n' : '\n';
|
||||
const NEW_LINE = isWindows() ? '\r\n' : '\n';
|
||||
|
||||
let todaysMidnight!: Date;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import optionService from "./options.js";
|
||||
import type { OptionMap } from "./options.js";
|
||||
import appInfo from "./app_info.js";
|
||||
import { randomSecureToken } from "./utils.js";
|
||||
import { randomSecureToken, isWindows } from "./utils.js";
|
||||
import log from "./log.js";
|
||||
import dateUtils from "./date_utils.js";
|
||||
import keyboardActions from "./keyboard_actions.js";
|
||||
@@ -72,7 +72,7 @@ const defaultOptions: DefaultOption[] = [
|
||||
{ name: 'revisionSnapshotTimeInterval', value: '600', isSynced: true },
|
||||
{ name: 'revisionSnapshotNumberLimit', value: '-1', isSynced: true },
|
||||
{ name: 'protectedSessionTimeout', value: '600', isSynced: true },
|
||||
{ name: 'zoomFactor', value: process.platform === "win32" ? '0.9' : '1.0', isSynced: false },
|
||||
{ name: 'zoomFactor', value: isWindows() ? '0.9' : '1.0', isSynced: false },
|
||||
{ name: 'overrideThemeFonts', value: 'false', isSynced: false },
|
||||
{ name: 'mainFontFamily', value: 'theme', isSynced: false },
|
||||
{ name: 'mainFontSize', value: '100', isSynced: false },
|
||||
|
||||
@@ -1,18 +1,8 @@
|
||||
function sanitizeAttributeName(origName: string) {
|
||||
let fixedName: string;
|
||||
|
||||
if (origName === '') {
|
||||
fixedName = "unnamed";
|
||||
}
|
||||
else {
|
||||
export default function sanitizeAttributeName(origName: string) {
|
||||
const fixedName = (origName === '')
|
||||
? "unnamed"
|
||||
: origName.replace(/[^\p{L}\p{N}_:]/ug, "_");
|
||||
// any not allowed character should be replaced with underscore
|
||||
fixedName = origName.replace(/[^\p{L}\p{N}_:]/ug, "_");
|
||||
}
|
||||
|
||||
return fixedName;
|
||||
}
|
||||
|
||||
|
||||
export default {
|
||||
sanitizeAttributeName
|
||||
};
|
||||
}
|
||||
@@ -13,7 +13,7 @@ import { normalize } from "../../utils.js";
|
||||
import sql from "../../sql.js";
|
||||
|
||||
|
||||
const ALLOWED_OPERATORS = ['=', '!=', '*=*', '*=', '=*', '%='];
|
||||
const ALLOWED_OPERATORS = new Set(['=', '!=', '*=*', '*=', '=*', '%=']);
|
||||
|
||||
const cachedRegexes: Record<string, RegExp> = {};
|
||||
|
||||
@@ -50,8 +50,8 @@ class NoteContentFulltextExp extends Expression {
|
||||
}
|
||||
|
||||
execute(inputNoteSet: NoteSet, executionContext: {}, searchContext: SearchContext) {
|
||||
if (!ALLOWED_OPERATORS.includes(this.operator)) {
|
||||
searchContext.addError(`Note content can be searched only with operators: ${ALLOWED_OPERATORS.join(", ")}, operator ${this.operator} given.`);
|
||||
if (!ALLOWED_OPERATORS.has(this.operator)) {
|
||||
searchContext.addError(`Note content can be searched only with operators: ${Array.from(ALLOWED_OPERATORS).join(", ")}, operator ${this.operator} given.`);
|
||||
|
||||
return inputNoteSet;
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ function getFulltext(_tokens: TokenData[], searchContext: SearchContext) {
|
||||
}
|
||||
}
|
||||
|
||||
const OPERATORS = [
|
||||
const OPERATORS = new Set([
|
||||
"=",
|
||||
"!=",
|
||||
"*=*",
|
||||
@@ -55,14 +55,14 @@ const OPERATORS = [
|
||||
"<",
|
||||
"<=",
|
||||
"%="
|
||||
];
|
||||
]);
|
||||
|
||||
function isOperator(token: TokenData) {
|
||||
if (Array.isArray(token)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return OPERATORS.includes(token.token);
|
||||
return OPERATORS.has(token.token);
|
||||
}
|
||||
|
||||
function getExpression(tokens: TokenData[], searchContext: SearchContext, level = 0) {
|
||||
|
||||
@@ -152,19 +152,19 @@ export function getContentDisposition(filename: string) {
|
||||
return `file; filename="${sanitizedFilename}"; filename*=UTF-8''${sanitizedFilename}`;
|
||||
}
|
||||
|
||||
const STRING_MIME_TYPES = [
|
||||
const STRING_MIME_TYPES = new Set([
|
||||
"application/javascript",
|
||||
"application/x-javascript",
|
||||
"application/json",
|
||||
"application/x-sql",
|
||||
"image/svg+xml"
|
||||
];
|
||||
]);
|
||||
|
||||
export function isStringNote(type: string | undefined, mime: string) {
|
||||
// render and book are string note in the sense that they are expected to contain empty string
|
||||
return (type && ["text", "code", "relationMap", "search", "render", "book", "mermaid", "canvas"].includes(type))
|
||||
|| mime.startsWith('text/')
|
||||
|| STRING_MIME_TYPES.includes(mime);
|
||||
|| STRING_MIME_TYPES.has(mime);
|
||||
}
|
||||
|
||||
export function quoteRegex(url: string) {
|
||||
@@ -332,6 +332,14 @@ export function getResourceDir() {
|
||||
}
|
||||
}
|
||||
|
||||
export function isMac() {
|
||||
return process.platform === "darwin";
|
||||
}
|
||||
|
||||
export function isWindows() {
|
||||
return process.platform === "win32";
|
||||
}
|
||||
|
||||
export default {
|
||||
randomSecureToken,
|
||||
randomString,
|
||||
@@ -365,5 +373,7 @@ export default {
|
||||
hashedBlobId,
|
||||
toMap,
|
||||
isString,
|
||||
getResourceDir
|
||||
getResourceDir,
|
||||
isMac,
|
||||
isWindows
|
||||
};
|
||||
|
||||
@@ -9,6 +9,7 @@ import cls from "./cls.js";
|
||||
import keyboardActionsService from "./keyboard_actions.js";
|
||||
import remoteMain from "@electron/remote/main/index.js";
|
||||
import { App, BrowserWindow, BrowserWindowConstructorOptions, WebContents, ipcMain } from 'electron';
|
||||
import { isMac, isWindows } from "./utils.js";
|
||||
|
||||
import { fileURLToPath } from "url";
|
||||
import { dirname } from "path";
|
||||
@@ -115,14 +116,11 @@ async function createMainWindow(app: App) {
|
||||
function getWindowExtraOpts() {
|
||||
const extraOpts: Partial<BrowserWindowConstructorOptions> = {};
|
||||
|
||||
const isMac = (process.platform === "darwin");
|
||||
const isWindows = (process.platform === "win32");
|
||||
|
||||
if (!optionService.getOptionBool('nativeTitleBarVisible')) {
|
||||
if (isMac) {
|
||||
if (isMac()) {
|
||||
extraOpts.titleBarStyle = "hiddenInset";
|
||||
extraOpts.titleBarOverlay = true;
|
||||
} else if (isWindows) {
|
||||
} else if (isWindows()) {
|
||||
extraOpts.titleBarStyle = "hidden";
|
||||
extraOpts.titleBarOverlay = true;
|
||||
} else {
|
||||
@@ -132,7 +130,7 @@ function getWindowExtraOpts() {
|
||||
}
|
||||
|
||||
// Window effects (Mica)
|
||||
if (optionService.getOptionBool('backgroundEffects') && isWindows) {
|
||||
if (optionService.getOptionBool('backgroundEffects') && isWindows()) {
|
||||
extraOpts.backgroundMaterial = "auto";
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user