Compare commits
5 Commits
gen-packag
...
sidebar_pl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
af36737d72 | ||
|
|
2cf8b99adc | ||
|
|
70134ce077 | ||
|
|
2586cd8287 | ||
|
|
18bc9133eb |
@@ -718,9 +718,6 @@ packages/app-desktop/gui/style/StyledTextInput.js.map
|
||||
packages/app-desktop/gui/utils/NoteListUtils.d.ts
|
||||
packages/app-desktop/gui/utils/NoteListUtils.js
|
||||
packages/app-desktop/gui/utils/NoteListUtils.js.map
|
||||
packages/app-desktop/gui/utils/convertToScreenCoordinates.d.ts
|
||||
packages/app-desktop/gui/utils/convertToScreenCoordinates.js
|
||||
packages/app-desktop/gui/utils/convertToScreenCoordinates.js.map
|
||||
packages/app-desktop/plugins/GotoAnything.d.ts
|
||||
packages/app-desktop/plugins/GotoAnything.js
|
||||
packages/app-desktop/plugins/GotoAnything.js.map
|
||||
|
||||
3
.gitignore
vendored
@@ -707,9 +707,6 @@ packages/app-desktop/gui/style/StyledTextInput.js.map
|
||||
packages/app-desktop/gui/utils/NoteListUtils.d.ts
|
||||
packages/app-desktop/gui/utils/NoteListUtils.js
|
||||
packages/app-desktop/gui/utils/NoteListUtils.js.map
|
||||
packages/app-desktop/gui/utils/convertToScreenCoordinates.d.ts
|
||||
packages/app-desktop/gui/utils/convertToScreenCoordinates.js
|
||||
packages/app-desktop/gui/utils/convertToScreenCoordinates.js.map
|
||||
packages/app-desktop/plugins/GotoAnything.d.ts
|
||||
packages/app-desktop/plugins/GotoAnything.js
|
||||
packages/app-desktop/plugins/GotoAnything.js.map
|
||||
|
||||
|
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 134 KiB After Width: | Height: | Size: 71 KiB |
@@ -164,12 +164,18 @@ DESKTOP=${DESKTOP,,} # convert to lower case
|
||||
echo 'Create Desktop icon...'
|
||||
if [[ $DESKTOP =~ .*gnome.*|.*kde.*|.*xfce.*|.*mate.*|.*lxqt.*|.*unity.*|.*x-cinnamon.*|.*deepin.*|.*pantheon.*|.*lxde.*|.*i3.* ]]
|
||||
then
|
||||
: "${TMPDIR:=$TEMP_DIR}"
|
||||
# This command extracts to squashfs-root by default and can't be changed...
|
||||
# So we run it in the tmp directory and clean up after ourselves
|
||||
(cd $TMPDIR && ~/.joplin/Joplin.AppImage --appimage-extract joplin.desktop &> /dev/null)
|
||||
APPIMAGE_VERSION=$(grep "^X-AppImage-Version=" $TMPDIR/squashfs-root/joplin.desktop | head -n 1 | cut -d "=" -f 2)
|
||||
rm -rf $TMPDIR/squashfs-root
|
||||
# Only delete the desktop file if it will be replaced
|
||||
rm -f ~/.local/share/applications/appimagekit-joplin.desktop
|
||||
|
||||
# On some systems this directory doesn't exist by default
|
||||
mkdir -p ~/.local/share/applications
|
||||
echo -e "[Desktop Entry]\nEncoding=UTF-8\nName=Joplin\nComment=Joplin for Desktop\nExec=${HOME}/.joplin/Joplin.AppImage\nIcon=joplin\nStartupWMClass=Joplin\nType=Application\nCategories=Office;" >> ~/.local/share/applications/appimagekit-joplin.desktop
|
||||
echo -e "[Desktop Entry]\nEncoding=UTF-8\nName=Joplin\nComment=Joplin for Desktop\nExec=${HOME}/.joplin/Joplin.AppImage\nIcon=joplin\nStartupWMClass=Joplin\nType=Application\nCategories=Office;\n#${APPIMAGE_VERSION}" >> ~/.local/share/applications/appimagekit-joplin.desktop
|
||||
# Update application icons
|
||||
[[ `command -v update-desktop-database` ]] && update-desktop-database ~/.local/share/applications && update-desktop-database ~/.local/share/icons
|
||||
print "${COLOR_GREEN}OK${COLOR_RESET}"
|
||||
|
||||
10
gulpfile.js
@@ -8,11 +8,11 @@ const tasks = {
|
||||
// deleteBuildDirs: require('./packages/tools/gulp/tasks/deleteBuildDirs'),
|
||||
completePublishAll: {
|
||||
fn: async () => {
|
||||
// await utils.execCommandVerbose('git pull');
|
||||
await utils.execCommandVerbose('git', ['add', '-A']);
|
||||
await utils.execCommandVerbose('git', ['commit', '-m', 'Releasing sub-packages']);
|
||||
await utils.execCommandVerbose('lerna', ['publish', 'from-package', '-y']);
|
||||
await utils.execCommandVerbose('git', ['push']);
|
||||
await utils.execCommandVerbose('git pull');
|
||||
await utils.execCommandVerbose('git add -A');
|
||||
await utils.execCommandVerbose('git commit -m "Releasing sub-packages"');
|
||||
await utils.execCommandVerbose('lerna publish from-package -y');
|
||||
await utils.execCommandVerbose('git push');
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"linter-precommit": "./node_modules/.bin/eslint --resolve-plugins-relative-to . --fix --ext .js --ext .jsx --ext .ts --ext .tsx",
|
||||
"linter": "./node_modules/.bin/eslint --resolve-plugins-relative-to . --fix --quiet --ext .js --ext .jsx --ext .ts --ext .tsx",
|
||||
"postinstall": "lerna bootstrap --no-ci && npm run tsc",
|
||||
"publishAll": "git pull && lerna version --yes --no-private --no-git-tag-version && gulp completePublishAll",
|
||||
"publishAll": "git pull && lerna version --no-git-tag-version && gulp completePublishAll",
|
||||
"releaseAndroid": "node packages/tools/release-android.js",
|
||||
"releaseCli": "node packages/tools/release-cli.js",
|
||||
"releaseClipper": "node packages/tools/release-clipper.js",
|
||||
|
||||
@@ -55,7 +55,7 @@ class Command extends BaseCommand {
|
||||
};
|
||||
|
||||
importOptions.onError = error => {
|
||||
const s = error.stack ? error.stack : error.toString();
|
||||
const s = error.trace ? error.trace : error.toString();
|
||||
this.stdout(s);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
const gulp = require('gulp');
|
||||
const fs = require('fs-extra');
|
||||
const utils = require('@joplin/tools/gulp/utils');
|
||||
const { setPackagePrivateField } = require('@joplin/tools/tool-utils');
|
||||
const tasks = {
|
||||
// compileExtensions: {
|
||||
// fn: require('../Tools/gulp/tasks/compileExtensions.js'),
|
||||
@@ -11,12 +10,12 @@ const tasks = {
|
||||
// updateIgnoredTypeScriptBuild: require('../Tools/gulp/tasks/updateIgnoredTypeScriptBuild'),
|
||||
};
|
||||
|
||||
// async function makePackagePublic(filePath) {
|
||||
// const text = await fs.readFile(filePath, 'utf8');
|
||||
// const obj = JSON.parse(text);
|
||||
// delete obj.private;
|
||||
// await fs.writeFile(filePath, JSON.stringify(obj), 'utf8');
|
||||
// }
|
||||
async function makePackagePublic(filePath) {
|
||||
const text = await fs.readFile(filePath, 'utf8');
|
||||
const obj = JSON.parse(text);
|
||||
delete obj.private;
|
||||
await fs.writeFile(filePath, JSON.stringify(obj), 'utf8');
|
||||
}
|
||||
|
||||
tasks.prepareBuild = {
|
||||
fn: async () => {
|
||||
@@ -26,8 +25,7 @@ tasks.prepareBuild = {
|
||||
});
|
||||
|
||||
await utils.copyFile(`${__dirname}/package.json`, `${buildDir}/package.json`);
|
||||
// await makePackagePublic(`${buildDir}/package.json`);
|
||||
await setPackagePrivateField(`${buildDir}/package.json`, false);
|
||||
await makePackagePublic(`${buildDir}/package.json`);
|
||||
|
||||
await utils.copyFile(`${__dirname}/package-lock.json`, `${buildDir}/package-lock.json`);
|
||||
await utils.copyFile(`${__dirname}/gulpfile.js`, `${buildDir}/gulpfile.js`);
|
||||
|
||||
2
packages/app-cli/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "joplin",
|
||||
"version": "1.5.1",
|
||||
"version": "1.4.7",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
],
|
||||
"owner": "Laurent Cozic"
|
||||
},
|
||||
"version": "1.5.1",
|
||||
"version": "1.5.0",
|
||||
"bin": {
|
||||
"joplin": "./main.js"
|
||||
},
|
||||
|
||||
@@ -44,18 +44,14 @@ describe('EnexToMd', function() {
|
||||
}
|
||||
|
||||
if (actualMd !== expectedMd) {
|
||||
const result = [];
|
||||
|
||||
result.push('');
|
||||
result.push(`Error converting file: ${htmlFilename}`);
|
||||
result.push('--------------------------------- Got:');
|
||||
result.push(actualMd.split('\n').map((l: string) => `"${l}"`).join('\n'));
|
||||
result.push('--------------------------------- Expected:');
|
||||
result.push(expectedMd.split('\n').map((l: string) => `"${l}"`).join('\n'));
|
||||
result.push('--------------------------------------------');
|
||||
result.push('');
|
||||
|
||||
console.info(result.join('\n'));
|
||||
console.info('');
|
||||
console.info(`Error converting file: ${htmlFilename}`);
|
||||
console.info('--------------------------------- Got:');
|
||||
console.info(actualMd.split('\n'));
|
||||
console.info('--------------------------------- Expected:');
|
||||
console.info(expectedMd.split('\n'));
|
||||
console.info('--------------------------------------------');
|
||||
console.info('');
|
||||
|
||||
expect(false).toBe(true);
|
||||
// return;
|
||||
@@ -117,33 +113,4 @@ describe('EnexToMd', function() {
|
||||
expect(all[0].body).toBe('');
|
||||
});
|
||||
|
||||
it('should handle invalid mime types', async () => {
|
||||
// This is to handle the case where a resource has an invalid mime type,
|
||||
// but that type can be determined from the filename. For example, in
|
||||
// this thread, the ENEX file contains a "file.zip" file with a mime
|
||||
// type "application/octet-stream", which can later cause problems to
|
||||
// open the file.
|
||||
// https://discourse.joplinapp.org/t/importing-a-note-with-a-zip-file/12123?u=laurent
|
||||
const filePath = `${enexSampleBaseDir}/WithInvalidMime.enex`;
|
||||
await importEnex('', filePath);
|
||||
const all = await Resource.all();
|
||||
expect(all.length).toBe(1);
|
||||
expect(all[0].mime).toBe('application/zip');
|
||||
});
|
||||
|
||||
it('should keep importing notes when one of them is corrupted', async () => {
|
||||
const filePath = `${enexSampleBaseDir}/ImportTestCorrupt.enex`;
|
||||
const errors: any[] = [];
|
||||
await importEnex('', filePath, {
|
||||
onError: (error: any) => errors.push(error),
|
||||
});
|
||||
const notes = await Note.all();
|
||||
expect(notes.length).toBe(2);
|
||||
|
||||
// Check that an error was recorded and that it includes the title
|
||||
// of the note, so that it can be found back by the user
|
||||
expect(errors.length).toBe(1);
|
||||
expect(errors[0].message.includes('Note 2')).toBe(true);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE en-export SYSTEM "http://xml.evernote.com/pub/evernote-export2.dtd">
|
||||
<en-export export-date="20201223T164244Z" application="Evernote/Windows" version="6.x">
|
||||
<note><title>Note 1</title><content><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd">
|
||||
|
||||
<en-note><div>Plain note</div></en-note>]]></content><created>20201223T163948Z</created><updated>20201223T163953Z</updated><note-attributes><author>laurent22777@gmail.com</author><source>desktop.win</source><source-application>evernote.win32</source-application></note-attributes></note><note><title>Note 2</title><content><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd">
|
||||
|
||||
<en-note><div><div><br/></div><table style="border-collapse: collapse; min-width: 100%;"><colgroup><col style="width: 130px;"/><col style="width: 130px;"/><col style="width: 130px;"/></colgroup><tbody><tr<td style="width: 130px; padding: 8px; border: 1px solid;"><div>test</div></td><td style="width: 130px; padding: 8px; border: 1px solid;"><div>test</div></td><td style="width: 130px; padding: 8px; border: 1px solid;"><div><br/></div></td></tr><tr><td style="width: 130px; padding: 8px; border: 1px solid;"><div>bl</div></td><td style="width: 130px; padding: 8px; border: 1px solid;"><div>bla</div></td><td style="width: 130px; padding: 8px; border: 1px solid;"><div>bla</div></td></tr></tbody></table><div><br/></div></div><div><br/></div></en-note>]]></content><created>20201223T164010Z</created><updated>20201223T164023Z</updated><note-attributes><author>laurent22777@gmail.com</author><source>desktop.win</source><source-application>evernote.win32</source-application></note-attributes></note><note><title>plain note 2</title><content><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd">
|
||||
|
||||
<en-note><div><br/></div></en-note>]]></content><created>20201223T164236Z</created><note-attributes><author>laurent22777@gmail.com</author><source>desktop.win</source><source-application>evernote.win32</source-application></note-attributes></note></en-export>
|
||||
@@ -1,53 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE en-export SYSTEM "http://xml.evernote.com/pub/evernote-export3.dtd">
|
||||
<en-export export-date="20201218T233722Z" application="Evernote" version="Evernote Mac 7.13 (458080)">
|
||||
<note><title>WithInvalidMime</title><content><![CDATA[<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd"><en-note><div><en-media hash="d502aa19556b5b4b4dcceaf0514ad206" type="application/zip" style="cursor:pointer;" /></div><div><br /></div></en-note>]]></content><created>20201218T233549Z</created><updated>20201218T233706Z</updated><note-attributes><latitude>51.57516479492188</latitude><longitude>0.2281720315013734</longitude><altitude>29.71427536010742</altitude><author>laurent@cozic.net</author><source>desktop.mac</source><reminder-order>0</reminder-order></note-attributes><resource><data encoding="base64">UEsDBBQACAAIAJlyelEAAAAAAAAAAKAKAAAJACAAcGhvdG8uanBnVVQNAAfDub9fz7m/X8O5v191eAsA
|
||||
AQT1AQAABBQAAACVjnk8048fxz+zMcccy1VjyFyVxdjmyK2cHYxo1BdF5T42N98I+4amHLnv23Knwrcc
|
||||
OXOUuRrDNH2NQtGlUvv59cfv8fv9+Xu9/3y+3s/Hi8vgLgNiNhbWFgAIBAKs9g/gMgFzQIAPyg/lE+CH
|
||||
8gsKCggJS4kKw2DCMhKSYlIKSEVFBaS8vJIaVl1JBaMqL482RGNwOvr6+qhjxieNdc2xevo6/5aABAUF
|
||||
hWHCCFFRhI6yvLLO/x1uDwDnB0KAaDBIEeCBg8BwELcfkAUAALo/9r8C4gFDePcX79MTYgAIzAOBgHl5
|
||||
oby/SyBgn8J5DxzG8Imb2it6xEtoBafToSizshZJJcLlzN4P2tiQhIzt/eeDIAD8v+bf6n0iBwf9zr7r
|
||||
PwTOcxgDNj2gZcadB2DgfQQHwwFj4FV62FsbvzblhHLcyJIAtWt9jZHRgyWUgU/GMw6VtgtWHGLDJapz
|
||||
RN1jKixHfSklh2fO9dOQkifKE9OPzZsoRFd0vqC/1vNUdBfSaZ9c71XsanXJG+YYWRoUgKMXzbosQSgT
|
||||
1GWLd14bYrquxwn6acmZSQ47O6tjppMcT5+8KydS+dPwbcxoZXv2Q/JZv7YpIPC+7amiN6aTo6dUBGSW
|
||||
FfFC1D1bTKrDD1gjtbMttV30WeHRtSeYOxMrwfxXKfz3TWYNbr5EMm/Q3RAX0JXwG8ux0kJe5mtVB5qf
|
||||
Nnm/eM6XT613vrTcqBAo9lr2uawhDepZVNFt/tbYrO7etp/aMv6JWMn3Z84tBKow1ngqkG7Fvxl091Ss
|
||||
pMolb28uUMkq95ugs34WGX+S+eRga+FIDGys4zvaCwmjqwGZJlcCsATFoOvKg7MC1dUYvUSsxnU8uZjv
|
||||
e6WY4cOdF+sBfh9Ld9Yqoe1t99yEzsQreU9L6mtNXX3PmcMJz4RBSXSLA1dJD43zo6yYW0XnPEuuXQHQ
|
||||
eFRQXJhAIRt0FxuKnJEWs0RVpM8l4/VIciVzxOEQcHTC5Lzbau320VfP86ionIbxr1K7Emb1hQ9SQxJ+
|
||||
TgTO9K/vuIg+iPGaNnC2FciemBU53dDRorrIqsV/qx+/0Ja0nOOyDE113ZtDCeekJ9u/6Au3PCELYpkJ
|
||||
sgw8/ihobrWzRj67MOd1VmBpa75CHiJLtuk0TYKeychnlg8T8qf8P1uXnRYyHgz8ElH3Vs5tFNJMcSNx
|
||||
gYGyK8JfHWOIeWM1iUhrDeYjFs1hfeCEO42CnyF8hGl8vRSzqUq37n9XXVORYlqjNZ+WpJhG7PCrjkkz
|
||||
1Gq7AFqrvBJksYuijKPBizsbefdrfTjZJiO3nXbguXjdXkiMdWsu5g/7oNVHf65gRORKTmbTp0YB2Wbw
|
||||
MCnubpyVlEykjKuvpDS8L03ZDWlb4XXcKW7J3Nyi6BxptSRpw+Zn9QjD+naqeG33qfxBn0StEwZek7q7
|
||||
IU/8G94Hlv8dKkF+c7BqbLOQ7X8DV8w+jM0cZPRtbVLvkfIvBRyprtcIsMggds125vVlsR7qFojWjGad
|
||||
ITApn6Q79jIlTlelhAtm65dbFOCFsnFDY9RYqR8bjwUPphkFZ3uwM/KzdXAdAmjyX6Z+82sC3eWTC57v
|
||||
eliOpbdwakKS6QJ9J809W4+r23vtKlVrQkrh8aU24PO4K9eJXepKTlMiFK3wjy5XqVjiknZiM2E6zkra
|
||||
43Fxt6N5iSOdrWk/suQ9gn6PhI7r2Ke91tay89HLwFViH9ZoDK5LbHqmkSofcIGcmdPYLK+8xGCGy4Zw
|
||||
a5Mk+Ze4nXKZh+LA5hj2jOP0/PebfK8NVNO0eoNmN4CtWkzKqsWZBQ3Sx5NfqMNhUdXi7qFSdLPiljQR
|
||||
UvKHUB4uUF6Na33C4Z0F2xUW22PxvoWD6SuozqndB0+9yY7jsbZHF9XPZuYKXfbaigIxNEyCVqXG5Pmq
|
||||
yryaxA08ha5Gzgyt2rBvXMuCHliBGd5TGh4uXC8qcM0WuvNitLvNlUxO0YQXKJpa8yDCTQ+AFfA27iY6
|
||||
no+oTv5C7msVK2QjVtLLsz16SR15N9iIpKOalS21Oip9ZQnvXc+jVu5t6XMUF9Fvclwppujk/ipQgnnY
|
||||
Fo4L8Py9EiOZNWPWrInwfpnaV+H2iuO7N+tj5S1z6I3uW+H5U0P57U0T+t4IiNHEVZjRtlT3t/Ka/hq/
|
||||
DLgHY0H55Ui17841jbD+9PKGaKWs9oW7OJZXzGBYBufgXBB2QW5YK2SvIZrayQjcJqhpzo+52AtDRLI2
|
||||
3B5Y9m88jsH1fmJEMw2vS+LQCqlrg/LHOWNz59+aFc6X9DT/2VNaINMYd3PVW86+qIU63in3aEP6bFXx
|
||||
UVoEJ34zhoDVa/RuV2iMHGBURlwTnS5IUN/AWCAbRpPu/BPSKis8FGpgqH3kmAYewYnI2y3/GEg/mf1d
|
||||
P/e9WlaU4LyfRcbRziN5OIOGv+X6ygiWvUq3UOae4rD7LuJUHxVqRi/dy0U44fyR7NYGWr/aWq6bs4ME
|
||||
GrG7BH3TKmv+JRmGJh9UWx0maz+5oLOs/52WaW45dHCcTz5+upcw6HhGW+sRmLN7x13nE9FAm3Lk3Yd8
|
||||
n0ylem0zWZMWSMmpv/pbECNNT2h5k7YqSVsLSXMRuPRuvmdMj7Cp5pJjvE5ESL3Bgnxyq7NWRN1KANty
|
||||
ZNNyz//n9IgRvFpEtOnujFQJzKvj0PaIzmdl8hhBRV9zB4RmnrpXf7hGL/bzBNkhisY5EncIrGf3GMVH
|
||||
vcKbT1+7fT6bGrJQvJgVM1dsW/QG97i8gr1hy1iHYQps1dAQGeJTQqZPU3oBe8+b8TDC89rXCJCverih
|
||||
TRnJn64LvfX5HRlJW89U0XzsfBE9wKiBPf9RGP9pK5QF/uzb9dd4+HFpdoxx8hG96cDRY8Bqzwr7NhcI
|
||||
Xn2ydFHdvzsUJThwTDNl1snjsyglDCm7VNGCtMxwLlKts7vIoXRNf5gfZorgovSpUCw2d3FnOmrvlenN
|
||||
6zRFv4mRV4PbYR2N7YdNO16Kb1/C84rYZ/sMiUKcmWPf1GUX/KkzmWM0scFzHWAweTOWC+DyamvzGyNV
|
||||
iy2NrJHhekMEe4rQ9XfFz18oIdIdTqwWW3ZZWnG2vm4VUBO7VjCBtBDNSea1CFVfSRU1xFmnri/T6VVT
|
||||
CxgC3VhsoG4tl0yiBORZ/BNuIKdbAIOblt5Ri/2BvW5s1qEK7lXKrTpve6bDDy1taM18I03sRZGDMzji
|
||||
QTjDl7tSsaxgQmTNfZVojMyocunznEVm01uabymZsv1AO0rXN6iG/UpkkqMJ4akLuQj1nGUpC60i7tek
|
||||
pEifM6hvDrh8kITke7xm5JuzciFhG/FNNehw4q4MA31N1jk/6upk/zJScztSp7Vn6adTd9qf9MWfch36
|
||||
fgWRa/CW+bWEQpHEvezbY64DNEjpBzseZjXwvjxjpJOCxWVaIfCHUtwhxJsmOQHZeDWFOIeLAaFG62+r
|
||||
+q2eJsv8ioccqJFegH3lcyQOEaFuyvQPdav/GL/3ZO3e8RQjhv7M+WXW5W17bql70fjWF7tR1o3IxajS
|
||||
m/fOpZEG04L7PwcbwTt+2T1YIYu5krZL3M7iFH4MsW8KZthygWljiUt3TQH5TlQnv4o8d+5fUEsHCAlM
|
||||
JEl7CgAAoAoAAFBLAQIUAxQACAAIAJlyelEJTCRJewoAAKAKAAAJACAAAAAAAAAAAACkgQAAAABwaG90
|
||||
by5qcGdVVA0AB8O5v1/Pub9fw7m/X3V4CwABBPUBAAAEFAAAAFBLBQYAAAAAAQABAFcAAADSCgAAAAA=
|
||||
</data><mime>application/octet-stream</mime><width>0</width><height>0</height><duration>0</duration><resource-attributes><timestamp>19700101T000000Z</timestamp><file-name>photo.zip</file-name></resource-attributes></resource></note>
|
||||
</en-export>
|
||||
@@ -1,2 +0,0 @@
|
||||
<pre style="font-family: monospace;"><code><div>jq -r <span>'.[]|[.index, .name, .section, .award, .industry]|join("\t")'</span> raw.json |pbcopy
|
||||
</div></code></pre>
|
||||
@@ -1 +0,0 @@
|
||||
jq -r '.[]|[.index, .name, .section, .award, .industry]|join("\t")' raw.json |pbcopy
|
||||
@@ -1,3 +0,0 @@
|
||||
<p>This is visible<br/>This too
|
||||
<div style='display:none !important;visibility:collapse !important;height:0 !important;white-space:nowrap;width:100%;overflow:hidden'>This is hidden <div>and this sub-tag <strong>too</strong></div></div>
|
||||
This is visible again</p>
|
||||
@@ -1,4 +0,0 @@
|
||||
This is visible
|
||||
This too<div style="display: none;">This is hidden
|
||||
and this sub-tag **too**
|
||||
</div>This is visible again
|
||||
@@ -1,21 +0,0 @@
|
||||
<p>Check that a hidden table within a hidden block results in a hidden block with a table inside.</p>
|
||||
<div style="background-color:none;width:0;max-height:0;visibility:collapse;overflow:hidden;float:left;display:none;font-size:0;line-height:0;">
|
||||
<table border="0" cellspacing="0" cellpadding="0" style="font-family:Helvetica,Arial,sans-serif; background-color: none; width: 0; max-height: 0; visibility: collapse; overflow: hidden; float: left; display: none; font-size:0; line-height:0; mso-hide:all" width="100%">
|
||||
<tr>
|
||||
<td colspan="1" rowspan="1">
|
||||
<table width="1" border="0" cellspacing="0" cellpadding="1">
|
||||
<tr>
|
||||
<td colspan="1" rowspan="1">
|
||||
<div style="height:5px;font-size:5px;line-height:5px"> </div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="1" rowspan="1">
|
||||
<a shape="rect" href="http://www.linkedin.com/e/v2?e=1506x2-huob5maa-42&t=nmp&midToken=AQFSKz2SrPsC9Q&tracking=eml-comm_nu_digest-see_all_updates&ek=nu_digest" style="border:none;outline:none;text-decoration:none;color:#0077B5;">See all updates <en-media width="4" height="8" style="border: none; outline: none; text-decoration: none; height: auto;" type="image/png" hash="de3a477878915a74f7bf042345acec5c"/></a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
@@ -1,11 +0,0 @@
|
||||
Check that a hidden table within a hidden block results in a hidden block with a table inside.
|
||||
|
||||
<div style="display: none;">
|
||||
|
||||
| |
|
||||
| --- |
|
||||
| |
|
||||
|
||||
[See all updates](http://www.linkedin.com/e/v2?e=1506x2-huob5maa-42&t=nmp&midToken=AQFSKz2SrPsC9Q&tracking=eml-comm_nu_digest-see_all_updates&ek=nu_digest)
|
||||
|
||||
</div>
|
||||
@@ -1,11 +0,0 @@
|
||||
<table>
|
||||
<caption><en-media alt="Video recordings download options" width="20" height="20" style="border:0px;margin:0px;padding:0px;-webkit-text-size-adjust:none;vertical-align:text-bottom;max-width:100%;height:auto;margin-right:5px;" hash="50b609a6abfeddd7005382bdcc6120f4" type="image/png"></en-media>MP4</caption>
|
||||
<tr>
|
||||
<th>Video Segments</th>
|
||||
<th>Download</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>one</td>
|
||||
<td>two</td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -1,5 +0,0 @@
|
||||
| Video Segments | Download |
|
||||
| --- | --- |
|
||||
| one | two |
|
||||
|
||||
MP4
|
||||
@@ -152,7 +152,7 @@ describe('services_KeymapService', () => {
|
||||
{ command: 'newNote', accelerator: 'Ctrl+Alt+Shift+N' },
|
||||
{ command: 'synchronize', accelerator: 'F15' },
|
||||
{ command: 'textBold', accelerator: 'Shift+F5' },
|
||||
{ command: 'showLocalSearch', accelerator: 'Ctrl+Alt+L' },
|
||||
{ command: 'showLocalSearch', accelerator: 'Ctrl+Alt+S' },
|
||||
{ command: 'gotoAnything', accelerator: 'Ctrl+Shift+G' },
|
||||
{ command: 'print', accelerator: null /* Disabled */ },
|
||||
{ command: 'focusElementNoteTitle', accelerator: 'Ctrl+Alt+Shift+T' },
|
||||
@@ -174,7 +174,7 @@ describe('services_KeymapService', () => {
|
||||
{ command: 'newNote', accelerator: 'Ctrl+Alt+Shift+N' },
|
||||
{ command: 'synchronize', accelerator: null /* Disabled */ },
|
||||
{ command: 'textBold', accelerator: 'Shift+F5' },
|
||||
{ command: 'showLocalSearch', accelerator: 'Ctrl+Alt+L' },
|
||||
{ command: 'showLocalSearch', accelerator: 'Ctrl+Alt+S' },
|
||||
{ command: 'gotoAnything', accelerator: 'Ctrl+Shift+G' },
|
||||
{ command: 'print', accelerator: 'Alt+P' },
|
||||
{ command: 'focusElementNoteTitle', accelerator: 'Ctrl+Alt+Shift+T' },
|
||||
@@ -222,7 +222,7 @@ describe('services_KeymapService', () => {
|
||||
{ command: 'newNote', accelerator: 'Ctrl+Alt+Shift+N' },
|
||||
{ command: 'synchronize', accelerator: 'Ctrl+F11' },
|
||||
{ command: 'textBold', accelerator: 'Shift+F5' },
|
||||
{ command: 'showLocalSearch', accelerator: 'Ctrl+Alt+L' },
|
||||
{ command: 'showLocalSearch', accelerator: 'Ctrl+Alt+S' },
|
||||
{ command: 'gotoAnything', accelerator: 'Ctrl+Shift+G' },
|
||||
{ command: 'print', accelerator: 'Alt+P' },
|
||||
{ command: 'help', accelerator: null /* Disabled */ },
|
||||
@@ -243,7 +243,7 @@ describe('services_KeymapService', () => {
|
||||
const customKeymaps = [
|
||||
[
|
||||
{ commmmmand: 'gotoAnything', accelerator: 'Ctrl+Shift+G' },
|
||||
{ command: 'showLocalSearch', accelerator: 'Ctrl+Alt+L' },
|
||||
{ command: 'showLocalSearch', accelerator: 'Ctrl+Alt+S' },
|
||||
{ command: 'print', accelerator: 'Alt+P' },
|
||||
],
|
||||
[
|
||||
@@ -252,13 +252,13 @@ describe('services_KeymapService', () => {
|
||||
{ command: 'gotoAnything', accelerator: 'Ctrl+Shift+G' },
|
||||
],
|
||||
[
|
||||
{ command: 'showLocalSearch', accel: 'Ctrl+Alt+L' },
|
||||
{ command: 'showLocalSearch', accel: 'Ctrl+Alt+S' },
|
||||
{ command: 'print', accelerator: 'Alt+P' },
|
||||
{ command: 'gotoAnything', accelerator: 'Ctrl+Shift+G' },
|
||||
],
|
||||
[
|
||||
{ command: 'print' },
|
||||
{ command: 'showLocalSearch', accelerator: 'Ctrl+Alt+L' },
|
||||
{ command: 'showLocalSearch', accelerator: 'Ctrl+Alt+S' },
|
||||
{ command: 'gotoAnything', accelerator: 'Ctrl+Shift+G' },
|
||||
],
|
||||
];
|
||||
@@ -311,12 +311,12 @@ describe('services_KeymapService', () => {
|
||||
|
||||
const customKeymaps_Linux = [
|
||||
[
|
||||
{ command: 'showLocalSearch', accelerator: 'Ctrl+Alt+L' /* Duplicate */ },
|
||||
{ command: 'showLocalSearch', accelerator: 'Ctrl+Alt+S' /* Duplicate */ },
|
||||
{ command: 'print', accelerator: 'Alt+P' },
|
||||
{ command: 'gotoAnything', accelerator: 'Ctrl+Alt+L' /* Duplicate */ },
|
||||
{ command: 'gotoAnything', accelerator: 'Ctrl+Alt+S' /* Duplicate */ },
|
||||
],
|
||||
[
|
||||
{ command: 'showLocalSearch', accelerator: 'Ctrl+Alt+L' },
|
||||
{ command: 'showLocalSearch', accelerator: 'Ctrl+Alt+S' },
|
||||
{ command: 'print', accelerator: 'Ctrl+P' /* Default of gotoAnything */ },
|
||||
{ command: 'focusElementNoteTitle', accelerator: 'Ctrl+Alt+Shift+J' },
|
||||
],
|
||||
|
||||
@@ -219,7 +219,7 @@ describe('services_PluginService', function() {
|
||||
const assetContent: string = await shim.fsDriver().readFile(asset.path, 'utf8');
|
||||
|
||||
expect(assetContent.includes('.just-testing')).toBe(true);
|
||||
expect(assetContent.includes('background-color: rgb(202, 255, 255)')).toBe(true);
|
||||
expect(assetContent.includes('background-color: red;')).toBe(true);
|
||||
expect(result.html.includes('JUST TESTING: something')).toBe(true);
|
||||
|
||||
await shim.fsDriver().remove(tempDir);
|
||||
|
||||
@@ -4,11 +4,12 @@
|
||||
function plugin(CodeMirror) {
|
||||
// This is a dummy command that is registered with codemirror.
|
||||
// Once created here it can be called by any other codemirror command
|
||||
// using cm.execCommand(stringName) or register a joplin command called 'editor.printSomething'
|
||||
// through the joplin.commands api
|
||||
// using cm.execCommand(stringName) or by binding the command to a key in the keymap
|
||||
CodeMirror.commands.printSomething = function(cm) {
|
||||
console.log("Something");
|
||||
}
|
||||
// Here we manually bind the keys using the codemirror keymap
|
||||
CodeMirror.keyMap.basic["Ctrl-U"] = "printSomething"
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -20,4 +20,4 @@
|
||||
"webpack": "^4.43.0",
|
||||
"webpack-cli": "^3.3.11"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -36,18 +36,10 @@ joplin.plugins.register({
|
||||
});
|
||||
|
||||
await joplin.commands.register({
|
||||
name: 'folderContextMenuExample',
|
||||
label: 'Folder menu item from plugin',
|
||||
execute: async (folderId:string) => {
|
||||
console.info('Click on folder: ' + folderId);
|
||||
},
|
||||
});
|
||||
|
||||
await joplin.commands.register({
|
||||
name: 'tagContextMenuExample',
|
||||
label: 'Tag menu item from plugin',
|
||||
execute: async (tagId:string) => {
|
||||
console.info('Click on tag: ' + tagId);
|
||||
name: 'sideBarContextMenuExample',
|
||||
label: 'Menu item from plugin',
|
||||
execute: async (itemType:number, itemId:string) => {
|
||||
console.info('Click on item: ' + JSON.stringify({ itemType, itemId }));
|
||||
},
|
||||
});
|
||||
|
||||
@@ -72,8 +64,7 @@ joplin.plugins.register({
|
||||
|
||||
await joplin.views.menuItems.create('contextMenuItem1', 'contextMenuCommandExample', MenuItemLocation.NoteListContextMenu);
|
||||
|
||||
await joplin.views.menuItems.create('folderMenuItem1', 'folderContextMenuExample', MenuItemLocation.FolderContextMenu);
|
||||
await joplin.views.menuItems.create('tagMenuItem1', 'tagContextMenuExample', MenuItemLocation.TagContextMenu);
|
||||
await joplin.views.menuItems.create('sideBarMenuItem1', 'sideBarContextMenuExample', MenuItemLocation.SideBarContextMenu);
|
||||
|
||||
console.info('Running command with arguments...');
|
||||
const result = await joplin.commands.execute('commandWithResult', 'abcd', 123);
|
||||
|
||||
@@ -55,7 +55,6 @@ const md5 = require('md5');
|
||||
const S3 = require('aws-sdk/clients/s3');
|
||||
const { Dirnames } = require('@joplin/lib/services/synchronizer/utils/types');
|
||||
const sharp = require('sharp');
|
||||
const { credentialFile } = require('@joplin/tools/tool-utils');
|
||||
|
||||
// Each suite has its own separate data and temp directory so that multiple
|
||||
// suites can be run at the same time. suiteName is what is used to
|
||||
@@ -192,7 +191,7 @@ function isNetworkSyncTarget() {
|
||||
function sleep(n: number) {
|
||||
return new Promise((resolve) => {
|
||||
shim.setTimeout(() => {
|
||||
resolve(null);
|
||||
resolve();
|
||||
}, Math.round(n * 1000));
|
||||
});
|
||||
}
|
||||
@@ -200,7 +199,7 @@ function sleep(n: number) {
|
||||
function msleep(ms: number) {
|
||||
return new Promise((resolve) => {
|
||||
shim.setTimeout(() => {
|
||||
resolve(null);
|
||||
resolve();
|
||||
}, ms);
|
||||
});
|
||||
}
|
||||
@@ -470,34 +469,18 @@ async function initFileApi() {
|
||||
fileApi = new FileApi('', new FileApiDriverDropbox(api));
|
||||
} else if (syncTargetId_ == SyncTargetRegistry.nameToId('onedrive')) {
|
||||
// To get a token, open the URL below, then copy the *complete*
|
||||
// redirection URL in onedrive-auth.txt. Keep in mind that auth
|
||||
// data only lasts 1h for OneDrive.
|
||||
//
|
||||
// redirection URL in onedrive-auth.txt. Keep in mind that auth data
|
||||
// only lasts 1h for OneDrive.
|
||||
// https://login.live.com/oauth20_authorize.srf?client_id=f1e68e1e-a729-4514-b041-4fdd5c7ac03a&scope=files.readwrite,offline_access&response_type=token&redirect_uri=https://joplinapp.org
|
||||
//
|
||||
// Also for now OneDrive tests cannot be run in parallel because
|
||||
// for that each suite would need its own sub-directory within the
|
||||
// OneDrive app directory, and it's not clear how to get that
|
||||
// working.
|
||||
|
||||
if (!process.argv.includes('--runInBand')) {
|
||||
throw new Error('OneDrive tests must be run sequentially, with the --runInBand arg. eg `npm test -- --runInBand`');
|
||||
|
||||
}
|
||||
|
||||
const { parameters, setEnvOverride } = require('@joplin/lib/parameters.js');
|
||||
Setting.setConstant('env', 'dev');
|
||||
setEnvOverride('test');
|
||||
const config = parameters().oneDriveTest;
|
||||
const api = new OneDriveApi(config.id, config.secret, false);
|
||||
const authData = fs.readFileSync(await credentialFile('onedrive-auth.txt'), 'utf8');
|
||||
const authData = fs.readFileSync(`${__dirname}/support/onedrive-auth.txt`, 'utf8');
|
||||
const urlInfo = require('url-parse')(authData, true);
|
||||
const auth = require('querystring').parse(urlInfo.hash.substr(1));
|
||||
api.setAuth(auth);
|
||||
|
||||
const accountProperties = await api.execAccountPropertiesRequest();
|
||||
api.setAccountProperties(accountProperties);
|
||||
|
||||
const appDir = await api.appDirectory();
|
||||
fileApi = new FileApi(appDir, new FileApiDriverOneDrive(api));
|
||||
} else if (syncTargetId_ == SyncTargetRegistry.nameToId('amazon_s3')) {
|
||||
@@ -789,7 +772,7 @@ class TestApp extends BaseApplication {
|
||||
const iid = shim.setInterval(() => {
|
||||
if (!this.middlewareCalls_.length) {
|
||||
clearInterval(iid);
|
||||
resolve(null);
|
||||
resolve();
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
|
||||
@@ -4,7 +4,6 @@ import shim from '@joplin/lib/shim';
|
||||
import { ExportOptions, FileSystemItem, Module } from '@joplin/lib/services/interop/types';
|
||||
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import { PluginStates } from '@joplin/lib/services/plugins/reducer';
|
||||
const bridge = require('electron').remote.require('./bridge').default;
|
||||
const Setting = require('@joplin/lib/models/Setting').default;
|
||||
const Note = require('@joplin/lib/models/Note.js');
|
||||
@@ -21,7 +20,6 @@ interface ExportNoteOptions {
|
||||
pageSize?: string;
|
||||
landscape?: boolean;
|
||||
includeConflicts?: boolean;
|
||||
plugins?: PluginStates;
|
||||
}
|
||||
|
||||
export default class InteropServiceHelper {
|
||||
@@ -56,7 +54,6 @@ export default class InteropServiceHelper {
|
||||
try {
|
||||
const exportOptions = {
|
||||
customCss: options.customCss ? options.customCss : '',
|
||||
plugins: options.plugins,
|
||||
};
|
||||
|
||||
htmlFile = await this.exportNoteToHtmlFile(noteId, exportOptions);
|
||||
@@ -165,7 +162,6 @@ export default class InteropServiceHelper {
|
||||
exportOptions.path = path;
|
||||
exportOptions.format = module.format;
|
||||
// exportOptions.modulePath = module.path;
|
||||
if (options.plugins) exportOptions.plugins = options.plugins;
|
||||
exportOptions.target = module.target;
|
||||
exportOptions.includeConflicts = !!options.includeConflicts;
|
||||
if (options.sourceFolderIds) exportOptions.sourceFolderIds = options.sourceFolderIds;
|
||||
|
||||
@@ -373,7 +373,6 @@ class MainScreenComponent extends React.Component<Props, State> {
|
||||
pageSize: Setting.value('export.pdfPageSize'),
|
||||
landscape: Setting.value('export.pdfPageOrientation') === 'landscape',
|
||||
customCss: this.props.customCss,
|
||||
plugins: this.props.plugins,
|
||||
});
|
||||
await shim.fsDriver().writeFile(options.path, pdfData, 'buffer');
|
||||
} catch (error) {
|
||||
|
||||
@@ -88,7 +88,6 @@ interface Props {
|
||||
pluginMenus: any[];
|
||||
['spellChecker.enabled']: boolean;
|
||||
['spellChecker.language']: string;
|
||||
plugins: PluginStates;
|
||||
}
|
||||
|
||||
const commandNames: string[] = menuCommandNames();
|
||||
@@ -137,8 +136,6 @@ function useMenu(props: Props) {
|
||||
|
||||
void CommandService.instance().execute('showModalMessage', modalMessage);
|
||||
|
||||
const errors: any[] = [];
|
||||
|
||||
const importOptions = {
|
||||
path,
|
||||
format: module.format,
|
||||
@@ -150,10 +147,7 @@ function useMenu(props: Props) {
|
||||
|
||||
void CommandService.instance().execute('showModalMessage', `${modalMessage}\n\n${statusStrings.join('\n')}`);
|
||||
},
|
||||
onError: (error: any) => {
|
||||
errors.push(error);
|
||||
console.warn(error);
|
||||
},
|
||||
onError: console.warn,
|
||||
destinationFolderId: !module.isNoteArchive && moduleSource === 'file' ? props.selectedFolderId : null,
|
||||
};
|
||||
|
||||
@@ -165,11 +159,6 @@ function useMenu(props: Props) {
|
||||
bridge().showErrorMessageBox(error.message);
|
||||
}
|
||||
|
||||
if (errors.length) {
|
||||
bridge().showErrorMessageBox('There was some errors importing the notes. Please check the console for more details.');
|
||||
props.dispatch({ type: 'NOTE_DEVTOOLS_SET', value: true });
|
||||
}
|
||||
|
||||
void CommandService.instance().execute('hideModalMessage');
|
||||
}, [props.selectedFolderId]);
|
||||
|
||||
@@ -244,11 +233,7 @@ function useMenu(props: Props) {
|
||||
exportItems.push({
|
||||
label: module.fullLabel(),
|
||||
click: async () => {
|
||||
await InteropServiceHelper.export(
|
||||
(action: any) => props.dispatch(action),
|
||||
module,
|
||||
{ plugins: props.plugins }
|
||||
);
|
||||
await InteropServiceHelper.export((action: any) => props.dispatch(action), module);
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -486,7 +471,7 @@ function useMenu(props: Props) {
|
||||
label: _('Import'),
|
||||
submenu: importItems,
|
||||
}, {
|
||||
label: _('Export all'),
|
||||
label: _('Export'),
|
||||
submenu: exportItems,
|
||||
}, {
|
||||
type: 'separator',
|
||||
@@ -519,9 +504,6 @@ function useMenu(props: Props) {
|
||||
menuItemDic.textPaste,
|
||||
menuItemDic.textSelectAll,
|
||||
separator(),
|
||||
menuItemDic['editor.undo'],
|
||||
menuItemDic['editor.redo'],
|
||||
separator(),
|
||||
menuItemDic.textBold,
|
||||
menuItemDic.textItalic,
|
||||
menuItemDic.textLink,
|
||||
@@ -530,14 +512,6 @@ function useMenu(props: Props) {
|
||||
menuItemDic.insertDateTime,
|
||||
menuItemDic.attachFile,
|
||||
separator(),
|
||||
menuItemDic['editor.deleteLine'],
|
||||
menuItemDic['editor.toggleComment'],
|
||||
menuItemDic['editor.sortSelectedLines'],
|
||||
menuItemDic['editor.indentLess'],
|
||||
menuItemDic['editor.indentMore'],
|
||||
menuItemDic['editor.swapLineDown'],
|
||||
menuItemDic['editor.swapLineUp'],
|
||||
separator(),
|
||||
menuItemDic.focusSearch,
|
||||
menuItemDic.showLocalSearch,
|
||||
],
|
||||
@@ -776,7 +750,7 @@ function useMenu(props: Props) {
|
||||
} else {
|
||||
setMenu(Menu.buildFromTemplate(template));
|
||||
}
|
||||
}, [props.routeName, props.pluginMenuItems, props.pluginMenus, keymapLastChangeTime, modulesLastChangeTime, props['spellChecker.language'], props['spellChecker.enabled'], props.plugins]);
|
||||
}, [props.routeName, props.pluginMenuItems, props.pluginMenus, keymapLastChangeTime, modulesLastChangeTime, props['spellChecker.language'], props['spellChecker.enabled']]);
|
||||
|
||||
useEffect(() => {
|
||||
const whenClauseContext = CommandService.instance().currentWhenClauseContext();
|
||||
@@ -873,7 +847,6 @@ const mapStateToProps = (state: AppState) => {
|
||||
pluginMenus: stateUtils.selectArrayShallow({ array: pluginUtils.viewsByType(state.pluginService.plugins, 'menu') }, 'menuBar.pluginMenus'),
|
||||
['spellChecker.language']: state.settings['spellChecker.language'],
|
||||
['spellChecker.enabled']: state.settings['spellChecker.enabled'],
|
||||
plugins: state.pluginService.plugins,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ interface KeyToLabelMap {
|
||||
let markupToHtml_: any = null;
|
||||
function markupToHtml() {
|
||||
if (markupToHtml_) return markupToHtml_;
|
||||
markupToHtml_ = markupLanguageUtils.newMarkupToHtml({});
|
||||
markupToHtml_ = markupLanguageUtils.newMarkupToHtml();
|
||||
return markupToHtml_;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ import { themeStyle } from '@joplin/lib/theme';
|
||||
import { ThemeAppearance } from '@joplin/lib/themes/type';
|
||||
import SpellCheckerService from '@joplin/lib/services/spellChecker/SpellCheckerService';
|
||||
import dialogs from '../../../dialogs';
|
||||
import convertToScreenCoordinates from '../../../utils/convertToScreenCoordinates';
|
||||
|
||||
const Note = require('@joplin/lib/models/Note.js');
|
||||
const { clipboard } = require('electron');
|
||||
@@ -165,18 +164,6 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
|
||||
replaceSelection: (value: any) => {
|
||||
return editorRef.current.replaceSelection(value);
|
||||
},
|
||||
textCopy: () => {
|
||||
editorCopyText();
|
||||
},
|
||||
textCut: () => {
|
||||
editorCutText();
|
||||
},
|
||||
textPaste: () => {
|
||||
editorPaste();
|
||||
},
|
||||
textSelectAll: () => {
|
||||
return editorRef.current.execCommand('selectAll');
|
||||
},
|
||||
textBold: () => wrapSelectionWithStrings('**', '**', _('strong text')),
|
||||
textItalic: () => wrapSelectionWithStrings('*', '*', _('emphasised text')),
|
||||
textLink: async () => {
|
||||
@@ -223,8 +210,6 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
|
||||
|
||||
if (commands[cmd.name]) {
|
||||
commandOutput = commands[cmd.name](cmd.value);
|
||||
} else if (editorRef.current.supportsCommand(cmd)) {
|
||||
commandOutput = editorRef.current.execCommandFromJoplin(cmd);
|
||||
} else {
|
||||
reg.logger().warn('CodeMirror: unsupported Joplin command: ', cmd);
|
||||
}
|
||||
@@ -270,17 +255,6 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
|
||||
}
|
||||
}, []);
|
||||
|
||||
const editorPaste = useCallback(() => {
|
||||
const clipboardText = clipboard.readText();
|
||||
|
||||
if (clipboardText) {
|
||||
editorPasteText();
|
||||
} else {
|
||||
// To handle pasting images
|
||||
void onEditorPaste();
|
||||
}
|
||||
}, [editorPasteText, onEditorPaste]);
|
||||
|
||||
const loadScript = async (script: any) => {
|
||||
return new Promise((resolve) => {
|
||||
let element: any = document.createElement('script');
|
||||
@@ -614,7 +588,7 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
|
||||
function pointerInsideEditor(x: number, y: number) {
|
||||
const elements = document.getElementsByClassName('codeMirrorEditor');
|
||||
if (!elements.length) return null;
|
||||
const rect = convertToScreenCoordinates(elements[0].getBoundingClientRect());
|
||||
const rect = elements[0].getBoundingClientRect();
|
||||
return rect.x < x && rect.y < y && rect.right > x && rect.bottom > y;
|
||||
}
|
||||
|
||||
@@ -624,6 +598,7 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
|
||||
const menu = new Menu();
|
||||
|
||||
const hasSelectedText = editorRef.current && !!editorRef.current.getSelection() ;
|
||||
const clipboardText = clipboard.readText();
|
||||
|
||||
menu.append(
|
||||
new MenuItem({
|
||||
@@ -650,7 +625,12 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
|
||||
label: _('Paste'),
|
||||
enabled: true,
|
||||
click: async () => {
|
||||
editorPaste();
|
||||
if (clipboardText) {
|
||||
editorPasteText();
|
||||
} else {
|
||||
// To handle pasting images
|
||||
void onEditorPaste();
|
||||
}
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
@@ -105,8 +105,8 @@ function Editor(props: EditorProps, ref: any) {
|
||||
useLineSorting(CodeMirror);
|
||||
useEditorSearch(CodeMirror);
|
||||
useJoplinMode(CodeMirror);
|
||||
const pluginOptions: any = useExternalPlugins(CodeMirror, props.plugins);
|
||||
useKeymap(CodeMirror);
|
||||
const pluginOptions: any = useExternalPlugins(CodeMirror, props.plugins);
|
||||
|
||||
useImperativeHandle(ref, () => {
|
||||
return editor;
|
||||
|
||||
@@ -138,87 +138,4 @@ export default function useCursorUtils(CodeMirror: any) {
|
||||
this.setSelection(anchor, head);
|
||||
});
|
||||
|
||||
//
|
||||
// START of HACK to support contenteditable
|
||||
//
|
||||
|
||||
// This is a HACK to enforce proper cursor positioning when using
|
||||
// codemirror in contenteditable mode
|
||||
// The problem is that chrome collapses trailing whitespace (for wrapped lines)
|
||||
// so when codemirror places the cursor after the trailing whitespace, chrome will
|
||||
// register that as being the start of the following line.
|
||||
//
|
||||
// An alternative fix for this would be to disable codemirror handling of Left/Right and Home/End
|
||||
// but that breaks multicursor support in codemirror.
|
||||
CodeMirror.defineExtension('isAfterTrailingWhitespace', function() {
|
||||
const { line, ch } = this.getCursor('head');
|
||||
const beforeCursor = this.charCoords({ line: line, ch: ch - 1 });
|
||||
const afterCursor = this.charCoords({ line: line, ch: ch });
|
||||
|
||||
const currentLine = this.getLine(line);
|
||||
|
||||
return beforeCursor.top < afterCursor.top && !!currentLine[ch - 1].match(/\s/);
|
||||
});
|
||||
|
||||
CodeMirror.commands.goLineRightSmart = function(cm: any) {
|
||||
// Only apply the manual cursor adjustments for contenteditable mode
|
||||
if (cm.options.inputStyle !== 'contenteditable') {
|
||||
cm.execCommand('goLineRight');
|
||||
return;
|
||||
}
|
||||
|
||||
// This detects the condition where the cursor is visibly placed at the beginning of
|
||||
// the current line, but codemirror treats it like it was on the end of the
|
||||
// previous line.
|
||||
// The fix is to step forward twice, then re-initiate goLineRight
|
||||
if (cm.isAfterTrailingWhitespace()) {
|
||||
cm.execCommand('goColumnRight');
|
||||
cm.execCommand('goColumnRight');
|
||||
cm.execCommand('goLineRightSmart');
|
||||
return;
|
||||
}
|
||||
|
||||
cm.execCommand('goLineRight');
|
||||
|
||||
// This detects the situation where the cursor moves to the end of a wrapped line
|
||||
// and is placed after a whitespace character.
|
||||
// In this situation we step the curso back once to put it on the correct line.
|
||||
if (cm.isAfterTrailingWhitespace()) {
|
||||
cm.execCommand('goCharLeft');
|
||||
}
|
||||
};
|
||||
|
||||
CodeMirror.commands.goLineUpSmart = function(cm: any) {
|
||||
if (cm.options.inputStyle !== 'contenteditable') {
|
||||
cm.execCommand('goLineUp');
|
||||
return;
|
||||
}
|
||||
|
||||
// In this situation the codemirror editor thinks it's a line above where it is.
|
||||
if (cm.isAfterTrailingWhitespace()) {
|
||||
cm.execCommand('goCharLeft');
|
||||
cm.execCommand('goLineLeft');
|
||||
} else {
|
||||
cm.execCommand('goLineUp');
|
||||
}
|
||||
};
|
||||
|
||||
CodeMirror.commands.goLineDownSmart = function(cm: any) {
|
||||
if (cm.options.inputStyle !== 'contenteditable') {
|
||||
cm.execCommand('goLineDown');
|
||||
return;
|
||||
}
|
||||
|
||||
// In this situation the codemirror editor thinks it's a line above where it is.
|
||||
if (cm.isAfterTrailingWhitespace()) {
|
||||
cm.execCommand('goLineRightSmart');
|
||||
cm.execCommand('goCharRight');
|
||||
} else {
|
||||
cm.execCommand('goLineDown');
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// END of HACK to support contenteditable
|
||||
//
|
||||
}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import { useEffect } from 'react';
|
||||
import CommandService from '@joplin/lib/services/CommandService';
|
||||
import KeymapService, { KeymapItem } from '@joplin/lib/services/KeymapService';
|
||||
import { EditorCommand } from '../../../utils/types';
|
||||
import shim from '@joplin/lib/shim';
|
||||
const { reg } = require('@joplin/lib/registry.js');
|
||||
|
||||
export default function useKeymap(CodeMirror: any) {
|
||||
|
||||
@@ -26,77 +23,6 @@ export default function useKeymap(CodeMirror: any) {
|
||||
CodeMirror.Vim.mapCommand('o', 'action', 'insertListElement', { after: true }, { context: 'normal', isEdit: true, interlaceInsertRepeat: true });
|
||||
}
|
||||
|
||||
function isEditorCommand(command: string) {
|
||||
return command.startsWith('editor.');
|
||||
}
|
||||
|
||||
// Converts a command of the form editor.command to just command
|
||||
function editorCommandToCodeMirror(command: String) {
|
||||
return command.slice(7); // 7 is the length of editor.
|
||||
}
|
||||
|
||||
// CodeMirror and Electron register accelerators slightly different
|
||||
// CodeMirror requires a - between keys while Electron want's a +
|
||||
// CodeMirror doesn't recognize Option (it uses Alt instead)
|
||||
// This function uses simple regex to translate the Electron
|
||||
// accelerator to a CodeMirror accelerator
|
||||
function normalizeAccelerator(accelerator: String) {
|
||||
return accelerator.replace(/\+/g, '-').replace('Option', 'Alt');
|
||||
}
|
||||
|
||||
// Because there is sometimes a clash between these keybindings and the Joplin window ones
|
||||
// (This specifically can happen with the Ctrl-B and Ctrl-I keybindings when
|
||||
// codemirror is in contenteditable mode)
|
||||
// we will register all keypresses with the codemirror editor to guarentee they
|
||||
// work no matter where the focus is
|
||||
function registerJoplinCommand(key: KeymapItem) {
|
||||
if (!key.command || !key.accelerator) return;
|
||||
|
||||
let command = '';
|
||||
if (isEditorCommand(key.command)) {
|
||||
command = editorCommandToCodeMirror(key.command);
|
||||
} else {
|
||||
// We need to register Joplin commands with codemirror
|
||||
command = `joplin${key.command}`;
|
||||
// Not all commands are registered with the command service
|
||||
// (for example, the Quit command)
|
||||
// This check will ensure that codemirror only takesover the commands that are
|
||||
// see gui/KeymapConfig/getLabel.ts for more information
|
||||
const commandNames = CommandService.instance().commandNames();
|
||||
if (commandNames.includes(key.command)) {
|
||||
CodeMirror.commands[command] = () => {
|
||||
void CommandService.instance().execute(key.command);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// CodeMirror and Electron have slightly different formats for defining accelerators
|
||||
const acc = normalizeAccelerator(key.accelerator);
|
||||
|
||||
CodeMirror.keyMap.default[acc] = command;
|
||||
}
|
||||
|
||||
// Called on initialization, and whenever the keymap changes
|
||||
function registerKeymap() {
|
||||
const keymapItems = KeymapService.instance().getKeymapItems();
|
||||
// Register all commands with the codemirror editor
|
||||
keymapItems.forEach((key) => { registerJoplinCommand(key); });
|
||||
}
|
||||
|
||||
CodeMirror.defineExtension('supportsCommand', function(cmd: EditorCommand) {
|
||||
return isEditorCommand(cmd.name) && editorCommandToCodeMirror(cmd.name) in CodeMirror.commands;
|
||||
});
|
||||
|
||||
// Used when an editor command is executed using the CommandService.instance().execute
|
||||
// function (rather than being initiated by a keypress in the editor)
|
||||
CodeMirror.defineExtension('execCommandFromJoplin', function(cmd: EditorCommand) {
|
||||
if (cmd.value) {
|
||||
reg.logger().warn('CodeMirror commands cannot accept a value:', cmd);
|
||||
}
|
||||
|
||||
return this.execCommand(editorCommandToCodeMirror(cmd.name));
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
// This enables the special modes (emacs and vim) to initiate sync by the save action
|
||||
CodeMirror.commands.save = save;
|
||||
@@ -104,9 +30,9 @@ export default function useKeymap(CodeMirror: any) {
|
||||
CodeMirror.keyMap.basic = {
|
||||
'Left': 'goCharLeft',
|
||||
'Right': 'goCharRight',
|
||||
'Up': 'goLineUpSmart',
|
||||
'Down': 'goLineDownSmart',
|
||||
'End': 'goLineRightSmart',
|
||||
'Up': 'goLineUp',
|
||||
'Down': 'goLineDown',
|
||||
'End': 'goLineRight',
|
||||
'Home': 'goLineLeftSmart',
|
||||
'PageUp': 'goPageUp',
|
||||
'PageDown': 'goPageDown',
|
||||
@@ -120,55 +46,61 @@ export default function useKeymap(CodeMirror: any) {
|
||||
'Esc': 'singleSelection',
|
||||
};
|
||||
|
||||
// Some keybindings are added here and not to the global registry because users
|
||||
// often expect multiple keys to bind to the same command for example, redo is mapped to
|
||||
// both Ctrl+Shift+Z AND Ctrl+Y
|
||||
// Doing this mapping here will make those commands available but will allow users to
|
||||
// override them using the KeymapService
|
||||
CodeMirror.keyMap.default = {
|
||||
// Windows / Linux
|
||||
'Ctrl-Z': 'undo',
|
||||
'Shift-Ctrl-Z': 'redo',
|
||||
'Ctrl-Y': 'redo',
|
||||
'Ctrl-Up': 'goLineUpSmart',
|
||||
'Ctrl-Down': 'goLineDownSmart',
|
||||
'Ctrl-Home': 'goDocStart',
|
||||
'Ctrl-End': 'goDocEnd',
|
||||
'Ctrl-Left': 'goGroupLeft',
|
||||
'Ctrl-Right': 'goGroupRight',
|
||||
'Alt-Left': 'goLineStart',
|
||||
'Alt-Right': 'goLineEnd',
|
||||
'Ctrl-Backspace': 'delGroupBefore',
|
||||
'Ctrl-Delete': 'delGroupAfter',
|
||||
|
||||
'fallthrough': 'basic',
|
||||
};
|
||||
if (shim.isMac()) {
|
||||
CodeMirror.keyMap.default = {
|
||||
// MacOS
|
||||
'Cmd-A': 'selectAll',
|
||||
'Cmd-D': 'deleteLine',
|
||||
'Cmd-Z': 'undo',
|
||||
'Shift-Cmd-Z': 'redo',
|
||||
'Cmd-Y': 'redo',
|
||||
'Cmd-End': 'goDocEnd',
|
||||
'Cmd-Down': 'goDocEnd',
|
||||
'Cmd-Home': 'goDocStart',
|
||||
'Cmd-Up': 'goDocStart',
|
||||
'Ctrl-D': 'delCharAfter',
|
||||
'Cmd-Left': 'goGroupLeft',
|
||||
'Cmd-Right': 'goGroupRight',
|
||||
'Ctrl-A': 'goLineStart',
|
||||
'Ctrl-E': 'goLineEnd',
|
||||
'Cmd-End': 'goDocEnd',
|
||||
'Cmd-Down': 'goDocEnd',
|
||||
'Cmd-Left': 'goLineLeft',
|
||||
'Cmd-Right': 'goLineRight',
|
||||
'Alt-Left': 'goGroupLeft',
|
||||
'Alt-Right': 'goGroupRight',
|
||||
'Alt-Backspace': 'delGroupBefore',
|
||||
'Alt-Delete': 'delGroupAfter',
|
||||
'Cmd-[': 'indentLess',
|
||||
'Cmd-]': 'indentMore',
|
||||
'Cmd-/': 'toggleComment',
|
||||
'Cmd-Opt-S': 'sortSelectedLines',
|
||||
'Opt-Up': 'swapLineUp',
|
||||
'Opt-Down': 'swapLineDown',
|
||||
|
||||
'fallthrough': 'basic',
|
||||
};
|
||||
} else {
|
||||
CodeMirror.keyMap.default = {
|
||||
// Windows/linux
|
||||
'Ctrl-A': 'selectAll',
|
||||
'Ctrl-D': 'deleteLine',
|
||||
'Ctrl-Z': 'undo',
|
||||
'Shift-Ctrl-Z': 'redo',
|
||||
'Ctrl-Y': 'redo',
|
||||
'Ctrl-Home': 'goDocStart',
|
||||
'Ctrl-End': 'goDocEnd',
|
||||
'Ctrl-Up': 'goLineUp',
|
||||
'Ctrl-Down': 'goLineDown',
|
||||
'Ctrl-Left': 'goGroupLeft',
|
||||
'Ctrl-Right': 'goGroupRight',
|
||||
'Alt-Left': 'goLineStart',
|
||||
'Alt-Right': 'goLineEnd',
|
||||
'Ctrl-Backspace': 'delGroupBefore',
|
||||
'Ctrl-Delete': 'delGroupAfter',
|
||||
'Ctrl-[': 'indentLess',
|
||||
'Ctrl-]': 'indentMore',
|
||||
'Ctrl-/': 'toggleComment',
|
||||
'Ctrl-Alt-S': 'sortSelectedLines',
|
||||
'Alt-Up': 'swapLineUp',
|
||||
'Alt-Down': 'swapLineDown',
|
||||
|
||||
'fallthrough': 'basic',
|
||||
};
|
||||
}
|
||||
|
||||
const keymapService = KeymapService.instance();
|
||||
|
||||
registerKeymap();
|
||||
keymapService.on('keymapChange', registerKeymap);
|
||||
|
||||
setupEmacs();
|
||||
setupVim();
|
||||
}, []);
|
||||
|
||||
@@ -19,7 +19,7 @@ const taboverride = require('taboverride');
|
||||
const { reg } = require('@joplin/lib/registry.js');
|
||||
const BaseItem = require('@joplin/lib/models/BaseItem');
|
||||
const { themeStyle } = require('@joplin/lib/theme');
|
||||
// const { clipboard } = require('electron');
|
||||
const { clipboard } = require('electron');
|
||||
const supportedLocales = require('./supportedLocales');
|
||||
|
||||
function markupRenderOptions(override: any = null) {
|
||||
@@ -1015,19 +1015,14 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
||||
}
|
||||
}
|
||||
|
||||
function onKeyDown(_event: any) {
|
||||
// It seems "paste as text" is now handled automatically by
|
||||
// either Chrome, Electron and/or TinyMCE so the code below
|
||||
// should not longer be necessary. Also fixes
|
||||
// https://github.com/laurent22/joplin/issues/4243
|
||||
|
||||
function onKeyDown(event: any) {
|
||||
// Handle "paste as text". Note that when pressing CtrlOrCmd+Shift+V it's going
|
||||
// to trigger the "keydown" event but not the "paste" event, so it's ok to process
|
||||
// it here and we don't need to do anything special in onPaste
|
||||
// if ((event.metaKey || event.ctrlKey) && event.shiftKey && event.code === 'KeyV') {
|
||||
// const pastedText = clipboard.readText();
|
||||
// if (pastedText) editor.insertContent(pastedText);
|
||||
// }
|
||||
if ((event.metaKey || event.ctrlKey) && event.shiftKey && event.code === 'KeyV') {
|
||||
const pastedText = clipboard.readText();
|
||||
if (pastedText) editor.insertContent(pastedText);
|
||||
}
|
||||
}
|
||||
|
||||
editor.on('keyup', onKeyUp);
|
||||
|
||||
@@ -6,7 +6,6 @@ import bridge from '../../../../../services/bridge';
|
||||
import { menuItems, ContextMenuOptions, ContextMenuItemType } from '../../../utils/contextMenu';
|
||||
import MenuUtils from '@joplin/lib/services/commands/MenuUtils';
|
||||
import CommandService from '@joplin/lib/services/CommandService';
|
||||
import convertToScreenCoordinates from '../../../../utils/convertToScreenCoordinates';
|
||||
|
||||
const Resource = require('@joplin/lib/models/Resource');
|
||||
|
||||
@@ -21,7 +20,7 @@ function contextMenuElement(editor: any, x: number, y: number) {
|
||||
const iframes = document.getElementsByClassName('tox-edit-area__iframe');
|
||||
if (!iframes.length) return null;
|
||||
|
||||
const iframeRect = convertToScreenCoordinates(iframes[0].getBoundingClientRect());
|
||||
const iframeRect = iframes[0].getBoundingClientRect();
|
||||
|
||||
if (iframeRect.x < x && iframeRect.y < y && iframeRect.right > x && iframeRect.bottom > y) {
|
||||
const relativeX = x - iframeRect.x;
|
||||
|
||||
@@ -154,7 +154,7 @@ function NoteEditor(props: NoteEditorProps) {
|
||||
const allAssets = useCallback(async (markupLanguage: number): Promise<any[]> => {
|
||||
const theme = themeStyle(props.themeId);
|
||||
|
||||
const markupToHtml = markupLanguageUtils.newMarkupToHtml({}, {
|
||||
const markupToHtml = markupLanguageUtils.newMarkupToHtml({
|
||||
resourceBaseUrl: `file://${Setting.value('resourceDir')}/`,
|
||||
});
|
||||
|
||||
|
||||
@@ -83,42 +83,6 @@ const declarations: CommandDeclaration[] = [
|
||||
label: () => _('Insert Date Time'),
|
||||
iconName: 'icon-add-date',
|
||||
},
|
||||
{
|
||||
name: 'editor.deleteLine',
|
||||
label: _('Delete line'),
|
||||
},
|
||||
{
|
||||
name: 'editor.undo',
|
||||
label: _('Undo'),
|
||||
},
|
||||
{
|
||||
name: 'editor.redo',
|
||||
label: _('Redo'),
|
||||
},
|
||||
{
|
||||
name: 'editor.indentLess',
|
||||
label: _('Indent less'),
|
||||
},
|
||||
{
|
||||
name: 'editor.indentMore',
|
||||
label: _('Indent more'),
|
||||
},
|
||||
{
|
||||
name: 'editor.toggleComment',
|
||||
label: _('Toggle comment'),
|
||||
},
|
||||
{
|
||||
name: 'editor.sortSelectedLines',
|
||||
label: _('Sort selected lines'),
|
||||
},
|
||||
{
|
||||
name: 'editor.swapLineUp',
|
||||
label: _('Swap line up'),
|
||||
},
|
||||
{
|
||||
name: 'editor.swapLineDown',
|
||||
label: _('Swap line down'),
|
||||
},
|
||||
{
|
||||
name: 'selectedText',
|
||||
},
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { PluginStates } from '@joplin/lib/services/plugins/reducer';
|
||||
import { contentScriptsToRendererRules } from '@joplin/lib/services/plugins/utils/loadContentScripts';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { ResourceInfos } from './types';
|
||||
import markupLanguageUtils from '@joplin/lib/markupLanguageUtils';
|
||||
@@ -22,8 +23,9 @@ export default function useMarkupToHtml(deps: HookDependencies) {
|
||||
const { themeId, customCss, plugins } = deps;
|
||||
|
||||
const markupToHtml = useMemo(() => {
|
||||
return markupLanguageUtils.newMarkupToHtml(deps.plugins, {
|
||||
return markupLanguageUtils.newMarkupToHtml({
|
||||
resourceBaseUrl: `file://${Setting.value('resourceDir')}/`,
|
||||
extraRendererRules: contentScriptsToRendererRules(plugins),
|
||||
});
|
||||
}, [plugins]);
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ class NoteRevisionViewerComponent extends React.PureComponent {
|
||||
|
||||
const theme = themeStyle(this.props.themeId);
|
||||
|
||||
const markupToHtml = markupLanguageUtils.newMarkupToHtml({}, {
|
||||
const markupToHtml = markupLanguageUtils.newMarkupToHtml({
|
||||
resourceBaseUrl: `file://${Setting.value('resourceDir')}/`,
|
||||
});
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ class SideBarComponent extends React.Component<Props, State> {
|
||||
private tagItemsOrder_: any[] = [];
|
||||
private rootRef: any = null;
|
||||
private anchorItemRefs: any = {};
|
||||
private pluginsRef: any;
|
||||
private pluginsRef:any;
|
||||
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
@@ -288,7 +288,7 @@ class SideBarComponent extends React.Component<Props, State> {
|
||||
new MenuItem({
|
||||
label: module.fullLabel(),
|
||||
click: async () => {
|
||||
await InteropServiceHelper.export(this.props.dispatch.bind(this), module, { sourceFolderIds: [itemId], plugins: this.pluginsRef.current });
|
||||
await InteropServiceHelper.export(this.props.dispatch.bind(this), module, { sourceFolderIds: [itemId] });
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
@@ -34,14 +34,5 @@ export default function() {
|
||||
'toggleNoteList',
|
||||
'toggleSideBar',
|
||||
'toggleVisiblePanes',
|
||||
'editor.deleteLine',
|
||||
'editor.undo',
|
||||
'editor.redo',
|
||||
'editor.indentLess',
|
||||
'editor.indentMore',
|
||||
'editor.toggleComment',
|
||||
'editor.sortSelectedLines',
|
||||
'editor.swapLineUp',
|
||||
'editor.swapLineDown',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -153,7 +153,6 @@ export default class NoteListUtils {
|
||||
await InteropServiceHelper.export(props.dispatch.bind(this), module, {
|
||||
sourceNoteIds: noteIds,
|
||||
includeConflicts: props.inConflictFolder,
|
||||
plugins: props.plugins,
|
||||
});
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
// Converts world coordinate to screen coordinates by applying the current
|
||||
// zoom.
|
||||
export default function convertToScreenCoordinates(o: any): any {
|
||||
const pixelRatio = window.devicePixelRatio;
|
||||
|
||||
if (typeof o === 'number') return o * pixelRatio;
|
||||
|
||||
if (typeof o === 'object' && o !== null) {
|
||||
o = JSON.parse(JSON.stringify(o));
|
||||
for (const k of Object.keys(o)) {
|
||||
o[k] = convertToScreenCoordinates(o[k]);
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
throw new Error(`Cannot convert to screen coordinates: ${typeof o}`);
|
||||
}
|
||||
2
packages/app-desktop/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/app-desktop",
|
||||
"version": "1.5.11",
|
||||
"version": "1.5.7",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/app-desktop",
|
||||
"version": "1.5.11",
|
||||
"version": "1.5.7",
|
||||
"description": "Joplin for Desktop",
|
||||
"main": "main.js",
|
||||
"private": true,
|
||||
|
||||
@@ -248,7 +248,7 @@ class Dialog extends React.PureComponent<Props, State> {
|
||||
|
||||
markupToHtml() {
|
||||
if (this.markupToHtml_) return this.markupToHtml_;
|
||||
this.markupToHtml_ = markupLanguageUtils.newMarkupToHtml({});
|
||||
this.markupToHtml_ = markupLanguageUtils.newMarkupToHtml();
|
||||
return this.markupToHtml_;
|
||||
}
|
||||
|
||||
|
||||
@@ -138,8 +138,8 @@ android {
|
||||
applicationId "net.cozic.joplin"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 2097614
|
||||
versionName "1.5.1"
|
||||
versionCode 2097613
|
||||
versionName "1.5.0"
|
||||
ndk {
|
||||
abiFilters "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ export default function useSource(noteBody: string, noteMarkupLanguage: number,
|
||||
}, [themeId, paddingBottom]);
|
||||
|
||||
const markupToHtml = useMemo(() => {
|
||||
return markupLanguageUtils.newMarkupToHtml({});
|
||||
return markupLanguageUtils.newMarkupToHtml();
|
||||
}, [isFirstRender]);
|
||||
|
||||
// To address https://github.com/laurent22/joplin/issues/433
|
||||
@@ -82,9 +82,7 @@ export default function useSource(noteBody: string, noteMarkupLanguage: number,
|
||||
resources: noteResources,
|
||||
codeTheme: theme.codeThemeCss,
|
||||
postMessageSyntax: 'window.joplinPostMessage_',
|
||||
// Disabled for now as it causes issues when zooming in or out
|
||||
// https://github.com/laurent22/joplin/pull/3939#issuecomment-734260166
|
||||
enableLongPress: false, // shim.mobilePlatform() === 'android', // On iOS, there's already a built-on open/share menu
|
||||
enableLongPress: shim.mobilePlatform() === 'android', // On iOS, there's already a built-on open/share menu
|
||||
};
|
||||
|
||||
// Whenever a resource state changes, for example when it goes from "not downloaded" to "downloaded", the "noteResources"
|
||||
|
||||
@@ -338,13 +338,13 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = 58;
|
||||
CURRENT_PROJECT_VERSION = 57;
|
||||
DEVELOPMENT_TEAM = A9BXAFS6CT;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Joplin/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
MARKETING_VERSION = 10.5.1;
|
||||
MARKETING_VERSION = 10.5.0;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
@@ -365,12 +365,12 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = 58;
|
||||
CURRENT_PROJECT_VERSION = 57;
|
||||
DEVELOPMENT_TEAM = A9BXAFS6CT;
|
||||
INFOPLIST_FILE = Joplin/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
MARKETING_VERSION = 10.5.1;
|
||||
MARKETING_VERSION = 10.5.0;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
|
||||
2
packages/fork-htmlparser2/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/fork-htmlparser2",
|
||||
"version": "4.1.14",
|
||||
"version": "4.1.8",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@joplin/fork-htmlparser2",
|
||||
"description": "Fast & forgiving HTML/XML/RSS parser",
|
||||
"version": "4.1.14",
|
||||
"version": "4.1.8",
|
||||
"author": "Felix Boehm <me@feedic.com>",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
@@ -64,6 +64,5 @@
|
||||
"license": "MIT",
|
||||
"prettier": {
|
||||
"tabWidth": 4
|
||||
},
|
||||
"gitHead": "80c0089d2c52aff608b2bea74389de5a7f12f2e2"
|
||||
}
|
||||
}
|
||||
|
||||
2
packages/fork-sax/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/fork-sax",
|
||||
"version": "1.2.18",
|
||||
"version": "1.2.12",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@joplin/fork-sax",
|
||||
"description": "An evented streaming XML parser in JavaScript",
|
||||
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
|
||||
"version": "1.2.18",
|
||||
"version": "1.2.12",
|
||||
"main": "lib/sax.js",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
@@ -17,6 +17,5 @@
|
||||
"devDependencies": {
|
||||
"standard": "^8.6.0",
|
||||
"tap": "^10.5.1"
|
||||
},
|
||||
"gitHead": "80c0089d2c52aff608b2bea74389de5a7f12f2e2"
|
||||
}
|
||||
}
|
||||
|
||||
2
packages/generator-joplin/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "generator-joplin",
|
||||
"version": "1.5.1",
|
||||
"version": "1.5.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "generator-joplin",
|
||||
"version": "1.5.1",
|
||||
"version": "1.5.0",
|
||||
"description": "Scaffolds out a new Joplin plugin",
|
||||
"homepage": "https://joplinapp.org",
|
||||
"author": {
|
||||
@@ -25,4 +25,4 @@
|
||||
},
|
||||
"repository": "https://github.com/laurent22/generator-joplin",
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ class FileApiDriverOneDrive {
|
||||
output.isDeleted = true;
|
||||
} else {
|
||||
// output.created_time = moment(odItem.fileSystemInfo.createdDateTime, 'YYYY-MM-DDTHH:mm:ss.SSSZ').format('x');
|
||||
output.updated_time = Number(moment(odItem.fileSystemInfo.lastModifiedDateTime, 'YYYY-MM-DDTHH:mm:ss.SSSZ').format('x'));
|
||||
output.updated_time = moment(odItem.fileSystemInfo.lastModifiedDateTime, 'YYYY-MM-DDTHH:mm:ss.SSSZ').format('x');
|
||||
}
|
||||
|
||||
return output;
|
||||
|
||||
@@ -377,12 +377,6 @@ function attributeToLowerCase(node) {
|
||||
return output;
|
||||
}
|
||||
|
||||
function isInvisibleBlock(attributes) {
|
||||
const style = attributes.style;
|
||||
if (!style) return false;
|
||||
return !!style.match(/display:[\s\S]*none/);
|
||||
}
|
||||
|
||||
function isSpanWithStyle(attributes) {
|
||||
if (attributes != undefined) {
|
||||
if ('style' in attributes) {
|
||||
@@ -395,13 +389,13 @@ function isSpanWithStyle(attributes) {
|
||||
|
||||
function isSpanStyleBold(attributes) {
|
||||
const style = attributes.style;
|
||||
if (!style) return false;
|
||||
|
||||
if (style.includes('font-weight: bold;')) {
|
||||
return true;
|
||||
} else if (style.search(/font-family:.*,Bold.*;/) != -1) {
|
||||
// console.debug('font-family regex matched');
|
||||
return true;
|
||||
} else {
|
||||
// console.debug('Found unsupported style(s) in span tag: %s', style);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -412,37 +406,6 @@ function isSpanStyleItalic(attributes) {
|
||||
return (style.toLowerCase().includes('font-style:italic;'));
|
||||
}
|
||||
|
||||
function displaySaxWarning(context, message) {
|
||||
const line = [];
|
||||
const parser = context ? context._parser : null;
|
||||
if (parser) {
|
||||
line.push(`Line ${parser.line}:${parser.column}`);
|
||||
}
|
||||
line.push(message);
|
||||
console.warn(line.join(': '));
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
|
||||
function removeSectionParent(section) {
|
||||
if (typeof section === 'string') return section;
|
||||
|
||||
section = { ...section };
|
||||
delete section.parent;
|
||||
|
||||
section.lines = section.lines.slice();
|
||||
|
||||
for (let i = 0; i < section.lines.length; i++) {
|
||||
section.lines[i] = removeSectionParent(section.lines[i]);
|
||||
}
|
||||
|
||||
return section;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
|
||||
function printSection(section) {
|
||||
console.info(JSON.stringify(removeSectionParent(section), null, 4));
|
||||
}
|
||||
|
||||
function enexXmlToMdArray(stream, resources) {
|
||||
const remainingResources = resources.slice();
|
||||
|
||||
@@ -463,7 +426,6 @@ function enexXmlToMdArray(stream, resources) {
|
||||
lists: [],
|
||||
anchorAttributes: [],
|
||||
spanAttributes: [],
|
||||
tags: [],
|
||||
};
|
||||
|
||||
const options = {};
|
||||
@@ -514,12 +476,6 @@ function enexXmlToMdArray(stream, resources) {
|
||||
saxStream.on('opentag', function(node) {
|
||||
const nodeAttributes = attributeToLowerCase(node);
|
||||
const n = node.name.toLowerCase();
|
||||
const isVisible = !isInvisibleBlock(nodeAttributes);
|
||||
|
||||
state.tags.push({
|
||||
name: n,
|
||||
visible: isVisible,
|
||||
});
|
||||
|
||||
const currentList = state.lists && state.lists.length ? state.lists[state.lists.length - 1] : null;
|
||||
|
||||
@@ -532,15 +488,10 @@ function enexXmlToMdArray(stream, resources) {
|
||||
currentList.startedText = true;
|
||||
}
|
||||
|
||||
// Note that the order of if/else blocks is important. In
|
||||
// particular table-related blocks should always be on top and
|
||||
// take priority over, in particular, hidden blocks. This is so
|
||||
// that a block that is both table-related and hidden is simply
|
||||
// handled as table-related. This is to ensure that the table
|
||||
// structure is valid.
|
||||
|
||||
if (n == 'en-note') {
|
||||
// Start of note
|
||||
} else if (isBlockTag(n)) {
|
||||
section.lines.push(BLOCK_OPEN);
|
||||
} else if (n == 'table') {
|
||||
const newSection = {
|
||||
type: 'table',
|
||||
@@ -552,20 +503,9 @@ function enexXmlToMdArray(stream, resources) {
|
||||
} else if (n == 'tbody' || n == 'thead') {
|
||||
// Ignore it
|
||||
} else if (n == 'tr') {
|
||||
// Note: Even if we encounter tags in the wrong place, we
|
||||
// create the sections anyway so that the data is imported.
|
||||
// Invalid HTML like would most likely be from clipped
|
||||
// pages which would look like a mess in Evernote. So it
|
||||
// will look like a mess in Joplin too but at least the
|
||||
// data will be there.
|
||||
//
|
||||
// Also if we simply skip the section, it will cause an
|
||||
// error in drawTable() later on.
|
||||
//
|
||||
// https://discourse.joplinapp.org/t/not-all-notes-imported-from-evernote/13056/12?u=laurent
|
||||
if (section.type != 'table') {
|
||||
displaySaxWarning(this, 'Found a <tr> tag outside of a table');
|
||||
// return;
|
||||
console.warn('Found a <tr> tag outside of a table');
|
||||
return;
|
||||
}
|
||||
|
||||
const newSection = {
|
||||
@@ -579,8 +519,8 @@ function enexXmlToMdArray(stream, resources) {
|
||||
section = newSection;
|
||||
} else if (n == 'td' || n == 'th') {
|
||||
if (section.type != 'tr') {
|
||||
displaySaxWarning(this, 'Found a <td> tag outside of a <tr>');
|
||||
// return;
|
||||
console.warn('Found a <td> tag outside of a <tr>');
|
||||
return;
|
||||
}
|
||||
|
||||
if (n == 'th') section.isHeader = true;
|
||||
@@ -593,38 +533,14 @@ function enexXmlToMdArray(stream, resources) {
|
||||
|
||||
section.lines.push(newSection);
|
||||
section = newSection;
|
||||
} else if (n == 'caption') {
|
||||
if (section.type != 'table') {
|
||||
displaySaxWarning(this, 'Found a <caption> tag outside of a <table>');
|
||||
// return;
|
||||
}
|
||||
|
||||
const newSection = {
|
||||
type: 'caption',
|
||||
lines: [],
|
||||
parent: section,
|
||||
};
|
||||
|
||||
section.lines.push(newSection);
|
||||
section = newSection;
|
||||
} else if (isInvisibleBlock(nodeAttributes)) {
|
||||
const newSection = {
|
||||
type: 'hidden',
|
||||
lines: [],
|
||||
parent: section,
|
||||
};
|
||||
section.lines.push(newSection);
|
||||
section = newSection;
|
||||
} else if (isBlockTag(n)) {
|
||||
section.lines.push(BLOCK_OPEN);
|
||||
} else if (isListTag(n)) {
|
||||
section.lines.push(BLOCK_OPEN);
|
||||
state.lists.push({ tag: n, counter: 1, startedText: false });
|
||||
} else if (n == 'li') {
|
||||
section.lines.push(BLOCK_OPEN);
|
||||
if (!state.lists.length) {
|
||||
displaySaxWarning(this, 'Found <li> tag without being inside a list');
|
||||
// return;
|
||||
console.warn('Found <li> tag without being inside a list');
|
||||
return;
|
||||
}
|
||||
|
||||
const container = state.lists[state.lists.length - 1];
|
||||
@@ -784,14 +700,14 @@ function enexXmlToMdArray(stream, resources) {
|
||||
}
|
||||
} else if (n == 'span') {
|
||||
if (isSpanWithStyle(nodeAttributes)) {
|
||||
// Found style(s) in span tag
|
||||
// console.debug('Found style(s) in span tag: %s', nodeAttributes.style);
|
||||
state.spanAttributes.push(nodeAttributes);
|
||||
if (isSpanStyleBold(nodeAttributes)) {
|
||||
// Applying style found in span tag: bold'
|
||||
// console.debug('Applying style found in span tag: bold')
|
||||
section.lines.push('**');
|
||||
}
|
||||
if (isSpanStyleItalic(nodeAttributes)) {
|
||||
// Applying style found in span tag: italic'
|
||||
// console.debug('Applying style found in span tag: italic')
|
||||
section.lines.push('*');
|
||||
}
|
||||
}
|
||||
@@ -805,17 +721,13 @@ function enexXmlToMdArray(stream, resources) {
|
||||
saxStream.on('closetag', function(n) {
|
||||
n = n ? n.toLowerCase() : n;
|
||||
|
||||
const poppedTag = state.tags.pop();
|
||||
|
||||
if (n == 'en-note') {
|
||||
// End of note
|
||||
} else if (!poppedTag.visible) {
|
||||
if (section && section.parent) section = section.parent;
|
||||
} else if (isNewLineOnlyEndTag(n)) {
|
||||
section.lines.push(BLOCK_CLOSE);
|
||||
} else if (n == 'td' || n == 'th') {
|
||||
if (section && section.parent) section = section.parent;
|
||||
} else if (n == 'tr' || n == 'caption') {
|
||||
} else if (n == 'tr') {
|
||||
if (section && section.parent) section = section.parent;
|
||||
} else if (n == 'table') {
|
||||
if (section && section.parent) section = section.parent;
|
||||
@@ -841,7 +753,7 @@ function enexXmlToMdArray(stream, resources) {
|
||||
state.inCode.pop();
|
||||
|
||||
if (!state.inCode.length) {
|
||||
const codeLines = processMdArrayNewLines(section.lines).split('\n');
|
||||
const codeLines = section.lines.join('').split('\n');
|
||||
section.lines = [];
|
||||
if (codeLines.length > 1) {
|
||||
for (let i = 0; i < codeLines.length; i++) {
|
||||
@@ -980,11 +892,11 @@ function enexXmlToMdArray(stream, resources) {
|
||||
const attributes = state.spanAttributes.pop();
|
||||
if (isSpanWithStyle(attributes)) {
|
||||
if (isSpanStyleBold(attributes)) {
|
||||
// Applying style found in span tag (closing): bold'
|
||||
// console.debug('Applying style found in span tag (closing): bold')
|
||||
section.lines.push('**');
|
||||
}
|
||||
if (isSpanStyleItalic(attributes)) {
|
||||
// Applying style found in span tag (closing): italic'
|
||||
// console.debug('Applying style found in span tag (closing): italic')
|
||||
section.lines.push('*');
|
||||
}
|
||||
}
|
||||
@@ -1013,10 +925,6 @@ function tableHasSubTables(table) {
|
||||
|
||||
for (let tdIndex = 0; tdIndex < tr.lines.length; tdIndex++) {
|
||||
const td = tr.lines[tdIndex];
|
||||
|
||||
// We are inside a CAPTION, not a TD
|
||||
if (typeof td === 'string') continue;
|
||||
|
||||
for (let i = 0; i < td.lines.length; i++) {
|
||||
if (typeof td.lines[i] === 'object') return true;
|
||||
}
|
||||
@@ -1042,15 +950,8 @@ function drawTable(table) {
|
||||
let lines = [];
|
||||
lines.push(BLOCK_OPEN);
|
||||
let headerDone = false;
|
||||
let caption = null;
|
||||
for (let trIndex = 0; trIndex < table.lines.length; trIndex++) {
|
||||
const tr = table.lines[trIndex];
|
||||
|
||||
if (tr.type === 'caption') {
|
||||
caption = tr;
|
||||
continue;
|
||||
}
|
||||
|
||||
const isHeader = tr.isHeader;
|
||||
const line = [];
|
||||
const headerLine = [];
|
||||
@@ -1073,14 +974,13 @@ function drawTable(table) {
|
||||
// In here, recursively render the tables
|
||||
for (let i = 0; i < td.lines.length; i++) {
|
||||
const c = td.lines[i];
|
||||
if (typeof c === 'object' && ['table', 'td', 'tr', 'th', 'caption'].indexOf(c.type) >= 0) {
|
||||
if (typeof c === 'object' && ['table', 'td', 'tr', 'th'].indexOf(c.type) >= 0) {
|
||||
// This is a table
|
||||
renderCurrentCells();
|
||||
currentCells = currentCells.concat(drawTable(c));
|
||||
} else {
|
||||
// This is plain text
|
||||
// currentCells.push(c);
|
||||
currentCells = currentCells.concat(renderLine(c));
|
||||
currentCells.push(c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1141,11 +1041,6 @@ function drawTable(table) {
|
||||
|
||||
lines.push(BLOCK_CLOSE);
|
||||
|
||||
if (caption) {
|
||||
const captionLines = renderLines(caption.lines);
|
||||
lines = lines.concat(captionLines);
|
||||
}
|
||||
|
||||
return flatRender ? lines : lines.join(`<<<<:D>>>>${NEWLINE}<<<<:D>>>>`).split('<<<<:D>>>>');
|
||||
}
|
||||
|
||||
@@ -1201,46 +1096,29 @@ function postProcessMarkdown(lines) {
|
||||
return lines;
|
||||
}
|
||||
|
||||
// A "line" can be some Markdown text, or it can be a section, like a table,
|
||||
// etc. so this function returns an array of strings.
|
||||
function renderLine(line) {
|
||||
if (typeof line === 'object' && line.type === 'table') {
|
||||
// A table
|
||||
const table = line;
|
||||
return drawTable(table);
|
||||
} else if (typeof line === 'object' && line.type === 'code') {
|
||||
return line.lines;
|
||||
} else if (typeof line === 'object' && line.type === 'hidden') {
|
||||
// ENEX notes sometimes have hidden tags. We could strip off these
|
||||
// sections but in the spirit of preserving all data we wrap them in
|
||||
// a hidden tag too.
|
||||
let hiddenLines = ['<div style="display: none;">'];
|
||||
hiddenLines = hiddenLines.concat(renderLines(line.lines));
|
||||
hiddenLines.push('</div>');
|
||||
return hiddenLines;
|
||||
} else if (typeof line === 'object') {
|
||||
console.warn('Unhandled object type:', line);
|
||||
return line.lines;
|
||||
} else {
|
||||
// an actual line
|
||||
return [line];
|
||||
}
|
||||
}
|
||||
|
||||
function renderLines(lines) {
|
||||
let mdLines = [];
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const renderedLines = renderLine(lines[i]);
|
||||
mdLines = mdLines.concat(renderedLines);
|
||||
}
|
||||
return mdLines;
|
||||
}
|
||||
|
||||
async function enexXmlToMd(xmlString, resources, options = {}) {
|
||||
const stream = stringToStream(xmlString);
|
||||
const result = await enexXmlToMdArray(stream, resources, options);
|
||||
|
||||
let mdLines = renderLines(result.content.lines);
|
||||
let mdLines = [];
|
||||
|
||||
for (let i = 0; i < result.content.lines.length; i++) {
|
||||
const line = result.content.lines[i];
|
||||
if (typeof line === 'object' && line.type === 'table') {
|
||||
// A table
|
||||
const table = line;
|
||||
const tableLines = drawTable(table);
|
||||
mdLines = mdLines.concat(tableLines);
|
||||
} else if (typeof line === 'object' && line.type === 'code') {
|
||||
mdLines = mdLines.concat(line.lines);
|
||||
} else if (typeof line === 'object') {
|
||||
console.warn('Unhandled object type:', line);
|
||||
mdLines = mdLines.concat(line.lines);
|
||||
} else {
|
||||
// an actual line
|
||||
mdLines.push(line);
|
||||
}
|
||||
}
|
||||
|
||||
let firstAttachment = true;
|
||||
for (let i = 0; i < result.resources.length; i++) {
|
||||
|
||||
@@ -6,7 +6,6 @@ const Tag = require('./models/Tag.js');
|
||||
const Resource = require('./models/Resource.js');
|
||||
const Setting = require('./models/Setting').default;
|
||||
const { MarkupToHtml } = require('@joplin/renderer');
|
||||
const { wrapError } = require('./errorUtils');
|
||||
const { enexXmlToMd } = require('./import-enex-md-gen.js');
|
||||
const { enexXmlToHtml } = require('./import-enex-html-gen.js');
|
||||
const time = require('./time').default;
|
||||
@@ -15,7 +14,6 @@ const md5 = require('md5');
|
||||
const { Base64Decode } = require('base64-stream');
|
||||
const md5File = require('md5-file');
|
||||
const shim = require('./shim').default;
|
||||
const { mime } = require('./mime-utils');
|
||||
|
||||
// const Promise = require('promise');
|
||||
const fs = require('fs-extra');
|
||||
@@ -325,13 +323,13 @@ function importEnex(parentFolderId, filePath, importOptions = null) {
|
||||
async function processNotes() {
|
||||
if (processingNotes) return false;
|
||||
|
||||
processingNotes = true;
|
||||
stream.pause();
|
||||
try {
|
||||
processingNotes = true;
|
||||
stream.pause();
|
||||
|
||||
while (notes.length) {
|
||||
const note = notes.shift();
|
||||
while (notes.length) {
|
||||
const note = notes.shift();
|
||||
|
||||
try {
|
||||
for (let i = 0; i < note.resources.length; i++) {
|
||||
let resource = note.resources[i];
|
||||
|
||||
@@ -385,10 +383,9 @@ function importEnex(parentFolderId, filePath, importOptions = null) {
|
||||
progressState.resourcesCreated += result.resourcesCreated;
|
||||
progressState.notesTagged += result.notesTagged;
|
||||
importOptions.onProgress(progressState);
|
||||
} catch (error) {
|
||||
const newError = wrapError(`Error on note "${note.title}"`, error);
|
||||
importOptions.onError(newError);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
stream.resume();
|
||||
@@ -517,27 +514,11 @@ function importEnex(parentFolderId, filePath, importOptions = null) {
|
||||
|
||||
noteAttributes = null;
|
||||
} else if (n == 'resource') {
|
||||
let mimeType = noteResource.mime ? noteResource.mime.trim() : '';
|
||||
|
||||
// Evernote sometimes gives an invalid or generic
|
||||
// "application/octet-stream" mime type for files that could
|
||||
// have a valid mime type, based on the extension. So in
|
||||
// general, we trust the filename more than the provided mime
|
||||
// type.
|
||||
// https://discourse.joplinapp.org/t/importing-a-note-with-a-zip-file/12123
|
||||
if (noteResource.filename) {
|
||||
const mimeTypeFromFile = mime.fromFilename(noteResource.filename);
|
||||
if (mimeTypeFromFile && mimeTypeFromFile !== mimeType) {
|
||||
importOptions.onError(new Error(`Invalid mime type "${mimeType}" for resource "${noteResource.filename}". Using "${mimeTypeFromFile}" instead.`));
|
||||
mimeType = mimeTypeFromFile;
|
||||
}
|
||||
}
|
||||
|
||||
note.resources.push({
|
||||
id: noteResource.id,
|
||||
dataFilePath: noteResource.dataFilePath,
|
||||
dataEncoding: noteResource.dataEncoding,
|
||||
mime: mimeType,
|
||||
mime: noteResource.mime ? noteResource.mime.trim() : '',
|
||||
title: noteResource.filename ? noteResource.filename.trim() : '',
|
||||
filename: noteResource.filename ? noteResource.filename.trim() : '',
|
||||
hasData: noteResource.hasData,
|
||||
|
||||
@@ -866,7 +866,7 @@ class JoplinDatabase extends Database {
|
||||
this.logger().warn('Could not upgrade to database v15 or v18 or v33 - FTS feature will not be used', error);
|
||||
saveVersionAgain = true;
|
||||
} else if (targetVersion === 34) {
|
||||
// if (!shim.isTestingEnv()) this.logger().warn('Could not upgrade to database v34 - fuzzy search will not be used', error);
|
||||
if (!shim.isTestingEnv()) this.logger().warn('Could not upgrade to database v34 - fuzzy search will not be used', error);
|
||||
saveVersionAgain = true;
|
||||
} else {
|
||||
throw error;
|
||||
|
||||
@@ -2,8 +2,6 @@ import markdownUtils from './markdownUtils';
|
||||
import Setting from './models/Setting';
|
||||
import shim from './shim';
|
||||
import MarkupToHtml, { MarkupLanguage } from '@joplin/renderer/MarkupToHtml';
|
||||
import { PluginStates } from './services/plugins/reducer';
|
||||
import { contentScriptsToRendererRules } from './services/plugins/utils/loadContentScripts';
|
||||
|
||||
const htmlUtils = require('./htmlUtils');
|
||||
const Resource = require('./models/Resource');
|
||||
@@ -21,7 +19,7 @@ class MarkupLanguageUtils {
|
||||
|
||||
// Create a new MarkupToHtml instance while injecting options specific to Joplin
|
||||
// desktop and mobile applications.
|
||||
newMarkupToHtml(plugins: PluginStates, options: any = null) {
|
||||
newMarkupToHtml(options: any = null) {
|
||||
const subValues = Setting.subValues('markdown.plugin', Setting.toPlainObject());
|
||||
const pluginOptions: any = {};
|
||||
for (const n in subValues) {
|
||||
@@ -33,7 +31,6 @@ class MarkupLanguageUtils {
|
||||
pluginOptions: pluginOptions,
|
||||
tempDir: Setting.value('tempDir'),
|
||||
fsDriver: shim.fsDriver(),
|
||||
extraRendererRules: contentScriptsToRendererRules(plugins),
|
||||
}, options);
|
||||
|
||||
return new MarkupToHtml(options);
|
||||
|
||||
@@ -793,6 +793,7 @@ class Setting extends BaseModel {
|
||||
type: SettingItemType.Bool,
|
||||
public: true,
|
||||
appTypes: ['desktop'],
|
||||
advanced: true,
|
||||
label: () => 'Enable spell checking in Markdown editor? (WARNING BETA feature)',
|
||||
description: () => 'Spell checker in the Markdown editor was previously unstable (cursor location was not stable, sometimes edits would not be saved or reflected in the viewer, etc.) however it appears to be more reliable now. If you notice any issue, please report it on GitHub or the Joplin Forum (Help -> Joplin Forum)',
|
||||
},
|
||||
|
||||
2
packages/lib/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/lib",
|
||||
"version": "1.0.15",
|
||||
"version": "1.0.9",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/lib",
|
||||
"version": "1.0.15",
|
||||
"version": "1.0.9",
|
||||
"description": "Joplin Core library",
|
||||
"author": "Laurent Cozic",
|
||||
"homepage": "",
|
||||
@@ -22,11 +22,11 @@
|
||||
"typescript": "^4.0.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@joplin/fork-htmlparser2": "^4.1.14",
|
||||
"@joplin/fork-sax": "^1.2.18",
|
||||
"@joplin/renderer": "^1.0.23",
|
||||
"@joplin/turndown": "^4.0.36",
|
||||
"@joplin/turndown-plugin-gfm": "^1.0.18",
|
||||
"@joplin/fork-htmlparser2": "^4.1.8",
|
||||
"@joplin/fork-sax": "^1.2.12",
|
||||
"@joplin/renderer": "^1.0.17",
|
||||
"@joplin/turndown": "^4.0.30",
|
||||
"@joplin/turndown-plugin-gfm": "^1.0.12",
|
||||
"async-mutex": "^0.1.3",
|
||||
"aws-sdk": "^2.588.0",
|
||||
"base-64": "^0.1.0",
|
||||
@@ -79,6 +79,5 @@
|
||||
"valid-url": "^1.0.9",
|
||||
"word-wrap": "^1.2.3",
|
||||
"xml2js": "^0.4.19"
|
||||
},
|
||||
"gitHead": "80c0089d2c52aff608b2bea74389de5a7f12f2e2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,10 +225,7 @@ export default class CommandService extends BaseService {
|
||||
|
||||
public async execute(commandName: string, ...args: any[]): Promise<any | void> {
|
||||
const command = this.commandByName(commandName);
|
||||
// Some commands such as "showModalMessage" can be executed many
|
||||
// times per seconds, so we should only display this message in
|
||||
// debug mode.
|
||||
this.logger().debug('CommandService::execute:', commandName, args);
|
||||
this.logger().info('CommandService::execute:', commandName, args);
|
||||
if (!command.runtime) throw new Error(`Cannot execute a command without a runtime: ${commandName}`);
|
||||
return command.runtime.execute(this.createContext(), ...args);
|
||||
}
|
||||
|
||||
@@ -45,15 +45,6 @@ const defaultKeymapItems = {
|
||||
{ accelerator: 'Cmd+P', command: 'gotoAnything' },
|
||||
{ accelerator: 'Shift+Cmd+P', command: 'commandPalette' },
|
||||
{ accelerator: 'F1', command: 'help' },
|
||||
{ accelerator: 'Cmd+D', command: 'editor.deleteLine' },
|
||||
{ accelerator: 'Cmd+Z', command: 'editor.undo' },
|
||||
{ accelerator: 'Cmd+Y', command: 'editor.redo' },
|
||||
{ accelerator: 'Cmd+[', command: 'editor.indentLess' },
|
||||
{ accelerator: 'Cmd+]', command: 'editor.indentMore' },
|
||||
{ accelerator: 'Cmd+/', command: 'editor.toggleComment' },
|
||||
{ accelerator: 'Option+Cmd+A', command: 'editor.sortSelectedLines' },
|
||||
{ accelerator: 'Option+Up', command: 'editor.swapLineUp' },
|
||||
{ accelerator: 'Option+Down', command: 'editor.swapLineDown' },
|
||||
],
|
||||
default: [
|
||||
{ accelerator: 'Ctrl+N', command: 'newNote' },
|
||||
@@ -86,15 +77,6 @@ const defaultKeymapItems = {
|
||||
{ accelerator: 'Ctrl+P', command: 'gotoAnything' },
|
||||
{ accelerator: 'Ctrl+Shift+P', command: 'commandPalette' },
|
||||
{ accelerator: 'F1', command: 'help' },
|
||||
{ accelerator: 'Ctrl+D', command: 'editor.deleteLine' },
|
||||
{ accelerator: 'Ctrl+Z', command: 'editor.undo' },
|
||||
{ accelerator: 'Ctrl+Y', command: 'editor.redo' },
|
||||
{ accelerator: 'Ctrl+[', command: 'editor.indentLess' },
|
||||
{ accelerator: 'Ctrl+]', command: 'editor.indentMore' },
|
||||
{ accelerator: 'Ctrl+/', command: 'editor.toggleComment' },
|
||||
{ accelerator: 'Ctrl+Alt+S', command: 'editor.sortSelectedLines' },
|
||||
{ accelerator: 'Alt+Up', command: 'editor.swapLineUp' },
|
||||
{ accelerator: 'Alt+Down', command: 'editor.swapLineDown' },
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ export default class InteropService_Exporter_Html extends InteropService_Exporte
|
||||
this.resourceDir_ = this.destDir_ ? `${this.destDir_}/_resources` : null;
|
||||
|
||||
await shim.fsDriver().mkdir(this.destDir_);
|
||||
this.markupToHtml_ = markupLanguageUtils.newMarkupToHtml(options.plugins);
|
||||
this.markupToHtml_ = markupLanguageUtils.newMarkupToHtml();
|
||||
this.resources_ = [];
|
||||
this.style_ = themeStyle(Setting.THEME_LIGHT);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { _ } from '../../locale';
|
||||
import { PluginStates } from '../plugins/reducer';
|
||||
|
||||
export interface CustomImportContext {
|
||||
sourcePath: string;
|
||||
@@ -95,7 +94,6 @@ export interface ExportOptions {
|
||||
// modulePath?: string;
|
||||
target?: FileSystemItem;
|
||||
includeConflicts?: boolean;
|
||||
plugins?: PluginStates;
|
||||
}
|
||||
|
||||
export interface ImportExportResult {
|
||||
|
||||
@@ -208,7 +208,7 @@ export enum MenuItemLocation {
|
||||
Note = 'note',
|
||||
Tools = 'tools',
|
||||
Help = 'help',
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated Do not use - same as NoteListContextMenu
|
||||
*/
|
||||
@@ -223,7 +223,7 @@ export enum MenuItemLocation {
|
||||
* - `noteIds:string[]`: IDs of the notes that were right-clicked on.
|
||||
*/
|
||||
NoteListContextMenu = 'noteListContextMenu',
|
||||
|
||||
|
||||
EditorContextMenu = 'editorContextMenu',
|
||||
|
||||
/**
|
||||
@@ -243,7 +243,7 @@ export enum MenuItemLocation {
|
||||
TagContextMenu = 'tagContextMenu',
|
||||
}
|
||||
|
||||
export function isContextMenuItemLocation(location: MenuItemLocation): boolean {
|
||||
export function isContextMenuItemLocation(location:MenuItemLocation):boolean {
|
||||
return [
|
||||
MenuItemLocation.Context,
|
||||
MenuItemLocation.NoteListContextMenu,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { PluginStates } from '../reducer';
|
||||
import { ContentScriptType } from '../api/types';
|
||||
import { dirname } from '@joplin/renderer/pathUtils';
|
||||
import shim from '../../../shim';
|
||||
|
||||
export interface ExtraContentScript {
|
||||
id: string;
|
||||
@@ -18,8 +17,6 @@ export function contentScriptsToCodeMirrorPlugin(plugins: PluginStates): ExtraCo
|
||||
}
|
||||
|
||||
function loadContentScripts(plugins: PluginStates, scriptType: ContentScriptType): ExtraContentScript[] {
|
||||
if (!plugins) return null;
|
||||
|
||||
const output: ExtraContentScript[] = [];
|
||||
|
||||
for (const pluginId in plugins) {
|
||||
@@ -28,7 +25,7 @@ function loadContentScripts(plugins: PluginStates, scriptType: ContentScriptType
|
||||
if (!contentScripts) continue;
|
||||
|
||||
for (const contentScript of contentScripts) {
|
||||
const module = shim.requireDynamic(contentScript.path);
|
||||
const module = require(contentScript.path);
|
||||
if (!module.default || typeof module.default !== 'function') throw new Error(`Content script must export a function under the "default" key: Plugin: ${pluginId}: Script: ${contentScript.id}`);
|
||||
|
||||
const loadedModule = module.default({});
|
||||
|
||||
@@ -176,10 +176,10 @@ export default class SpellCheckerService {
|
||||
},
|
||||
|
||||
// Can be removed once it does work
|
||||
// {
|
||||
// label: '⚠ Spell checker doesn\'t work in Markdown editor ⚠',
|
||||
// enabled: false,
|
||||
// },
|
||||
{
|
||||
label: '⚠ Spell checker doesn\'t work in Markdown editor ⚠',
|
||||
enabled: false,
|
||||
},
|
||||
|
||||
{
|
||||
type: 'separator',
|
||||
|
||||
@@ -533,10 +533,6 @@ function shimInit(sharp = null, keytar = null, React = null) {
|
||||
shim.keytar = () => {
|
||||
return keytar;
|
||||
};
|
||||
|
||||
shim.requireDynamic = (path) => {
|
||||
return require(path);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = { shimInit };
|
||||
|
||||
@@ -325,16 +325,6 @@ const shim = {
|
||||
keytar: (): any => {
|
||||
throw new Error('Not implemented');
|
||||
},
|
||||
|
||||
// In general all imports should be static, but for cases where dynamic
|
||||
// require is needed, we should use the shim so that the code can build in
|
||||
// React Native. In React Native that code path will throw an error, but at
|
||||
// least it will build.
|
||||
// https://stackoverflow.com/questions/55581073
|
||||
requireDynamic: (_path: string): any => {
|
||||
throw new Error('Not implemented');
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default shim;
|
||||
|
||||
@@ -272,11 +272,6 @@ function renderToStringWithCache(latex: string, katexOptions: any) {
|
||||
}
|
||||
}
|
||||
|
||||
function renderKatexError(latex: string, error: any): string {
|
||||
console.error('Katex error for:', latex, error);
|
||||
return `<div class="inline-code">${error.message}</div>`;
|
||||
}
|
||||
|
||||
export default {
|
||||
plugin: function(markdownIt: any, options: RuleOptions) {
|
||||
// Keep macros that persist across Katex blocks to allow defining a macro
|
||||
@@ -291,13 +286,12 @@ export default {
|
||||
// set KaTeX as the renderer for markdown-it-simplemath
|
||||
const katexInline = function(latex: string) {
|
||||
katexOptions.displayMode = false;
|
||||
let outputHtml: string = '';
|
||||
try {
|
||||
outputHtml = renderToStringWithCache(latex, katexOptions);
|
||||
return `<span class="joplin-editable"><span class="joplin-source" data-joplin-language="katex" data-joplin-source-open="$" data-joplin-source-close="$">${markdownIt.utils.escapeHtml(latex)}</span>${renderToStringWithCache(latex, katexOptions)}</span>`;
|
||||
} catch (error) {
|
||||
outputHtml = renderKatexError(latex, error);
|
||||
console.error('Katex error for:', latex, error);
|
||||
return latex;
|
||||
}
|
||||
return `<span class="joplin-editable"><span class="joplin-source" data-joplin-language="katex" data-joplin-source-open="$" data-joplin-source-close="$">${markdownIt.utils.escapeHtml(latex)}</span>${outputHtml}</span>`;
|
||||
};
|
||||
|
||||
const inlineRenderer = function(tokens: any[], idx: number) {
|
||||
@@ -306,13 +300,12 @@ export default {
|
||||
|
||||
const katexBlock = function(latex: string) {
|
||||
katexOptions.displayMode = true;
|
||||
let outputHtml: string = '';
|
||||
try {
|
||||
outputHtml = renderToStringWithCache(latex, katexOptions);
|
||||
return `<div class="joplin-editable"><pre class="joplin-source" data-joplin-language="katex" data-joplin-source-open="$$ " data-joplin-source-close=" $$ ">${markdownIt.utils.escapeHtml(latex)}</pre>${renderToStringWithCache(latex, katexOptions)}</div>`;
|
||||
} catch (error) {
|
||||
outputHtml = renderKatexError(latex, error);
|
||||
console.error('Katex error for:', latex, error);
|
||||
return latex;
|
||||
}
|
||||
return `<div class="joplin-editable"><pre class="joplin-source" data-joplin-language="katex" data-joplin-source-open="$$ " data-joplin-source-close=" $$ ">${markdownIt.utils.escapeHtml(latex)}</pre>${outputHtml}</div>`;
|
||||
};
|
||||
|
||||
const blockRenderer = function(tokens: any[], idx: number) {
|
||||
|
||||
2
packages/renderer/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/renderer",
|
||||
"version": "1.0.23",
|
||||
"version": "1.0.17",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/renderer",
|
||||
"version": "1.0.23",
|
||||
"version": "1.0.17",
|
||||
"description": "The Joplin note renderer, used the mobile and desktop application",
|
||||
"repository": "https://github.com/laurent22/joplin/tree/dev/packages/renderer",
|
||||
"main": "index.js",
|
||||
@@ -10,6 +10,7 @@
|
||||
},
|
||||
"scripts": {
|
||||
"buildAssets": "node Tools/buildAssets.js",
|
||||
"prepublishOnly": "npm run buildAssets",
|
||||
"tsc": "node node_modules/typescript/bin/tsc --project tsconfig.json",
|
||||
"watch": "node node_modules/typescript/bin/tsc --watch --project tsconfig.json",
|
||||
"test": "jest",
|
||||
@@ -18,13 +19,13 @@
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/jest": "^26.0.15",
|
||||
"@types/node": "^14.14.6",
|
||||
"@types/jest": "^26.0.15",
|
||||
"jest": "^26.6.3",
|
||||
"typescript": "^4.0.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@joplin/fork-htmlparser2": "^4.1.14",
|
||||
"@joplin/fork-htmlparser2": "^4.1.8",
|
||||
"font-awesome-filetypes": "^2.1.0",
|
||||
"fs-extra": "^8.1.0",
|
||||
"highlight.js": "^10.2.1",
|
||||
@@ -47,6 +48,5 @@
|
||||
"md5": "^2.2.1",
|
||||
"mermaid": "^8.8.4",
|
||||
"uslug": "git+https://github.com/laurent22/uslug.git#emoji-support"
|
||||
},
|
||||
"gitHead": "80c0089d2c52aff608b2bea74389de5a7f12f2e2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,7 +282,7 @@ const operations = [
|
||||
];
|
||||
|
||||
async function main() {
|
||||
const rootDir = dirname(dirname(__dirname));
|
||||
const rootDir = dirname(__dirname);
|
||||
const sourceImageDir = `${rootDir}/Assets/ImageSources`;
|
||||
|
||||
for (const operation of operations) {
|
||||
@@ -333,8 +333,6 @@ async function main() {
|
||||
const icnsSource = `${rootDir}/Assets/macOs.iconset`;
|
||||
console.info(`iconutil -c icns -o "${icnsDest}" "${icnsSource}"`);
|
||||
await execCommand(`iconutil -c icns -o "${icnsDest}" "${icnsSource}"`);
|
||||
} else {
|
||||
console.info('If the macOS icon has been updated, this script should be run on macOS too');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,8 +15,6 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.4.2\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"POT-Creation-Date: \n"
|
||||
"PO-Revision-Date: \n"
|
||||
|
||||
#: packages/app-desktop/bridge.js:106 packages/app-desktop/bridge.js:110
|
||||
#: packages/app-desktop/bridge.js:126 packages/app-desktop/bridge.js:134
|
||||
@@ -598,8 +596,9 @@ msgid "Options"
|
||||
msgstr "Opzioni"
|
||||
|
||||
#: packages/app-desktop/gui/KeymapConfig/utils/getLabel.js:37
|
||||
#, fuzzy
|
||||
msgid "Invalid"
|
||||
msgstr "Non valido"
|
||||
msgstr "%s non valido: %s."
|
||||
|
||||
#: packages/app-desktop/gui/KeymapConfig/ShortcutRecorder.js:49
|
||||
msgid "Press the shortcut"
|
||||
@@ -674,8 +673,6 @@ msgstr "Maggiori informazioni"
|
||||
#: packages/app-desktop/gui/MainScreen/MainScreen.js:527
|
||||
msgid "Use the arrows to move the layout items. Press \"Escape\" to exit."
|
||||
msgstr ""
|
||||
"Utilizza le frecce per muovere gli elementi del layout. Premi \"Esc\" per "
|
||||
"uscire"
|
||||
|
||||
#: packages/app-desktop/gui/MainScreen/commands/showNoteContentProperties.js:18
|
||||
msgid "Statistics..."
|
||||
@@ -744,7 +741,7 @@ msgstr "Attiva / disattiva editor"
|
||||
|
||||
#: packages/app-desktop/gui/MainScreen/commands/toggleLayoutMoveMode.js:16
|
||||
msgid "Change application layout"
|
||||
msgstr "Modifica il layout dell'applicazione"
|
||||
msgstr ""
|
||||
|
||||
#: packages/app-desktop/gui/MainScreen/commands/renameTag.js:30
|
||||
msgid "Rename tag:"
|
||||
@@ -761,7 +758,7 @@ msgstr "Titolo del Taccuino:"
|
||||
#: packages/app-desktop/gui/MainScreen/commands/showSpellCheckerMenu.js:19
|
||||
#: packages/lib/services/spellChecker/SpellCheckerService.js:180
|
||||
msgid "Spell checker"
|
||||
msgstr "Controllo ortografico"
|
||||
msgstr ""
|
||||
|
||||
#: packages/app-desktop/gui/MainScreen/commands/showShareNoteDialog.js:16
|
||||
msgid "Share note..."
|
||||
@@ -986,7 +983,7 @@ msgstr "Diminuisci zoom"
|
||||
|
||||
#: packages/app-desktop/gui/MenuBar.js:533
|
||||
msgid "&Go"
|
||||
msgstr "&Vai"
|
||||
msgstr ""
|
||||
|
||||
#: packages/app-desktop/gui/MenuBar.js:545
|
||||
msgid "&Note"
|
||||
@@ -1188,12 +1185,13 @@ msgstr ""
|
||||
"Importante: questa operazione va eseguita SOLO UNA VOLTA in UN dispositivo."
|
||||
|
||||
#: packages/app-desktop/gui/EncryptionConfigScreen.min.js:198
|
||||
#, fuzzy
|
||||
msgid "Re-encryption"
|
||||
msgstr "Cripta nuovamente"
|
||||
msgstr "Crittografia"
|
||||
|
||||
#: packages/app-desktop/gui/EncryptionConfigScreen.min.js:213
|
||||
msgid "Ignore"
|
||||
msgstr "Ignora"
|
||||
msgstr ""
|
||||
|
||||
#: packages/app-desktop/gui/EncryptionConfigScreen.min.js:244
|
||||
#: packages/app-mobile/components/screens/encryption-config.js:215
|
||||
@@ -1371,7 +1369,6 @@ msgstr "Naviga..."
|
||||
#: packages/app-desktop/gui/ConfigScreen/ConfigScreen.js:456
|
||||
msgid "The application must be restarted for these changes to take effect."
|
||||
msgstr ""
|
||||
"L'applicazione deve essere riavviata perché le modificano siano attive."
|
||||
|
||||
#: packages/app-desktop/gui/ConfigScreen/ConfigScreen.js:468
|
||||
#: packages/app-desktop/gui/NoteList/NoteList.js:163
|
||||
@@ -1380,24 +1377,25 @@ msgstr "Fallo subito"
|
||||
|
||||
#: packages/app-desktop/gui/ConfigScreen/ConfigScreen.js:468
|
||||
msgid "Later"
|
||||
msgstr "Dopo"
|
||||
msgstr ""
|
||||
|
||||
#: packages/app-desktop/gui/ConfigScreen/ConfigScreen.js:521
|
||||
#, fuzzy
|
||||
msgid "Restart now"
|
||||
msgstr "Riavvia ora"
|
||||
msgstr "Scaricalo subito:"
|
||||
|
||||
#: packages/app-desktop/gui/ConfigScreen/ButtonBar.js:27
|
||||
msgid "Apply"
|
||||
msgstr "Applica"
|
||||
|
||||
#: packages/app-desktop/gui/ConfigScreen/controls/PluginsStates.js:137
|
||||
#, javascript-format
|
||||
#, fuzzy, javascript-format
|
||||
msgid "Delete plugin \"%s\"?"
|
||||
msgstr "Eliminare il plugin \"%s\"?"
|
||||
msgstr "Eliminare la nota \"%s\"?"
|
||||
|
||||
#: packages/app-desktop/gui/ConfigScreen/controls/PluginsStates.js:181
|
||||
msgid "Install plugin"
|
||||
msgstr "Installa plugin"
|
||||
msgstr ""
|
||||
|
||||
#: packages/app-desktop/gui/PromptDialog.min.js:249
|
||||
msgid "Clear"
|
||||
@@ -2397,8 +2395,9 @@ msgstr ""
|
||||
"carattere generico monospace."
|
||||
|
||||
#: packages/lib/models/Setting.js:609
|
||||
#, fuzzy
|
||||
msgid "Custom stylesheet for rendered Markdown"
|
||||
msgstr "Foglio di stile personalizzato per visualizzare il markdown"
|
||||
msgstr "CSS per gli stili Joplin-wide app"
|
||||
|
||||
#: packages/lib/models/Setting.js:625
|
||||
msgid "Custom stylesheet for Joplin-wide app styles"
|
||||
@@ -2584,11 +2583,12 @@ msgstr ""
|
||||
|
||||
#: packages/lib/models/Setting.js:786
|
||||
msgid "Note list growth factor"
|
||||
msgstr "Fattore di crescita della lista note"
|
||||
msgstr "Fattore di crescita delle note"
|
||||
|
||||
#: packages/lib/models/Setting.js:798
|
||||
#, fuzzy
|
||||
msgid "Note area growth factor"
|
||||
msgstr "Fattore di crescita dell'area note"
|
||||
msgstr "Fattore di crescita dell'area delle note"
|
||||
|
||||
#: packages/lib/models/Setting.js:969
|
||||
#, javascript-format
|
||||
@@ -3027,7 +3027,7 @@ msgstr ""
|
||||
#: packages/app-cli/app/command-done.js:20
|
||||
#, javascript-format
|
||||
msgid "Cannot find \"%s\"."
|
||||
msgstr "Impossibile trovare \"%s\"."
|
||||
msgstr "Non posso trovare \"%s\"."
|
||||
|
||||
#: packages/lib/services/interop/InteropService.js:199
|
||||
#, javascript-format
|
||||
@@ -3120,7 +3120,7 @@ msgstr "Allegati"
|
||||
|
||||
#: packages/lib/services/report.js:190
|
||||
msgid "Downloaded and decrypted"
|
||||
msgstr "Scaricato e decrittato"
|
||||
msgstr "Scaricato e decriptato"
|
||||
|
||||
#: packages/lib/services/report.js:190 packages/lib/services/report.js:191
|
||||
#: packages/lib/services/report.js:194
|
||||
@@ -3143,7 +3143,7 @@ msgstr "%s (%s): %s"
|
||||
|
||||
#: packages/lib/services/report.js:222
|
||||
msgid "Sync status (synced items / total items)"
|
||||
msgstr "Stato di sincronizzazione (elementi sincronizzati / elementi totali)"
|
||||
msgstr "Stato di sincronizzazione (Elementi sincronizzati / Elementi totali)"
|
||||
|
||||
#: packages/lib/services/report.js:226
|
||||
#, javascript-format
|
||||
@@ -3158,7 +3158,7 @@ msgstr "Totale: %d %d"
|
||||
#: packages/lib/services/report.js:231
|
||||
#, javascript-format
|
||||
msgid "Conflicted: %d"
|
||||
msgstr "Conflitti: %d"
|
||||
msgstr "In conflitto: %d"
|
||||
|
||||
#: packages/lib/services/report.js:232
|
||||
#, javascript-format
|
||||
@@ -3185,19 +3185,20 @@ msgstr "Su %s: %s"
|
||||
|
||||
#: packages/lib/services/spellChecker/SpellCheckerService.js:107
|
||||
msgid "No suggestions"
|
||||
msgstr "Nessun suggerimento"
|
||||
msgstr ""
|
||||
|
||||
#: packages/lib/services/spellChecker/SpellCheckerService.js:114
|
||||
msgid "Add to dictionary"
|
||||
msgstr "Aggiungi al dizionario"
|
||||
msgstr ""
|
||||
|
||||
#: packages/lib/services/spellChecker/SpellCheckerService.js:153
|
||||
msgid "Use spell checker"
|
||||
msgstr "Usa controllo ortografico"
|
||||
msgstr ""
|
||||
|
||||
#: packages/lib/services/spellChecker/SpellCheckerService.js:173
|
||||
#, fuzzy
|
||||
msgid "Change language"
|
||||
msgstr "Cambia lingua"
|
||||
msgstr "Linguaggio"
|
||||
|
||||
#: packages/app-cli/app/command-cp.js:13
|
||||
msgid ""
|
||||
@@ -3458,11 +3459,11 @@ msgid "Downloading resources..."
|
||||
msgstr "Scaricamento risorse..."
|
||||
|
||||
#: packages/app-cli/app/command-sync.js:242
|
||||
#, javascript-format
|
||||
#, fuzzy, javascript-format
|
||||
msgid "Sync target must be upgraded! Run `%s` to proceed."
|
||||
msgstr ""
|
||||
"La destinazione di sincronizzazione deve essere aggiornata! Avvia `%s` per "
|
||||
"procedere."
|
||||
"La destinazione di sincronizzazione deve essere aggiornata. Premi questo "
|
||||
"banner per procedere."
|
||||
|
||||
#: packages/app-cli/app/command-sync.js:260
|
||||
msgid "Cancelling... Please wait."
|
||||
|
||||
2
packages/tools/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/tools",
|
||||
"version": "1.0.15",
|
||||
"version": "1.0.9",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/tools",
|
||||
"version": "1.0.15",
|
||||
"version": "1.0.9",
|
||||
"description": "Various tools for Joplin",
|
||||
"main": "index.js",
|
||||
"author": "Laurent Cozic",
|
||||
@@ -16,7 +16,7 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@joplin/lib": "^1.0.15",
|
||||
"@joplin/lib": "^1.0.9",
|
||||
"execa": "^4.1.0",
|
||||
"fs-extra": "^4.0.3",
|
||||
"gettext-parser": "^1.3.0",
|
||||
@@ -37,6 +37,5 @@
|
||||
"@types/node": "^14.14.6",
|
||||
"gulp": "^4.0.2",
|
||||
"sqlite3": "^5.0.0"
|
||||
},
|
||||
"gitHead": "80c0089d2c52aff608b2bea74389de5a7f12f2e2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
const { execCommand, execCommandVerbose, rootDir, gitPullTry, setPackagePrivateField } = require('./tool-utils.js');
|
||||
const { execCommand, execCommandVerbose, rootDir, gitPullTry } = require('./tool-utils.js');
|
||||
|
||||
const genDir = `${rootDir}/packages/generator-joplin`;
|
||||
|
||||
async function main() {
|
||||
process.chdir(genDir);
|
||||
|
||||
const packageFilePath = `${genDir}/package.json`;
|
||||
|
||||
console.info(`Running from: ${process.cwd()}`);
|
||||
|
||||
await gitPullTry();
|
||||
@@ -14,21 +12,15 @@ async function main() {
|
||||
const version = (await execCommand('npm version patch')).trim();
|
||||
const tagName = `plugin-generator-${version}`;
|
||||
|
||||
await setPackagePrivateField(packageFilePath, false);
|
||||
console.info(`New version number: ${version}`);
|
||||
|
||||
try {
|
||||
console.info(`New version number: ${version}`);
|
||||
|
||||
await execCommandVerbose('npm', ['publish']);
|
||||
await gitPullTry();
|
||||
await execCommandVerbose('git', ['add', '-A']);
|
||||
await execCommandVerbose('git', ['commit', '-m', `Plugin Generator release ${version}`]);
|
||||
await execCommandVerbose('git', ['tag', tagName]);
|
||||
await execCommandVerbose('git', ['push']);
|
||||
await execCommandVerbose('git', ['push', '--tags']);
|
||||
} finally {
|
||||
await setPackagePrivateField(packageFilePath, true);
|
||||
}
|
||||
await execCommandVerbose('npm', ['publish']);
|
||||
await gitPullTry();
|
||||
await execCommandVerbose('git', ['add', '-A']);
|
||||
await execCommandVerbose('git', ['commit', '-m', `Plugin Generator release ${version}`]);
|
||||
await execCommandVerbose('git', ['tag', tagName]);
|
||||
await execCommandVerbose('git', ['push']);
|
||||
await execCommandVerbose('git', ['push', '--tags']);
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
|
||||
@@ -89,17 +89,6 @@ toolUtils.deleteLink = async function(path) {
|
||||
}
|
||||
};
|
||||
|
||||
toolUtils.setPackagePrivateField = async function(filePath, value) {
|
||||
const text = await fs.readFile(filePath, 'utf8');
|
||||
const obj = JSON.parse(text);
|
||||
if (!value) {
|
||||
delete obj.private;
|
||||
} else {
|
||||
obj.private = true;
|
||||
}
|
||||
await fs.writeFile(filePath, JSON.stringify(obj, null, 2), 'utf8');
|
||||
};
|
||||
|
||||
toolUtils.credentialDir = async function() {
|
||||
const username = require('os').userInfo().username;
|
||||
|
||||
|
||||
2
packages/turndown-plugin-gfm/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/turndown-plugin-gfm",
|
||||
"version": "1.0.18",
|
||||
"version": "1.0.12",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
{
|
||||
"name": "@joplin/turndown-plugin-gfm",
|
||||
"description": "Turndown plugin to add GitHub Flavored Markdown extensions.",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"version": "1.0.18",
|
||||
"version": "1.0.12",
|
||||
"author": "Dom Christie",
|
||||
"main": "lib/turndown-plugin-gfm.cjs.js",
|
||||
"module": "lib/turndown-plugin-gfm.es.js",
|
||||
@@ -41,7 +38,6 @@
|
||||
"build-es": "rollup -c config/rollup.config.es.js && rollup -c config/rollup.config.browser.es.js",
|
||||
"build-iife": "rollup -c config/rollup.config.iife.js",
|
||||
"build-test": "browserify test/turndown-plugin-gfm-test.js --outfile test/turndown-plugin-gfm-test.browser.js",
|
||||
"prepare": "npm run build"
|
||||
},
|
||||
"gitHead": "80c0089d2c52aff608b2bea74389de5a7f12f2e2"
|
||||
"postinstall": "npm run build"
|
||||
}
|
||||
}
|
||||
|
||||
2
packages/turndown/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/turndown",
|
||||
"version": "4.0.36",
|
||||
"version": "4.0.30",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
{
|
||||
"name": "@joplin/turndown",
|
||||
"description": "A library that converts HTML to Markdown",
|
||||
"version": "4.0.36",
|
||||
"version": "4.0.30",
|
||||
"author": "Dom Christie",
|
||||
"main": "lib/turndown.cjs.js",
|
||||
"module": "lib/turndown.es.js",
|
||||
"jsnext:main": "lib/turndown.es.js",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"browser": {
|
||||
"jsdom": false
|
||||
},
|
||||
@@ -48,7 +45,6 @@
|
||||
"build-umd": "rollup -c config/rollup.config.umd.js && rollup -c config/rollup.config.browser.umd.js",
|
||||
"build-iife": "rollup -c config/rollup.config.iife.js",
|
||||
"build-test": "browserify test/turndown-test.js --outfile test/turndown-test.browser.js",
|
||||
"prepare": "npm run build"
|
||||
},
|
||||
"gitHead": "80c0089d2c52aff608b2bea74389de5a7f12f2e2"
|
||||
"postinstall": "npm run build"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,5 @@
|
||||
# Joplin terminal app changelog
|
||||
|
||||
## [cli-v1.5.1](https://github.com/laurent22/joplin/releases/tag/cli-v1.5.1) - 2020-12-26T00:46:31Z
|
||||
|
||||
- New: Add table captions when importing ENEX files
|
||||
- Improved: Allow exporting conflict notes (#4095)
|
||||
- Improved: Allow lowercase filters when doing search
|
||||
- Improved: Improved error handling when importing ENEX files
|
||||
- Improved: Partially reverts #3975 (link rendering)
|
||||
- Fixed: Fix sorting by title in a case insensitive way
|
||||
- Fixed: Fixed basic search when executing a query in Chinese (#4034 by Naveen M V)
|
||||
- Fixed: Fixed importing ENEX files that contain empty resources
|
||||
- Fixed: Fixed importing ENEX files that contain resources with invalid mime type
|
||||
- Fixed: Fixed importing certain ENEX files that contain invalid dates
|
||||
- Fixed: Fixed importing certain code blocks from ENEX
|
||||
- Fixed: Fixed issue when searching for text that contains diacritic (#4152) (#4025 by Roman Musin)
|
||||
- Fixed: Fixed issues when importing hidden tables within hidden sections in Enex files
|
||||
|
||||
## [cli-v1.4.9](https://github.com/laurent22/joplin/releases/tag/cli-v1.4.9) - 2020-11-26T15:00:37Z
|
||||
|
||||
- Improved: Allow exporting conflict notes (#4095)
|
||||
|
||||
@@ -14,12 +14,6 @@ Now try to install again and it should work.
|
||||
|
||||
More info there: https://github.com/electron-userland/electron-builder/issues/4057
|
||||
|
||||
## How can I pass arguments to the Linux installation script?
|
||||
|
||||
You can pass [arguments](https://github.com/laurent22/joplin/blob/dev/Joplin_install_and_update.sh#L37) to the installation script by using this command.
|
||||
|
||||
`wget -O - https://raw.githubusercontent.com/laurent22/joplin/dev/Joplin_install_and_update.sh \| bash -s -- --argument1 --argument2`
|
||||
|
||||
## How can I edit my note in an external text editor?
|
||||
|
||||
The editor command (may include arguments) defines which editor will be used to open a note. If none is provided it will try to auto-detect the default editor. If this does nothing or you want to change it for Joplin, you need to configure it in the Preferences -> Text editor command.
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
# Joplin Web API for Nextcloud
|
||||
|
||||
* * *
|
||||
|
||||
**IMPORTANT: THIS APPLICATION IS DEPRECATED AND WILL NO LONGER BE SUPPORTED FROM JOPLIN 1.6.x**
|
||||
|
||||
It is deprecated in favour of [Joplin Server](https://discourse.joplinapp.org/t/joplin-web-api-for-nextcloud/4491/72?u=laurent), so if you are relying on it please do not upgrade to Joplin 1.6.x till you are ready to migrate to Joplin Server or some other alternative.
|
||||
|
||||
* * *
|
||||
|
||||
**This is a beta feature, not yet completed. More info coming soon!**
|
||||
|
||||
The app can be downloaded from there: https://apps.nextcloud.com/apps/joplin
|
||||
@@ -45,4 +37,4 @@ No
|
||||
|
||||
- [ ] Handle encrypted notes (shared notes will be unencrypted on server)
|
||||
- [ ] Move Joplin note rendererer to separate package and re-use it to render notes in the Nextcloud app
|
||||
- [ ] Allow editing note in browser
|
||||
- [ ] Allow editing note in browser
|
||||