mirror of
https://github.com/TriliumNext/Notes.git
synced 2025-08-10 02:02:29 +08:00
Merge branch 'feature/trilium_next_theme' of https://github.com/TriliumNext/Notes into feature/trilium_next_theme
This commit is contained in:
commit
b6dda4983c
12
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
12
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -3,6 +3,12 @@ description: Report a bug
|
||||
title: "(Bug report) "
|
||||
labels: "Type: Bug"
|
||||
body:
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Description
|
||||
description: A clear and concise description of the bug and any additional information.
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: TriliumNext Version
|
||||
@ -38,12 +44,6 @@ body:
|
||||
placeholder: "e.g. Windows 10 version 1909, macOS Catalina 10.15.7, or Ubuntu 20.04"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Description
|
||||
description: A clear and concise description of the bug and any additional information.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Error logs
|
||||
|
@ -17,17 +17,45 @@
|
||||
#
|
||||
# --------------------------------------------------------------------------------------------------
|
||||
|
||||
number_of_keys() {
|
||||
[ -f "$1" ] && jq 'path(..) | select(length == 2) | .[1]' "$1" | wc -l || echo "0"
|
||||
}
|
||||
|
||||
stats() {
|
||||
# Print the number of existing strings on the JSON files for each locale
|
||||
s=$(jq 'path(..) | select(length == 2) | .[1]' "${paths[0]}/en/server.json" | wc -l)
|
||||
c=$(jq 'path(..) | select(length == 2) | .[1]' "${paths[1]}/en/translation.json" | wc -l)
|
||||
echo "|locale |server strings |client strings |"
|
||||
echo "|-------|---------------|---------------|"
|
||||
echo "| en | ${s} | ${c} |"
|
||||
s=$(number_of_keys "${paths[0]}/en/server.json")
|
||||
c=$(number_of_keys "${paths[1]}/en/translation.json")
|
||||
echo "| locale |server strings |client strings |"
|
||||
echo "|--------|---------------|---------------|"
|
||||
echo "| en | ${s} | ${c} |"
|
||||
for locale in "${locales[@]}"; do
|
||||
s=$(jq 'path(..) | select(length == 2) | .[1]' "${paths[0]}/${locale}/server.json" | wc -l)
|
||||
c=$(jq 'path(..) | select(length == 2) | .[1]' "${paths[1]}/${locale}/translation.json" | wc -l)
|
||||
echo "| ${locale} | ${s} | ${c} |"
|
||||
s=$(number_of_keys "${paths[0]}/${locale}/server.json")
|
||||
c=$(number_of_keys "${paths[1]}/${locale}/translation.json")
|
||||
n1=$(((8 - ${#locale}) / 2))
|
||||
n2=$((n1 == 1 ? n1 + 1 : n1))
|
||||
echo "|$(printf "%${n1}s")${locale}$(printf "%${n2}s")| ${s} | ${c} |"
|
||||
done
|
||||
}
|
||||
|
||||
update_1() {
|
||||
# Update PO files from English and localized JSON files as source
|
||||
# NOTE: if you want a new language you need to first create the JSON files
|
||||
# on their corresponding place with `{}` as content to avoid error on `json2po`
|
||||
local locales=("$@")
|
||||
for path in "${paths[@]}"; do
|
||||
for locale in "${locales[@]}"; do
|
||||
json2po -t "${path}/en" "${path}/${locale}" "${path}/po-${locale}"
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
update_2() {
|
||||
# Recover translation from PO files to localized JSON files
|
||||
local locales=("$@")
|
||||
for path in "${paths[@]}"; do
|
||||
for locale in "${locales[@]}"; do
|
||||
po2json -t "${path}/en" "${path}/po-${locale}" "${path}/${locale}"
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
@ -35,11 +63,11 @@ help() {
|
||||
echo -e "\nDescription:"
|
||||
echo -e "\tCreate PO files to make easier the labor of translation"
|
||||
echo -e "\nUsage:"
|
||||
echo -e "\t./translation.sh [--stats] [--update <OPT_LOCALE>] [--update2 <OPT_LOCALE>]"
|
||||
echo -e "\t./translation.sh [--stats] [--update1 <OPT_LOCALE>] [--update2 <OPT_LOCALE>]"
|
||||
echo -e "\nFlags:"
|
||||
echo -e " --clear\n\tClear all po-* directories"
|
||||
echo -e " --stats\n\tPrint the number of existing strings on the JSON files for each locale"
|
||||
echo -e " --update <LOCALE>\n\tUpdate PO files from English and localized JSON files as source"
|
||||
echo -e " --update1 <LOCALE>\n\tUpdate PO files from English and localized JSON files as source"
|
||||
echo -e " --update2 <LOCALE>\n\tRecover translation from PO files to localized JSON files"
|
||||
}
|
||||
|
||||
@ -51,7 +79,7 @@ file_path="$(
|
||||
pwd -P
|
||||
)"
|
||||
paths=("${file_path}/../translations/" "${file_path}/../src/public/translations/")
|
||||
locales=(cn es fr ro)
|
||||
locales=(cn de es fr pt_br ro tw)
|
||||
|
||||
if [ $# -eq 1 ]; then
|
||||
if [ "$1" == "--clear" ]; then
|
||||
@ -62,34 +90,18 @@ if [ $# -eq 1 ]; then
|
||||
done
|
||||
elif [ "$1" == "--stats" ]; then
|
||||
stats
|
||||
elif [ "$1" == "--update" ]; then
|
||||
# Update PO files from English and localized JSON files as source
|
||||
for path in "${paths[@]}"; do
|
||||
for locale in "${locales[@]}"; do
|
||||
json2po -t "${path}/en" "${path}/${locale}" "${path}/po-${locale}"
|
||||
done
|
||||
done
|
||||
elif [ "$1" == "--update1" ]; then
|
||||
update_1 "${locales[@]}"
|
||||
elif [ "$1" == "--update2" ]; then
|
||||
# Recover translation from PO files to localized JSON files
|
||||
for path in "${paths[@]}"; do
|
||||
for locale in "${locales[@]}"; do
|
||||
po2json -t "${path}/en" "${path}/po-${locale}" "${path}/${locale}"
|
||||
done
|
||||
done
|
||||
update_2 "${locales[@]}"
|
||||
else
|
||||
help
|
||||
fi
|
||||
elif [ $# -eq 2 ]; then
|
||||
if [ "$1" == "--update" ]; then
|
||||
locale="$2"
|
||||
for path in "${paths[@]}"; do
|
||||
json2po -t "${path}/en" "${path}/${locale}" "${path}/po-${locale}"
|
||||
done
|
||||
if [ "$1" == "--update1" ]; then
|
||||
update_1 "$2"
|
||||
elif [ "$1" == "--update2" ]; then
|
||||
locale="$2"
|
||||
for path in "${paths[@]}"; do
|
||||
po2json -t "${path}/en" "${path}/po-${locale}" "${path}/${locale}"
|
||||
done
|
||||
update_2 "$2"
|
||||
else
|
||||
help
|
||||
fi
|
||||
|
BIN
db/demo.zip
BIN
db/demo.zip
Binary file not shown.
1
libraries/mermaid-elk/elk.min.js
vendored
Normal file
1
libraries/mermaid-elk/elk.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
13
libraries/mermaid-elk/package-lock.json
generated
Normal file
13
libraries/mermaid-elk/package-lock.json
generated
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "mermaid-elk",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "mermaid-elk",
|
||||
"version": "1.0.0",
|
||||
"license": "ISC"
|
||||
}
|
||||
}
|
||||
}
|
13
libraries/mermaid-elk/package.json
Normal file
13
libraries/mermaid-elk/package.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "mermaid-elk",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build": "cross-env node --import ../../loader-register.js ../../node_modules/webpack/bin/webpack.js -c webpack.config.cjs"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"description": "",
|
||||
"dependencies": {}
|
||||
}
|
19
libraries/mermaid-elk/webpack.config.cjs
Normal file
19
libraries/mermaid-elk/webpack.config.cjs
Normal file
@ -0,0 +1,19 @@
|
||||
const path = require("path");
|
||||
const webpack = require("webpack");
|
||||
|
||||
module.exports = {
|
||||
mode: "production",
|
||||
entry: "../../node_modules/@mermaid-js/layout-elk/dist/mermaid-layout-elk.esm.min.mjs",
|
||||
output: {
|
||||
library: "MERMAID_ELK",
|
||||
filename: "elk.min.js",
|
||||
path: path.resolve(__dirname),
|
||||
libraryTarget: "umd",
|
||||
libraryExport: "default"
|
||||
},
|
||||
plugins: [
|
||||
new webpack.optimize.LimitChunkCountPlugin({
|
||||
maxChunks: 1
|
||||
})
|
||||
]
|
||||
}
|
22
package-lock.json
generated
22
package-lock.json
generated
@ -1,18 +1,19 @@
|
||||
{
|
||||
"name": "trilium",
|
||||
"version": "0.90.11-beta",
|
||||
"version": "0.90.12",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "trilium",
|
||||
"version": "0.90.11-beta",
|
||||
"version": "0.90.12",
|
||||
"license": "AGPL-3.0-only",
|
||||
"dependencies": {
|
||||
"@braintree/sanitize-url": "7.1.0",
|
||||
"@electron/remote": "2.1.2",
|
||||
"@excalidraw/excalidraw": "0.17.6",
|
||||
"@highlightjs/cdn-assets": "11.10.0",
|
||||
"@mermaid-js/layout-elk": "0.1.5",
|
||||
"archiver": "7.0.1",
|
||||
"async-mutex": "0.5.0",
|
||||
"autocomplete.js": "0.38.1",
|
||||
@ -3072,6 +3073,18 @@
|
||||
"url": "https://github.com/malept/cross-spawn-promise?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@mermaid-js/layout-elk": {
|
||||
"version": "0.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@mermaid-js/layout-elk/-/layout-elk-0.1.5.tgz",
|
||||
"integrity": "sha512-6ML4iWdVdyIkSW47KiID9runHzaomLxdMfNo9U60LJvfcQkB/FAjg0Vjc4AZEQnnBq7ibAoAknAWlT1XetwXSg==",
|
||||
"dependencies": {
|
||||
"d3": "^7.9.0",
|
||||
"elkjs": "^0.9.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"mermaid": "^11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@mermaid-js/parser": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-0.3.0.tgz",
|
||||
@ -7904,6 +7917,11 @@
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
||||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
|
||||
},
|
||||
"node_modules/elkjs": {
|
||||
"version": "0.9.3",
|
||||
"resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.9.3.tgz",
|
||||
"integrity": "sha512-f/ZeWvW/BCXbhGEf1Ujp29EASo/lk1FDnETgNKwJrsVvGZhUWCZyg3xLJjAsxfOmt8KjswHmI5EwCQcPMpOYhQ=="
|
||||
},
|
||||
"node_modules/emitter-listener": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/emitter-listener/-/emitter-listener-1.1.2.tgz",
|
||||
|
@ -2,7 +2,7 @@
|
||||
"name": "trilium",
|
||||
"productName": "TriliumNext Notes",
|
||||
"description": "Build your personal knowledge base with TriliumNext Notes",
|
||||
"version": "0.90.11-beta",
|
||||
"version": "0.90.12",
|
||||
"license": "AGPL-3.0-only",
|
||||
"main": "./dist/electron-main.js",
|
||||
"author": {
|
||||
@ -54,6 +54,7 @@
|
||||
"@electron/remote": "2.1.2",
|
||||
"@excalidraw/excalidraw": "0.17.6",
|
||||
"@highlightjs/cdn-assets": "11.10.0",
|
||||
"@mermaid-js/layout-elk": "0.1.5",
|
||||
"archiver": "7.0.1",
|
||||
"async-mutex": "0.5.0",
|
||||
"autocomplete.js": "0.38.1",
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { t } from '../services/i18n.js';
|
||||
import utils from "../services/utils.js";
|
||||
import contextMenu from "./context_menu.js";
|
||||
import imageService from "../services/image.js";
|
||||
@ -18,14 +19,14 @@ function setupContextMenu($image) {
|
||||
y: e.pageY,
|
||||
items: [
|
||||
{
|
||||
title: "Copy reference to clipboard",
|
||||
title: t("image_context_menu.copy_reference_to_clipboard"),
|
||||
command: "copyImageReferenceToClipboard",
|
||||
uiIcon: "bx bx-directions"
|
||||
},
|
||||
{
|
||||
title: "Copy image to clipboard",
|
||||
{
|
||||
title: t("image_context_menu.copy_image_to_clipboard"),
|
||||
command: "copyImageToClipboard",
|
||||
uiIcon: "bx bx-copy"
|
||||
uiIcon: "bx bx-copy"
|
||||
},
|
||||
],
|
||||
selectMenuItemHandler: async ({ command }) => {
|
||||
@ -61,4 +62,4 @@ function setupContextMenu($image) {
|
||||
|
||||
export default {
|
||||
setupContextMenu
|
||||
};
|
||||
};
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { t } from "../services/i18n.js";
|
||||
import contextMenu from "./context_menu.js";
|
||||
import appContext from "../components/app_context.js";
|
||||
|
||||
@ -6,9 +7,9 @@ function openContextMenu(notePath, e, viewScope = {}, hoistedNoteId = null) {
|
||||
x: e.pageX,
|
||||
y: e.pageY,
|
||||
items: [
|
||||
{title: "Open note in a new tab", command: "openNoteInNewTab", uiIcon: "bx bx-link-external"},
|
||||
{title: "Open note in a new split", command: "openNoteInNewSplit", uiIcon: "bx bx-dock-right"},
|
||||
{title: "Open note in a new window", command: "openNoteInNewWindow", uiIcon: "bx bx-window-open"}
|
||||
{title: t("link_context_menu.open_note_in_new_tab"), command: "openNoteInNewTab", uiIcon: "bx bx-link-external"},
|
||||
{title: t("link_context_menu.open_note_in_new_split"), command: "openNoteInNewSplit", uiIcon: "bx bx-dock-right"},
|
||||
{title: t("link_context_menu.open_note_in_new_window"), command: "openNoteInNewWindow", uiIcon: "bx bx-window-open"}
|
||||
],
|
||||
selectMenuItemHandler: ({command}) => {
|
||||
if (!hoistedNoteId) {
|
||||
|
@ -12,6 +12,7 @@ import FAttachment from "../entities/fattachment.js";
|
||||
import imageContextMenuService from "../menus/image_context_menu.js";
|
||||
import { applySingleBlockSyntaxHighlight, applySyntaxHighlight } from "./syntax_highlight.js";
|
||||
import mime_types from "./mime_types.js";
|
||||
import { loadElkIfNeeded } from "./mermaid.js";
|
||||
|
||||
let idCounter = 1;
|
||||
|
||||
@ -237,6 +238,7 @@ async function renderMermaid(note, $renderedContent) {
|
||||
mermaid.mermaidAPI.initialize({startOnLoad: false, theme: mermaidTheme.trim(), securityLevel: 'antiscript'});
|
||||
|
||||
try {
|
||||
await loadElkIfNeeded(content);
|
||||
const {svg} = await mermaid.mermaidAPI.render("in-mermaid-graph-" + idCounter++, content);
|
||||
|
||||
$renderedContent.append($(svg));
|
||||
|
@ -58,7 +58,19 @@ const FORCE_GRAPH = {
|
||||
};
|
||||
|
||||
const MERMAID = {
|
||||
js: [ "node_modules/mermaid/dist/mermaid.min.js" ]
|
||||
js: [
|
||||
"node_modules/mermaid/dist/mermaid.min.js"
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* The ELK extension of Mermaid.js, which supports more advanced layouts.
|
||||
* See https://www.npmjs.com/package/@mermaid-js/layout-elk for more information.
|
||||
*/
|
||||
const MERMAID_ELK = {
|
||||
js: [
|
||||
"libraries/mermaid-elk/elk.min.js"
|
||||
]
|
||||
}
|
||||
|
||||
const EXCALIDRAW = {
|
||||
@ -197,6 +209,7 @@ export default {
|
||||
WHEEL_ZOOM,
|
||||
FORCE_GRAPH,
|
||||
MERMAID,
|
||||
MERMAID_ELK,
|
||||
EXCALIDRAW,
|
||||
MARKJS,
|
||||
I18NEXT,
|
||||
|
28
src/public/app/services/mermaid.js
Normal file
28
src/public/app/services/mermaid.js
Normal file
@ -0,0 +1,28 @@
|
||||
import library_loader from "./library_loader.js";
|
||||
|
||||
let elkLoaded = false;
|
||||
|
||||
/**
|
||||
* Determines whether the ELK extension of Mermaid.js needs to be loaded (which is a relatively large library), based on the
|
||||
* front-matter of the diagram and loads the library if needed.
|
||||
*
|
||||
* <p>
|
||||
* If the library has already been loaded or the diagram does not require it, the method will exit immediately.
|
||||
*
|
||||
* @param mermaidContent the plain text of the mermaid diagram, potentially including a frontmatter.
|
||||
*/
|
||||
export async function loadElkIfNeeded(mermaidContent) {
|
||||
if (elkLoaded) {
|
||||
// Exit immediately since the ELK library is already loaded.
|
||||
return;
|
||||
}
|
||||
|
||||
const parsedContent = await mermaid.parse(mermaidContent, {
|
||||
suppressErrors: true
|
||||
});
|
||||
if (parsedContent?.config?.layout === "elk") {
|
||||
elkLoaded = true;
|
||||
await library_loader.requireLibrary(library_loader.MERMAID_ELK);
|
||||
mermaid.registerLayoutLoaders(MERMAID_ELK);
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@ function parse(value) {
|
||||
if (token === 'promoted') {
|
||||
defObj.isPromoted = true;
|
||||
}
|
||||
else if (['text', 'number', 'boolean', 'date', 'datetime', 'url'].includes(token)) {
|
||||
else if (['text', 'number', 'boolean', 'date', 'datetime', 'time', 'url'].includes(token)) {
|
||||
defObj.labelType = token;
|
||||
}
|
||||
else if (['single', 'multi'].includes(token)) {
|
||||
|
@ -125,6 +125,7 @@ const TPL = `
|
||||
<option value="boolean">${t('attribute_detail.boolean')}</option>
|
||||
<option value="date">${t('attribute_detail.date')}</option>
|
||||
<option value="datetime">${t('attribute_detail.date_time')}</option>
|
||||
<option value="time">${t('attribute_detail.time')}</option>
|
||||
<option value="url">${t('attribute_detail.url')}</option>
|
||||
</select>
|
||||
</td>
|
||||
|
@ -4,8 +4,8 @@ import BookmarkFolderWidget from "./buttons/bookmark_folder.js";
|
||||
import froca from "../services/froca.js";
|
||||
|
||||
export default class BookmarkButtons extends FlexContainer {
|
||||
constructor() {
|
||||
super("column");
|
||||
constructor(isHorizontalLayout) {
|
||||
super(isHorizontalLayout ? "row" : "column");
|
||||
|
||||
this.contentSized();
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ export default class LauncherWidget extends BasicWidget {
|
||||
|
||||
return new SpacerWidget(baseSize, growthFactor);
|
||||
case "bookmarks":
|
||||
return new BookmarkButtons();
|
||||
return new BookmarkButtons(this.isHorizontalLayout);
|
||||
case "protectedSession":
|
||||
return new ProtectedSessionStatusWidget();
|
||||
case "syncStatus":
|
||||
|
@ -3,6 +3,7 @@ import libraryLoader from "../services/library_loader.js";
|
||||
import NoteContextAwareWidget from "./note_context_aware_widget.js";
|
||||
import server from "../services/server.js";
|
||||
import utils from "../services/utils.js";
|
||||
import { loadElkIfNeeded } from "../services/mermaid.js";
|
||||
|
||||
const TPL = `<div class="mermaid-widget">
|
||||
<style>
|
||||
@ -57,10 +58,10 @@ export default class MermaidWidget extends NoteContextAwareWidget {
|
||||
this.$errorContainer.hide();
|
||||
|
||||
await libraryLoader.requireLibrary(libraryLoader.MERMAID);
|
||||
|
||||
|
||||
const documentStyle = window.getComputedStyle(document.documentElement);
|
||||
const mermaidTheme = documentStyle.getPropertyValue('--mermaid-theme');
|
||||
|
||||
const mermaidTheme = documentStyle.getPropertyValue('--mermaid-theme');
|
||||
|
||||
mermaid.mermaidAPI.initialize({
|
||||
startOnLoad: false,
|
||||
theme: mermaidTheme.trim(),
|
||||
@ -111,6 +112,7 @@ export default class MermaidWidget extends NoteContextAwareWidget {
|
||||
zoomOnClick: false
|
||||
});
|
||||
} catch (e) {
|
||||
console.warn(e);
|
||||
this.$errorMessage.text(e.message);
|
||||
this.$errorContainer.show();
|
||||
}
|
||||
@ -122,6 +124,7 @@ export default class MermaidWidget extends NoteContextAwareWidget {
|
||||
const blob = await this.note.getBlob();
|
||||
const content = blob.content || "";
|
||||
|
||||
await loadElkIfNeeded(content);
|
||||
const {svg} = await mermaid.mermaidAPI.render(`mermaid-graph-${idCounter}`, content);
|
||||
return svg;
|
||||
}
|
||||
|
@ -225,6 +225,9 @@ export default class PromotedAttributesWidget extends NoteContextAwareWidget {
|
||||
else if (definition.labelType === 'datetime') {
|
||||
$input.prop('type', 'datetime-local')
|
||||
}
|
||||
else if (definition.labelType === 'time') {
|
||||
$input.prop('type', 'time')
|
||||
}
|
||||
else if (definition.labelType === 'url') {
|
||||
$input.prop("placeholder", t("promoted_attributes.url_placeholder"));
|
||||
|
||||
|
@ -1,45 +1,53 @@
|
||||
import NoteContextAwareWidget from "../../note_context_aware_widget.js";
|
||||
import server from "../../../services/server.js";
|
||||
import { t } from "../../../services/i18n.js";
|
||||
import AbstractCodeTypeWidget from "../abstract_code_type_widget.js";
|
||||
|
||||
const TPL = `<div style="height: 100%; display: flex; flex-direction: column;">
|
||||
<style>
|
||||
.backend-log-textarea {
|
||||
.backend-log-editor {
|
||||
flex-grow: 1;
|
||||
width: 100%;
|
||||
border: none;
|
||||
resize: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<textarea class="backend-log-textarea" readonly="readonly"></textarea>
|
||||
<pre class="backend-log-editor"></pre>
|
||||
|
||||
<div style="display: flex; justify-content: space-around; margin-top: 10px;">
|
||||
<button class="refresh-backend-log-button btn btn-primary">${t("backend_log.refresh")}</button>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
export default class BackendLogWidget extends NoteContextAwareWidget {
|
||||
export default class BackendLogWidget extends AbstractCodeTypeWidget {
|
||||
doRender() {
|
||||
super.doRender();
|
||||
this.$widget = $(TPL);
|
||||
this.$backendLogTextArea = this.$widget.find(".backend-log-textarea");
|
||||
this.$editor = this.$widget.find(".backend-log-editor");
|
||||
|
||||
this.$refreshBackendLog = this.$widget.find(".refresh-backend-log-button");
|
||||
|
||||
this.$refreshBackendLog.on('click', () => this.load());
|
||||
}
|
||||
|
||||
scrollToBottom() {
|
||||
this.$backendLogTextArea.scrollTop(this.$backendLogTextArea[0].scrollHeight);
|
||||
}
|
||||
|
||||
async refresh() {
|
||||
await this.load();
|
||||
}
|
||||
|
||||
getExtraOpts() {
|
||||
return {
|
||||
lineWrapping: false,
|
||||
readOnly: true
|
||||
};
|
||||
}
|
||||
|
||||
async load() {
|
||||
const backendLog = await server.get('backend-log');
|
||||
const content = await server.get('backend-log');
|
||||
await this.initialized;
|
||||
|
||||
this.$backendLogTextArea.text(backendLog);
|
||||
|
||||
this.scrollToBottom();
|
||||
this._update({
|
||||
mime: "text/plain"
|
||||
}, content);
|
||||
this.show();
|
||||
this.scrollToEnd();
|
||||
}
|
||||
}
|
||||
|
@ -185,8 +185,8 @@
|
||||
|
||||
--root-background: var(--left-pane-background-color);
|
||||
|
||||
--gutter-color: #e7e7e7;
|
||||
--gutter-hover-color: #bfbfbf;
|
||||
--gutter-color: transparent;
|
||||
--gutter-hover-color: #5e5e5e;
|
||||
|
||||
--active-tab-background-color: #666;
|
||||
--active-tab-hover-background-color: #737373;
|
||||
@ -256,7 +256,11 @@
|
||||
padding-bottom: var(--launcher-pane-button-gap);
|
||||
}
|
||||
|
||||
#launcher-pane.vertical .launcher-button {
|
||||
#launcher-pane.horizontal {
|
||||
height: var(--launcher-pane-size) !important;
|
||||
}
|
||||
|
||||
#launcher-pane .launcher-button {
|
||||
width: calc(var(--launcher-pane-size) - (var(--launcher-pane-button-margin) * 2)) !important;
|
||||
height: calc(var(--launcher-pane-size) - (var(--launcher-pane-button-margin) * 2)) !important;
|
||||
margin: var(--launcher-pane-button-gap) var(--launcher-pane-button-margin);
|
||||
@ -268,14 +272,14 @@
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
#launcher-pane.vertical .launcher-button:active,
|
||||
#launcher-pane.vertical .launcher-button.show {
|
||||
#launcher-pane .launcher-button:active,
|
||||
#launcher-pane .launcher-button.show {
|
||||
transform: scale(0.9);
|
||||
transition: transform 50ms linear;
|
||||
}
|
||||
|
||||
#launcher-pane.vertical .launcher-button:hover,
|
||||
#launcher-pane.vertical .launcher-button.right-dropdown-button.show {
|
||||
#launcher-pane .launcher-button:hover,
|
||||
#launcher-pane .launcher-button.right-dropdown-button.show {
|
||||
background: var(--launcher-pane-button-hover-background);
|
||||
color: var(--launcher-pane-button-hover-color);
|
||||
box-shadow: var(--launcher-pane-button-hover-shadow);
|
||||
|
@ -15,7 +15,13 @@
|
||||
"message": "发生了严重错误,导致客户端应用程序无法启动:\n\n{{message}}\n\n这很可能是由于脚本以意外的方式失败引起的。请尝试以安全模式启动应用程序并解决问题。"
|
||||
},
|
||||
"widget-error": {
|
||||
"title": "小部件初始化失败"
|
||||
"title": "小部件初始化失败",
|
||||
"message-custom": "来自 ID 为 \"{{id}}\"、标题为 \"{{title}}\" 的笔记的自定义小部件因以下原因无法初始化:\n\n{{message}}",
|
||||
"message-unknown": "未知小部件因以下原因无法初始化:\n\n{{message}}"
|
||||
},
|
||||
"bundle-error": {
|
||||
"title": "加载自定义脚本失败",
|
||||
"message": "来自 ID 为 \"{{id}}\"、标题为 \"{{title}}\" 的笔记的脚本因以下原因无法执行:\n\n{{message}}"
|
||||
}
|
||||
},
|
||||
"add_link": {
|
||||
@ -45,7 +51,11 @@
|
||||
"chosen_actions": "选择的操作",
|
||||
"execute_bulk_actions": "执行批量操作",
|
||||
"bulk_actions_executed": "批量操作已成功执行。",
|
||||
"none_yet": "暂无操作 ... 通过点击上方的可用操作添加一个操作。"
|
||||
"none_yet": "暂无操作 ... 通过点击上方的可用操作添加一个操作。",
|
||||
"labels": "标签",
|
||||
"relations": "关联关系",
|
||||
"notes": "笔记",
|
||||
"other": "其它"
|
||||
},
|
||||
"clone_to": {
|
||||
"clone_notes_to": "克隆笔记到...",
|
||||
@ -164,7 +174,8 @@
|
||||
"textImportedAsText": "如果元数据不明确,将HTML、Markdown和TXT导入为文本笔记",
|
||||
"codeImportedAsCode": "如果元数据不明确,将识别的代码文件(例如<code>.json</code>)导入为代码笔记",
|
||||
"replaceUnderscoresWithSpaces": "在导入的笔记名称中将下划线替换为空格",
|
||||
"import": "导入"
|
||||
"import": "导入",
|
||||
"failed": "导入失败: {{message}}."
|
||||
},
|
||||
"include_note": {
|
||||
"dialog_title": "包含笔记",
|
||||
@ -304,6 +315,7 @@
|
||||
"boolean": "布尔值",
|
||||
"date": "日期",
|
||||
"date_time": "日期和时间",
|
||||
"time": "时间",
|
||||
"url": "网址",
|
||||
"precision_title": "值设置界面中浮点数后的位数。",
|
||||
"precision": "精度",
|
||||
@ -630,7 +642,10 @@
|
||||
"export_note": "导出笔记",
|
||||
"delete_note": "删除笔记",
|
||||
"print_note": "打印笔记",
|
||||
"save_revision": "保存笔记历史"
|
||||
"save_revision": "保存笔记历史",
|
||||
"convert_into_attachment_failed": "笔记 '{{title}}' 转换失败。",
|
||||
"convert_into_attachment_successful": "笔记 '{{title}}' 已成功转换为附件。",
|
||||
"convert_into_attachment_prompt": "确定要将笔记 '{{title}}' 转换为父笔记的附件吗?"
|
||||
},
|
||||
"onclick_button": {
|
||||
"no_click_handler": "按钮组件'{{componentId}}'没有定义点击处理程序"
|
||||
@ -885,7 +900,8 @@
|
||||
"label_rock_or_pop": "只需一个标签存在即可",
|
||||
"label_year_comparison": "数字比较(也包括>,>=,<)。",
|
||||
"label_date_created": "上个月创建的笔记",
|
||||
"error": "搜索错误:{{error}}"
|
||||
"error": "搜索错误:{{error}}",
|
||||
"search_prefix": "搜索:"
|
||||
},
|
||||
"attachment_detail": {
|
||||
"open_help_page": "打开附件帮助页面",
|
||||
@ -919,7 +935,15 @@
|
||||
},
|
||||
"protected_session": {
|
||||
"enter_password_instruction": "显示受保护的笔记需要输入您的密码:",
|
||||
"start_session_button": "开始受保护的会话"
|
||||
"start_session_button": "开始受保护的会话",
|
||||
"started": "受保护的会话已启动。",
|
||||
"wrong_password": "密码错误。",
|
||||
"protecting-finished-successfully": "保护操作已成功完成。",
|
||||
"unprotecting-finished-successfully": "解除保护操作已成功完成。",
|
||||
"protecting-in-progress": "保护进行中:{{count}}",
|
||||
"unprotecting-in-progress-count": "解除保护进行中:{{count}}",
|
||||
"protecting-title": "保护状态",
|
||||
"unprotecting-title": "解除保护状态"
|
||||
},
|
||||
"relation_map": {
|
||||
"open_in_new_tab": "在新标签页中打开",
|
||||
@ -990,7 +1014,9 @@
|
||||
"fill_entity_changes_button": "填充实体变更记录",
|
||||
"full_sync_triggered": "全量同步已触发",
|
||||
"filling_entity_changes": "正在填充实体变更行...",
|
||||
"sync_rows_filled_successfully": "同步行填充成功"
|
||||
"sync_rows_filled_successfully": "同步行填充成功",
|
||||
"finished-successfully": "同步已完成。",
|
||||
"failed": "同步失败:{{message}}"
|
||||
},
|
||||
"vacuum_database": {
|
||||
"title": "数据库清理",
|
||||
@ -1036,8 +1062,13 @@
|
||||
"theme_label": "主题",
|
||||
"override_theme_fonts_label": "覆盖主题字体",
|
||||
"light_theme": "浅色",
|
||||
"dark_theme": "深色"
|
||||
},
|
||||
"dark_theme": "深色",
|
||||
"layout": "布局",
|
||||
"layout-vertical-title": "垂直",
|
||||
"layout-horizontal-title": "水平",
|
||||
"layout-vertical-description": "启动栏位于左侧(默认)",
|
||||
"layout-horizontal-description": "启动栏位于标签栏下方,标签栏现在是全宽的。"
|
||||
},
|
||||
"zoom_factor": {
|
||||
"title": "缩放系数(仅桌面客户端有效)",
|
||||
"description": "缩放也可以通过 CTRL+- 和 CTRL+= 快捷键进行控制。"
|
||||
@ -1162,6 +1193,8 @@
|
||||
"backup_now": "立即备份",
|
||||
"backup_database_now": "立即备份数据库",
|
||||
"existing_backups": "现有备份",
|
||||
"date-and-time": "日期和时间",
|
||||
"path": "路径",
|
||||
"database_backed_up_to": "数据库已备份到",
|
||||
"no_backup_yet": "尚无备份"
|
||||
},
|
||||
@ -1309,7 +1342,9 @@
|
||||
"duplicate-subtree": "复制子树",
|
||||
"export": "导出",
|
||||
"import-into-note": "导入到笔记",
|
||||
"apply-bulk-actions": "应用批量操作"
|
||||
"apply-bulk-actions": "应用批量操作",
|
||||
"converted-to-attachments": "{{count}} 个笔记已被转换为附件。",
|
||||
"convert-to-attachment-confirm": "确定要将选中的笔记转换为其父笔记的附件吗?"
|
||||
},
|
||||
"shared_info": {
|
||||
"shared_publicly": "此笔记已公开分享在",
|
||||
@ -1332,7 +1367,8 @@
|
||||
"image": "图片",
|
||||
"launcher": "启动器",
|
||||
"doc": "文档",
|
||||
"widget": "小部件"
|
||||
"widget": "小部件",
|
||||
"confirm-change": "当笔记内容不为空时,不建议更改笔记类型。您仍然要继续吗?"
|
||||
},
|
||||
"protect_note": {
|
||||
"toggle-on": "保护笔记",
|
||||
@ -1355,7 +1391,11 @@
|
||||
"open-help-page": "打开帮助页面",
|
||||
"find": {
|
||||
"case_sensitive": "区分大小写",
|
||||
"match_words": "匹配单词"
|
||||
"match_words": "匹配单词",
|
||||
"find_placeholder": "在文本中查找...",
|
||||
"replace_placeholder": "替换为...",
|
||||
"replace": "替换",
|
||||
"replace_all": "全部替换"
|
||||
},
|
||||
"highlights_list_2": {
|
||||
"title": "高亮列表",
|
||||
@ -1378,7 +1418,9 @@
|
||||
"hide-archived-notes": "隐藏已归档笔记",
|
||||
"automatically-collapse-notes": "自动折叠笔记",
|
||||
"automatically-collapse-notes-title": "笔记在一段时间内未使用将被折叠,以减少树形结构的杂乱。",
|
||||
"save-changes": "保存并应用更改"
|
||||
"save-changes": "保存并应用更改",
|
||||
"auto-collapsing-notes-after-inactivity": "在不活动后自动折叠笔记...",
|
||||
"saved-search-note-refreshed": "已保存的搜索笔记已刷新。"
|
||||
},
|
||||
"title_bar_buttons": {
|
||||
"window-on-top": "保持此窗口置顶"
|
||||
@ -1407,8 +1449,11 @@
|
||||
"add_new_tab": "添加新标签页",
|
||||
"close": "关闭",
|
||||
"close_other_tabs": "关闭其他标签页",
|
||||
"close_right_tabs": "关闭右侧标签页",
|
||||
"close_all_tabs": "关闭所有标签页",
|
||||
"reopen_last_tab": "重新打开最后一个关闭的标签页",
|
||||
"move_tab_to_new_window": "将此标签页移动到新窗口",
|
||||
"copy_tab_to_new_window": "将此标签页复制到新窗口",
|
||||
"new_tab": "新标签页"
|
||||
},
|
||||
"toc": {
|
||||
@ -1422,5 +1467,101 @@
|
||||
},
|
||||
"app_context": {
|
||||
"please_wait_for_save": "请等待几秒钟以完成保存,然后您可以尝试再操作一次。"
|
||||
},
|
||||
"note_create": {
|
||||
"duplicated": "笔记 \"{{title}}\" 已被复制。"
|
||||
},
|
||||
"image": {
|
||||
"copied-to-clipboard": "图片的引用已复制到剪贴板,可以粘贴到任何文本笔记中。",
|
||||
"cannot-copy": "无法将图片引用复制到剪贴板。"
|
||||
},
|
||||
"clipboard": {
|
||||
"cut": "笔记已剪切到剪贴板。",
|
||||
"copied": "笔记已复制到剪贴板。"
|
||||
},
|
||||
"entrypoints": {
|
||||
"note-revision-created": "笔记修订已创建。",
|
||||
"note-executed": "笔记已执行。",
|
||||
"sql-error": "执行 SQL 查询时发生错误:{{message}}"
|
||||
},
|
||||
"branches": {
|
||||
"cannot-move-notes-here": "无法将笔记移动到这里。",
|
||||
"delete-status": "删除状态",
|
||||
"delete-notes-in-progress": "正在删除笔记:{{count}}",
|
||||
"delete-finished-successfully": "删除成功完成。",
|
||||
"undeleting-notes-in-progress": "正在恢复删除的笔记:{{count}}",
|
||||
"undeleting-notes-finished-successfully": "恢复删除的笔记已成功完成。"
|
||||
},
|
||||
"frontend_script_api": {
|
||||
"async_warning": "您正在将一个异步函数传递给 `api.runOnBackend()`,这可能无法按预期工作。\\n要么使该函数同步(通过移除 `async` 关键字),要么使用 `api.runAsyncOnBackendWithManualTransactionHandling()`。",
|
||||
"sync_warning": "您正在将一个同步函数传递给 `api.runAsyncOnBackendWithManualTransactionHandling()`,\\n而您可能应该使用 `api.runOnBackend()`。"
|
||||
},
|
||||
"ws": {
|
||||
"sync-check-failed": "同步检查失败!",
|
||||
"consistency-checks-failed": "一致性检查失败!请查看日志了解详细信息。",
|
||||
"encountered-error": "遇到错误 \"{{message}}\",请查看控制台。"
|
||||
},
|
||||
"hoisted_note": {
|
||||
"confirm_unhoisting": "请求的笔记 '{{requestedNote}}' 位于提升的笔记 '{{hoistedNote}}' 的子树之外,您必须取消提升才能访问该笔记。是否继续取消提升?"
|
||||
},
|
||||
"launcher_context_menu": {
|
||||
"reset_launcher_confirm": "您确定要重置 \"{{title}}\" 吗?此笔记(及其子项)中的所有数据/设置将丢失,且启动器将恢复到其原始位置。",
|
||||
"add-note-launcher": "添加笔记启动器",
|
||||
"add-script-launcher": "添加脚本启动器",
|
||||
"add-custom-widget": "添加自定义小部件",
|
||||
"add-spacer": "添加间隔",
|
||||
"delete": "删除",
|
||||
"reset": "重置",
|
||||
"move-to-visible-launchers": "移动到可见启动器",
|
||||
"move-to-available-launchers": "移动到可用启动器",
|
||||
"duplicate-launcher": "复制启动器"
|
||||
},
|
||||
"editable-text": {
|
||||
"auto-detect-language": "自动检测"
|
||||
},
|
||||
"highlighting": {
|
||||
"title": "文本笔记的代码语法高亮",
|
||||
"description": "控制文本笔记中代码块的语法高亮,代码笔记不会受到影响。",
|
||||
"color-scheme": "颜色方案"
|
||||
},
|
||||
"code_block": {
|
||||
"word_wrapping": "自动换行"
|
||||
},
|
||||
"classic_editor_toolbar": {
|
||||
"title": "格式化"
|
||||
},
|
||||
"editor": {
|
||||
"title": "编辑器"
|
||||
},
|
||||
"editing": {
|
||||
"editor_type": {
|
||||
"label": "格式化工具栏",
|
||||
"floating": {
|
||||
"title": "浮动",
|
||||
"description": "编辑工具出现在光标附近;"
|
||||
},
|
||||
"fixed": {
|
||||
"title": "固定",
|
||||
"description": "编辑工具出现在 \"格式化\" 功能区标签中。"
|
||||
}
|
||||
}
|
||||
},
|
||||
"electron_context_menu": {
|
||||
"add-term-to-dictionary": "将 \"{{term}}\" 添加到字典",
|
||||
"cut": "剪切",
|
||||
"copy": "复制",
|
||||
"copy-link": "复制链接",
|
||||
"paste": "粘贴",
|
||||
"paste-as-plain-text": "以纯文本粘贴",
|
||||
"search_online": "用 {{searchEngine}} 搜索 \"{{term}}\""
|
||||
},
|
||||
"image_context_menu": {
|
||||
"copy_reference_to_clipboard": "复制引用到剪贴板",
|
||||
"copy_image_to_clipboard": "复制图片到剪贴板"
|
||||
},
|
||||
"link_context_menu": {
|
||||
"open_note_in_new_tab": "在新标签页中打开笔记",
|
||||
"open_note_in_new_split": "在新分屏中打开笔记",
|
||||
"open_note_in_new_window": "在新窗口中打开笔记"
|
||||
}
|
||||
}
|
||||
|
@ -310,6 +310,7 @@
|
||||
"boolean": "Boolescher Wert",
|
||||
"date": "Datum",
|
||||
"date_time": "Datum und Uhrzeit",
|
||||
"time": "Uhrzeit",
|
||||
"url": "URL",
|
||||
"precision_title": "Wie viele Nachkommastellen im Wert-Einstellungs-Interface verfügbar sein sollen.",
|
||||
"precision": "Präzision",
|
||||
|
@ -315,6 +315,7 @@
|
||||
"boolean": "Boolean",
|
||||
"date": "Date",
|
||||
"date_time": "Date & Time",
|
||||
"time": "Time",
|
||||
"url": "URL",
|
||||
"precision_title": "What number of digits after floating point should be available in the value setting interface.",
|
||||
"precision": "Precision",
|
||||
@ -1554,5 +1555,14 @@
|
||||
"paste": "Paste",
|
||||
"paste-as-plain-text": "Paste as plain text",
|
||||
"search_online": "Search for \"{{term}}\" with {{searchEngine}}"
|
||||
},
|
||||
"image_context_menu": {
|
||||
"copy_reference_to_clipboard": "Copy reference to clipboard",
|
||||
"copy_image_to_clipboard": "Copy image to clipboard"
|
||||
},
|
||||
"link_context_menu": {
|
||||
"open_note_in_new_tab": "Open note in a new tab",
|
||||
"open_note_in_new_split": "Open note in a new split",
|
||||
"open_note_in_new_window": "Open note in a new window"
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,11 @@
|
||||
"chosen_actions": "Acciones elegidas",
|
||||
"execute_bulk_actions": "Ejecutar acciones en bloque",
|
||||
"bulk_actions_executed": "Las acciones en bloque se han ejecutado con éxito.",
|
||||
"none_yet": "Ninguna todavía... agrega una acción haciendo clic en una de las disponibles arriba."
|
||||
"none_yet": "Ninguna todavía... agregue una acción haciendo clic en una de las disponibles arriba.",
|
||||
"labels": "Etiquetas",
|
||||
"relations": "Relaciones",
|
||||
"notes": "Notas",
|
||||
"other": "Otro"
|
||||
},
|
||||
"clone_to": {
|
||||
"clone_notes_to": "Clonar notas a...",
|
||||
@ -311,6 +315,7 @@
|
||||
"boolean": "Booleano",
|
||||
"date": "Fecha",
|
||||
"date_time": "Fecha y hora",
|
||||
"time": "Hora",
|
||||
"url": "URL",
|
||||
"precision_title": "Cantidad de dígitos después del punto flotante que deben estar disponibles en la interfaz de configuración del valor.",
|
||||
"precision": "Precisión",
|
||||
@ -1057,7 +1062,12 @@
|
||||
"theme_label": "Tema",
|
||||
"override_theme_fonts_label": "Sobreescribir fuentes de tema",
|
||||
"light_theme": "Claro",
|
||||
"dark_theme": "Oscuro"
|
||||
"dark_theme": "Oscuro",
|
||||
"layout": "Disposición",
|
||||
"layout-vertical-title": "Vertical",
|
||||
"layout-horizontal-title": "Horizontal",
|
||||
"layout-vertical-description": "la barra del lanzador está en la izquierda (por defecto)",
|
||||
"layout-horizontal-description": "la barra de lanzamiento está debajo de la barra de pestañas, la barra de pestañas ahora tiene ancho completo."
|
||||
},
|
||||
"zoom_factor": {
|
||||
"title": "Factor de zoom (solo versión de escritorio)",
|
||||
@ -1183,6 +1193,8 @@
|
||||
"backup_now": "Realizar copia de seguridad ahora",
|
||||
"backup_database_now": "Realizar copia de seguridad de la base de datos ahora",
|
||||
"existing_backups": "Copias de seguridad existentes",
|
||||
"date-and-time": "Fecha y hora",
|
||||
"path": "Ruta",
|
||||
"database_backed_up_to": "Se ha realizado una copia de seguridad de la base de datos en",
|
||||
"no_backup_yet": "no hay copia de seguridad todavía"
|
||||
},
|
||||
@ -1439,7 +1451,9 @@
|
||||
"close_other_tabs": "Cerrar otras pestañas",
|
||||
"close_right_tabs": "Cerrar pestañas a la derecha",
|
||||
"close_all_tabs": "Cerras todas las pestañas",
|
||||
"reopen_last_tab": "Reabrir última pestaña cerrada",
|
||||
"move_tab_to_new_window": "Mover esta pestaña a una nueva ventana",
|
||||
"copy_tab_to_new_window": "Copiar esta pestaña a una ventana nueva",
|
||||
"new_tab": "Nueva pestaña"
|
||||
},
|
||||
"toc": {
|
||||
@ -1531,5 +1545,14 @@
|
||||
"description": "las herramientas de edición aparecen en la pestaña de la cinta \"Formato\")."
|
||||
}
|
||||
}
|
||||
},
|
||||
"electron_context_menu": {
|
||||
"add-term-to-dictionary": "Agregar \"{{term}}\" al diccionario.",
|
||||
"cut": "Cortar",
|
||||
"copy": "Copiar",
|
||||
"copy-link": "Copiar enlace",
|
||||
"paste": "Pegar",
|
||||
"paste-as-plain-text": "Pegar como texto plano",
|
||||
"search_online": "Buscar \"{{term}}\" con {{searchEngine}}"
|
||||
}
|
||||
}
|
||||
|
@ -311,6 +311,7 @@
|
||||
"boolean": "Booléen",
|
||||
"date": "Date",
|
||||
"date_time": "Date et heure",
|
||||
"time": "Heure",
|
||||
"url": "URL",
|
||||
"precision_title": "Nombre de chiffres après la virgule devant être disponible dans l'interface définissant la valeur.",
|
||||
"precision": "Précision",
|
||||
|
1
src/public/translations/pt_br/translation.json
Normal file
1
src/public/translations/pt_br/translation.json
Normal file
@ -0,0 +1 @@
|
||||
{}
|
@ -127,6 +127,7 @@
|
||||
"custom_resource_provider": "a se vedea <a href=\"javascript:\" data-help-page=\"custom-request-handler.html\">Custom request handler</a>",
|
||||
"date": "Dată",
|
||||
"date_time": "Dată și timp",
|
||||
"time": "Timp",
|
||||
"delete": "Șterge",
|
||||
"digits": "număr de zecimale",
|
||||
"disable_inclusion": "script-urile cu această etichetă nu vor fi incluse în execuția scriptului părinte.",
|
||||
|
1
src/public/translations/tw/translation.json
Normal file
1
src/public/translations/tw/translation.json
Normal file
@ -0,0 +1 @@
|
||||
{}
|
@ -103,7 +103,8 @@ const HIDDEN_SUBTREE_DEFINITION: Item = {
|
||||
type: 'contentWidget',
|
||||
icon: 'bx-terminal',
|
||||
attributes: [
|
||||
{ type: 'label', name: 'keepCurrentHoisting' }
|
||||
{ type: 'label', name: 'keepCurrentHoisting' },
|
||||
{ type: 'label', name: 'fullContentWidth' }
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -8,7 +8,7 @@ function parse(value: string): DefinitionObject {
|
||||
if (token === 'promoted') {
|
||||
defObj.isPromoted = true;
|
||||
}
|
||||
else if (['text', 'number', 'boolean', 'date', 'datetime', 'url'].includes(token)) {
|
||||
else if (['text', 'number', 'boolean', 'date', 'datetime', 'time', 'url'].includes(token)) {
|
||||
defObj.labelType = token;
|
||||
}
|
||||
else if (['single', 'multi'].includes(token)) {
|
||||
|
@ -27,43 +27,52 @@ class SearchResult {
|
||||
this.score = 0;
|
||||
|
||||
const note = becca.notes[this.noteId];
|
||||
const normalizedQuery = fulltextQuery.toLowerCase();
|
||||
const normalizedTitle = note.title.toLowerCase();
|
||||
|
||||
// Note ID exact match, much higher score
|
||||
if (note.noteId.toLowerCase() === fulltextQuery) {
|
||||
this.score += 100;
|
||||
this.score += 1000;
|
||||
}
|
||||
|
||||
if (note.title.toLowerCase() === fulltextQuery) {
|
||||
this.score += 100; // high reward for exact match #3470
|
||||
// Title matching scores, make sure to always win
|
||||
if (normalizedTitle === normalizedQuery) {
|
||||
this.score += 2000; // Increased from 1000 to ensure exact matches always win
|
||||
}
|
||||
else if (normalizedTitle.startsWith(normalizedQuery)) {
|
||||
this.score += 500; // Increased to give more weight to prefix matches
|
||||
}
|
||||
else if (normalizedTitle.includes(` ${normalizedQuery} `) ||
|
||||
normalizedTitle.startsWith(`${normalizedQuery} `) ||
|
||||
normalizedTitle.endsWith(` ${normalizedQuery}`)) {
|
||||
this.score += 300; // Increased to better distinguish word matches
|
||||
}
|
||||
|
||||
// notes with matches on its own note title as opposed to ancestors or descendants
|
||||
this.addScoreForStrings(tokens, note.title, 1.5);
|
||||
|
||||
// matches in attributes don't get extra points and thus are implicitly valued less than note path matches
|
||||
|
||||
this.addScoreForStrings(tokens, this.notePathTitle, 1);
|
||||
// Add scores for partial matches with adjusted weights
|
||||
this.addScoreForStrings(tokens, note.title, 2.0); // Increased to give more weight to title matches
|
||||
this.addScoreForStrings(tokens, this.notePathTitle, 0.3); // Reduced to further de-emphasize path matches
|
||||
|
||||
if (note.isInHiddenSubtree()) {
|
||||
this.score = this.score / 2;
|
||||
this.score = this.score / 3; // Increased penalty for hidden notes
|
||||
}
|
||||
}
|
||||
|
||||
addScoreForStrings(tokens: string[], str: string, factor: number) {
|
||||
const chunks = str.toLowerCase().split(" ");
|
||||
|
||||
this.score = 0;
|
||||
|
||||
let tokenScore = 0;
|
||||
for (const chunk of chunks) {
|
||||
for (const token of tokens) {
|
||||
if (chunk === token) {
|
||||
this.score += 4 * token.length * factor;
|
||||
tokenScore += 4 * token.length * factor;
|
||||
} else if (chunk.startsWith(token)) {
|
||||
this.score += 2 * token.length * factor;
|
||||
tokenScore += 2 * token.length * factor;
|
||||
} else if (chunk.includes(token)) {
|
||||
this.score += token.length * factor;
|
||||
tokenScore += token.length * factor;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.score += tokenScore;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,8 @@
|
||||
"copy-without-formatting": "不带格式复制选定文本",
|
||||
"force-save-revision": "强制创建/保存当前笔记的历史版本",
|
||||
"show-help": "显示内置帮助/备忘单",
|
||||
"toggle-book-properties": "切换书籍属性"
|
||||
"toggle-book-properties": "切换书籍属性",
|
||||
"toggle-classic-editor-toolbar": "切换具有固定工具栏的编辑器格式化选项卡"
|
||||
},
|
||||
"login": {
|
||||
"title": "登录",
|
||||
@ -157,5 +158,40 @@
|
||||
"clipped-from": "此笔记最初剪切自 {{- url}}",
|
||||
"child-notes": "子笔记:",
|
||||
"no-content": "此笔记没有内容。"
|
||||
},
|
||||
"weekdays": {
|
||||
"monday": "周一",
|
||||
"tuesday": "周二",
|
||||
"wednesday": "周三",
|
||||
"thursday": "周四",
|
||||
"friday": "周五",
|
||||
"saturday": "周六",
|
||||
"sunday": "周日"
|
||||
},
|
||||
"months": {
|
||||
"january": "一月",
|
||||
"february": "二月",
|
||||
"march": "三月",
|
||||
"april": "四月",
|
||||
"may": "五月",
|
||||
"june": "六月",
|
||||
"july": "七月",
|
||||
"august": "八月",
|
||||
"september": "九月",
|
||||
"october": "十月",
|
||||
"november": "十一月",
|
||||
"december": "十二月"
|
||||
},
|
||||
"special_notes": {
|
||||
"search_prefix": "搜索:"
|
||||
},
|
||||
"code_block": {
|
||||
"theme_none": "无语法高亮",
|
||||
"theme_group_light": "浅色主题",
|
||||
"theme_group_dark": "深色主题"
|
||||
},
|
||||
"test_sync": {
|
||||
"not-configured": "同步服务器主机未配置。请先配置同步。",
|
||||
"successful": "同步服务器握手成功,同步已开始。"
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user