You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2026-02-22 08:47:34 +02:00
Compare commits
41 Commits
v2.13.12
...
check-pr-t
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
60c755dbbf | ||
|
|
84cc1576a8 | ||
|
|
29b42b3b37 | ||
|
|
3b15834e8d | ||
|
|
d9ce98d374 | ||
|
|
19531d229b | ||
|
|
2b9bf6deba | ||
|
|
0abaeef05e | ||
|
|
b2e86d2f8a | ||
|
|
52a3a59623 | ||
|
|
c78afc46c9 | ||
|
|
9b89f4ecfb | ||
|
|
99be29707f | ||
|
|
2a62bbdbd3 | ||
|
|
c5e15e93f4 | ||
|
|
719e0e6104 | ||
|
|
1eea2400cb | ||
|
|
83efd67ff8 | ||
|
|
8ef682dcf9 | ||
|
|
401d551daa | ||
|
|
8a533b2003 | ||
|
|
27f888d0c4 | ||
|
|
4aeb2fafb2 | ||
|
|
dc20402f5b | ||
|
|
9b078de9d8 | ||
|
|
214f9916d9 | ||
|
|
87aeffa160 | ||
|
|
14a2d2d795 | ||
|
|
3560bc62a2 | ||
|
|
0729d1db27 | ||
|
|
5f27d425bf | ||
|
|
e2956c391d | ||
|
|
bdc8f30705 | ||
|
|
2c9bf9f03a | ||
|
|
60c2964acd | ||
|
|
97248035b1 | ||
|
|
35c79a2cfb | ||
|
|
9b9762f940 | ||
|
|
e186fe8936 | ||
|
|
213cd419f0 | ||
|
|
b89b5fef65 |
@@ -249,6 +249,8 @@ packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/styles/index.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/joplinCommandToTinyMceCommands.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/openEditDialog.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/setupToolbarButtons.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/shouldPasteResources.test.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/shouldPasteResources.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/types.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useContextMenu.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useScroll.js
|
||||
@@ -542,7 +544,6 @@ packages/editor/CodeMirror/editorCommands/swapLine.js
|
||||
packages/editor/CodeMirror/getScrollFraction.js
|
||||
packages/editor/CodeMirror/markdown/computeSelectionFormatting.test.js
|
||||
packages/editor/CodeMirror/markdown/computeSelectionFormatting.js
|
||||
packages/editor/CodeMirror/markdown/decoratorExtension.test.js
|
||||
packages/editor/CodeMirror/markdown/decoratorExtension.js
|
||||
packages/editor/CodeMirror/markdown/markdownCommands.bulletedVsChecklist.test.js
|
||||
packages/editor/CodeMirror/markdown/markdownCommands.test.js
|
||||
|
||||
42
.github/scripts/run_ci.sh
vendored
42
.github/scripts/run_ci.sh
vendored
@@ -8,16 +8,23 @@ SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
|
||||
ROOT_DIR="$SCRIPT_DIR/../.."
|
||||
|
||||
IS_PULL_REQUEST=0
|
||||
IS_DEV_BRANCH=0
|
||||
IS_DESKTOP_RELEASE=0
|
||||
IS_SERVER_RELEASE=0
|
||||
IS_LINUX=0
|
||||
IS_MACOS=0
|
||||
|
||||
# If pull requests are coming from a branch of the main repository,
|
||||
# IS_PULL_REQUEST will be zero.
|
||||
if [ "$GITHUB_EVENT_NAME" == "pull_request" ]; then
|
||||
IS_PULL_REQUEST=1
|
||||
fi
|
||||
|
||||
if [ "$GITHUB_REF" == "refs/heads/dev" ]; then
|
||||
IS_DEV_BRANCH=1
|
||||
if [[ $GIT_TAG_NAME = $SERVER_TAG_PREFIX-* ]]; then
|
||||
IS_SERVER_RELEASE=1
|
||||
fi
|
||||
|
||||
if [[ $GIT_TAG_NAME = v* ]]; then
|
||||
IS_DESKTOP_RELEASE=1
|
||||
fi
|
||||
|
||||
if [ "$RUNNER_OS" == "Linux" ]; then
|
||||
@@ -28,6 +35,14 @@ else
|
||||
IS_MACOS=1
|
||||
fi
|
||||
|
||||
# Tests can randomly fail in some cases, so only run them when not publishing
|
||||
# a release
|
||||
RUN_TESTS=0
|
||||
|
||||
if [ "$IS_SERVER_RELEASE" = 0 ] && [ "$IS_DESKTOP_RELEASE" = 0 ]; then
|
||||
RUN_TESTS=1
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
# Print environment
|
||||
# =============================================================================
|
||||
@@ -43,7 +58,9 @@ echo "SERVER_TAG_PREFIX=$SERVER_TAG_PREFIX"
|
||||
|
||||
echo "IS_CONTINUOUS_INTEGRATION=$IS_CONTINUOUS_INTEGRATION"
|
||||
echo "IS_PULL_REQUEST=$IS_PULL_REQUEST"
|
||||
echo "IS_DEV_BRANCH=$IS_DEV_BRANCH"
|
||||
echo "IS_DESKTOP_RELEASE=$IS_DESKTOP_RELEASE"
|
||||
echo "IS_SERVER_RELEASE=$IS_SERVER_RELEASE"
|
||||
echo "RUN_TESTS=$RUN_TESTS"
|
||||
echo "IS_LINUX=$IS_LINUX"
|
||||
echo "IS_MACOS=$IS_MACOS"
|
||||
|
||||
@@ -64,11 +81,10 @@ if [ $testResult -ne 0 ]; then
|
||||
fi
|
||||
|
||||
# =============================================================================
|
||||
# Run test units. Only do it for pull requests and dev branch because we don't
|
||||
# want it to randomly fail when trying to create a desktop release.
|
||||
# Run test units
|
||||
# =============================================================================
|
||||
|
||||
if [ "$IS_PULL_REQUEST" == "1" ] || [ "$IS_DEV_BRANCH" = "1" ]; then
|
||||
if [ "$RUN_TESTS" == "1" ]; then
|
||||
echo "Step: Running tests..."
|
||||
|
||||
# On Linux, we run the Joplin Server tests using PostgreSQL
|
||||
@@ -102,7 +118,7 @@ fi
|
||||
# Check that the website builder can run without errors
|
||||
# =============================================================================
|
||||
|
||||
if [ "$IS_PULL_REQUEST" == "1" ] || [ "$IS_DEV_BRANCH" = "1" ]; then
|
||||
if [ "$RUN_TESTS" == "1" ]; then
|
||||
if [ "$IS_LINUX" == "1" ]; then
|
||||
echo "Step: Running website builder..."
|
||||
node packages/tools/website/processDocs.js --env dev
|
||||
@@ -114,7 +130,7 @@ fi
|
||||
# release randomly fail.
|
||||
# =============================================================================
|
||||
|
||||
if [ "$IS_PULL_REQUEST" == "1" ] || [ "$IS_DEV_BRANCH" = "1" ]; then
|
||||
if [ "$RUN_TESTS" == "1" ]; then
|
||||
echo "Step: Running linter..."
|
||||
|
||||
yarn run linter-ci ./
|
||||
@@ -154,7 +170,7 @@ fi
|
||||
# what commit may have broken translation building.
|
||||
# =============================================================================
|
||||
|
||||
if [ "$IS_PULL_REQUEST" == "1" ] || [ "$IS_DEV_BRANCH" = "1" ]; then
|
||||
if [ "$RUN_TESTS" == "1" ]; then
|
||||
if [ "$IS_LINUX" == "1" ]; then
|
||||
echo "Step: Checking for lost translation strings..."
|
||||
|
||||
@@ -190,7 +206,7 @@ fi
|
||||
# Check that the website still builds
|
||||
# =============================================================================
|
||||
|
||||
if [ "$IS_PULL_REQUEST" == "1" ] || [ "$IS_DEV_BRANCH" = "1" ]; then
|
||||
if [ "$RUN_TESTS" == "1" ]; then
|
||||
echo "Step: Check that the website still builds..."
|
||||
|
||||
mkdir -p ../joplin-website/docs
|
||||
@@ -226,7 +242,7 @@ fi
|
||||
|
||||
cd "$ROOT_DIR/packages/app-desktop"
|
||||
|
||||
if [[ $GIT_TAG_NAME = v* ]]; then
|
||||
if [ "$IS_DESKTOP_RELEASE" == "1" ]; then
|
||||
echo "Step: Building and publishing desktop application..."
|
||||
# cd "$ROOT_DIR/packages/tools"
|
||||
# node bundleDefaultPlugins.js
|
||||
@@ -251,7 +267,7 @@ if [[ $GIT_TAG_NAME = v* ]]; then
|
||||
else
|
||||
USE_HARD_LINKS=false yarn run dist
|
||||
fi
|
||||
elif [[ $IS_LINUX = 1 ]] && [[ $GIT_TAG_NAME = $SERVER_TAG_PREFIX-* ]]; then
|
||||
elif [[ $IS_LINUX = 1 ]] && [ "$IS_SERVER_RELEASE" == "1" ]; then
|
||||
echo "Step: Building Docker Image..."
|
||||
cd "$ROOT_DIR"
|
||||
yarn run buildServerDocker --tag-name $GIT_TAG_NAME --push-images --repository $SERVER_REPOSITORY
|
||||
|
||||
8
.github/workflows/check-pr-title.yml
vendored
Normal file
8
.github/workflows/check-pr-title.yml
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
name: Check pull request title
|
||||
on: [pull_request]
|
||||
jobs:
|
||||
main:
|
||||
steps:
|
||||
- uses: Slashgear/action-check-pr-title@v4.3.0
|
||||
with:
|
||||
regexp: "(Desktop|Mobile|All|Cli|Tools|Chore|Clipper|Server|Android|iOS|Plugins): (Fixes|Resolves) #[0-9]+: .+"
|
||||
14
.github/workflows/comment-on-failure.yml
vendored
Normal file
14
.github/workflows/comment-on-failure.yml
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
name: comment-on-failure
|
||||
on:
|
||||
workflow_run:
|
||||
workflows:
|
||||
- Joplin Continuous Integration
|
||||
- react-native-android-build-apk
|
||||
- Build macOS M1
|
||||
types: [ completed ]
|
||||
|
||||
jobs:
|
||||
comment-failure:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: quipper/comment-failure-action@v0.1.1
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -231,6 +231,8 @@ packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/styles/index.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/joplinCommandToTinyMceCommands.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/openEditDialog.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/setupToolbarButtons.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/shouldPasteResources.test.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/shouldPasteResources.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/types.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useContextMenu.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/useScroll.js
|
||||
@@ -524,7 +526,6 @@ packages/editor/CodeMirror/editorCommands/swapLine.js
|
||||
packages/editor/CodeMirror/getScrollFraction.js
|
||||
packages/editor/CodeMirror/markdown/computeSelectionFormatting.test.js
|
||||
packages/editor/CodeMirror/markdown/computeSelectionFormatting.js
|
||||
packages/editor/CodeMirror/markdown/decoratorExtension.test.js
|
||||
packages/editor/CodeMirror/markdown/decoratorExtension.js
|
||||
packages/editor/CodeMirror/markdown/markdownCommands.bulletedVsChecklist.test.js
|
||||
packages/editor/CodeMirror/markdown/markdownCommands.test.js
|
||||
|
||||
@@ -26,7 +26,7 @@ For more information about the applications, see the [full Joplin documentation]
|
||||
|
||||
Donations to Joplin support the development of the project. Developing quality applications mostly takes time, but there are also some expenses, such as digital certificates to sign the applications, app store fees, hosting, etc. Most of all, your donation will make it possible to keep up the current development standard.
|
||||
|
||||
Please see the [donation page](https://github.com/laurent22/joplin/blob/dev/readme/about/donate.md) for information on how to support the development of Joplin.
|
||||
Please see the [donation page](https://github.com/laurent22/joplin/blob/dev/readme/donate.md) for information on how to support the development of Joplin.
|
||||
|
||||
# Sponsors
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
"@types/fs-extra": "11.0.3",
|
||||
"eslint-plugin-github": "4.10.0",
|
||||
"http-server": "14.1.1",
|
||||
"node-gyp": "9.4.0",
|
||||
"node-gyp": "9.4.1",
|
||||
"nodemon": "3.0.1"
|
||||
},
|
||||
"packageManager": "yarn@3.6.4",
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
],
|
||||
"owner": "Laurent Cozic"
|
||||
},
|
||||
"version": "2.13.2",
|
||||
"version": "2.13.1",
|
||||
"bin": "./main.js",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
@@ -73,7 +73,7 @@
|
||||
"@joplin/tools": "~2.13",
|
||||
"@types/fs-extra": "11.0.3",
|
||||
"@types/jest": "29.5.5",
|
||||
"@types/node": "18.18.7",
|
||||
"@types/node": "18.18.8",
|
||||
"@types/proper-lockfile": "^4.1.2",
|
||||
"gulp": "4.0.2",
|
||||
"jest": "29.7.0",
|
||||
|
||||
@@ -291,29 +291,4 @@ describe('MdToHtml', () => {
|
||||
expect(html.html).toContain(opening + trimmedTex + closing);
|
||||
}
|
||||
});
|
||||
|
||||
it('should render inline KaTeX after a numbered equation', async () => {
|
||||
const mdToHtml = newTestMdToHtml();
|
||||
|
||||
// This test is intended to verify that inline KaTeX renders correctly
|
||||
// after creating a numbered equation with \begin{align}...\end{align}.
|
||||
//
|
||||
// See https://github.com/laurent22/joplin/issues/9455 for details.
|
||||
|
||||
const markdown = [
|
||||
'$$',
|
||||
'\\begin{align}\\text{Block}\\end{align}',
|
||||
'$$',
|
||||
'',
|
||||
'$\\text{Inline}$',
|
||||
].join('\n');
|
||||
const { html } = await mdToHtml.render(markdown, null, { bodyOnly: true });
|
||||
|
||||
// Because we don't control the output of KaTeX, this test should be as general as
|
||||
// possible while still verifying that rendering (without an error) occurs.
|
||||
|
||||
// Should have rendered the inline and block content without errors
|
||||
expect(html).toContain('Inline</span>');
|
||||
expect(html).toContain('Block</span>');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<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></t><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"?>
|
||||
<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>
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,12 +0,0 @@
|
||||
<table>
|
||||
<div></div> <!-- INVALID! -->
|
||||
<tr>
|
||||
<td>one</td>
|
||||
<td>two</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<div></div> <!-- INVALID! -->
|
||||
<td>three</td>
|
||||
<td>four</td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -1,4 +0,0 @@
|
||||
| | |
|
||||
| --- | --- |
|
||||
| one | two |
|
||||
| three | four |
|
||||
@@ -1,10 +1,10 @@
|
||||
<body>
|
||||
<table>
|
||||
<table border="5px" bordercolor="#8707B0">
|
||||
<tr>
|
||||
<td>Left side of the main table</td>
|
||||
<td>
|
||||
<table>
|
||||
<b>Nested Table</b>
|
||||
<table border="5px" bordercolor="#F35557">
|
||||
<h4 align="center">Nested Table</h4>
|
||||
<tr>
|
||||
<td>nested table C1</td>
|
||||
<td>nested table C2</td>
|
||||
|
||||
@@ -1 +1 @@
|
||||
<table><tbody><tr><td>Left side of the main table</td><td><b>Nested Table</b><table><tbody><tr><td>nested table C1</td><td>nested table C2</td></tr><tr><td>nested table</td><td>nested table</td></tr></tbody></table></td></tr></tbody></table>
|
||||
<table border="5px" bordercolor="#8707B0"><tbody><tr><td>Left side of the main table</td><td><h4 align="center">Nested Table</h4><table border="5px" bordercolor="#F35557"><tbody><tr><td>nested table C1</td><td>nested table C2</td></tr><tr><td>nested table</td><td>nested table</td></tr></tbody></table></td></tr></tbody></table>
|
||||
@@ -27,6 +27,7 @@ import bridge from '../../../../services/bridge';
|
||||
import { TinyMceEditorEvents } from './utils/types';
|
||||
import type { Editor } from 'tinymce';
|
||||
import { joplinCommandToTinyMceCommands, TinyMceCommand } from './utils/joplinCommandToTinyMceCommands';
|
||||
import shouldPasteResources from './utils/shouldPasteResources';
|
||||
const { clipboard } = require('electron');
|
||||
const supportedLocales = require('./supportedLocales');
|
||||
|
||||
@@ -1085,15 +1086,9 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
||||
// formatted text.
|
||||
const pastedHtml = event.clipboardData.getData('text/html') ? clipboard.readHTML() : '';
|
||||
|
||||
// We should only process the images if there is no plain text or
|
||||
// HTML text in the clipboard. This is because certain applications,
|
||||
// such as Word, are going to add multiple versions of the copied
|
||||
// data to the clipboard - one with the text formatted as HTML, and
|
||||
// one with the text as an image. In that case, we need to ignore
|
||||
// the image and only process the HTML.
|
||||
const resourceMds = await getResourcesFromPasteEvent(event);
|
||||
|
||||
if (!pastedText && !pastedHtml) {
|
||||
const resourceMds = await getResourcesFromPasteEvent(event);
|
||||
if (shouldPasteResources(pastedText, pastedHtml, resourceMds)) {
|
||||
if (resourceMds.length) {
|
||||
const result = await markupToHtml.current(MarkupToHtml.MARKUP_LANGUAGE_MARKDOWN, resourceMds.join('\n'), markupRenderOptions({ bodyOnly: true }));
|
||||
editor.insertContent(result.html);
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import shouldPasteResources from './shouldPasteResources';
|
||||
|
||||
describe('shouldPasteResources', () => {
|
||||
|
||||
test.each([
|
||||
[
|
||||
'',
|
||||
'',
|
||||
[],
|
||||
true,
|
||||
],
|
||||
[
|
||||
'some text',
|
||||
'',
|
||||
[],
|
||||
false,
|
||||
],
|
||||
[
|
||||
'',
|
||||
'<b>some html<b>',
|
||||
[],
|
||||
false,
|
||||
],
|
||||
[
|
||||
'',
|
||||
'<img src="https://example.com/img.png"/>',
|
||||
[],
|
||||
false,
|
||||
],
|
||||
[
|
||||
'some text',
|
||||
'<img src="https://example.com/img.png"/>',
|
||||
[],
|
||||
false,
|
||||
],
|
||||
[
|
||||
'',
|
||||
'<img src="https://example.com/img.png"/><p>Some text</p>',
|
||||
[],
|
||||
false,
|
||||
],
|
||||
])('should tell if clipboard content should be processed as resources', (pastedText, pastedHtml, resourceMds, expected) => {
|
||||
const actual = shouldPasteResources(pastedText, pastedHtml, resourceMds);
|
||||
expect(actual).toBe(expected);
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,49 @@
|
||||
import { htmlDocIsImageOnly } from '@joplin/renderer/htmlUtils';
|
||||
import Logger from '@joplin/utils/Logger';
|
||||
|
||||
const logger = Logger.create('shouldPasteResources');
|
||||
|
||||
// We should only process the images if there is no plain text or HTML text in
|
||||
// the clipboard. This is because certain applications, such as Word, are going
|
||||
// to add multiple versions of the copied data to the clipboard - one with the
|
||||
// text formatted as HTML, and one with the text as an image. In that case, we
|
||||
// need to ignore the image and only process the HTML.
|
||||
//
|
||||
// Additional source of troubles is that when copying an image from Chrome, the
|
||||
// clipboard will contain two elements: The actual image (type=image), and an
|
||||
// HTML fragment with a link to the image. Most of the time getting the image
|
||||
// from the HTML will work... except if some authentication is required to
|
||||
// access the image. In that case we'll end up with dead link in the RTE. For
|
||||
// that reason, when there's only an image in the HTML document, we process
|
||||
// instead the clipboard resources, which will contain the actual image.
|
||||
//
|
||||
// We have a lot of log statements so that if someone reports a bug we can ask
|
||||
// them to check the console and give us the messages they have.
|
||||
export default (pastedText: string, pastedHtml: string, resourceMds: string[]) => {
|
||||
logger.info('Pasted text:', pastedText);
|
||||
logger.info('Pasted HTML:', pastedHtml);
|
||||
logger.info('Resources:', resourceMds);
|
||||
|
||||
if (pastedText) {
|
||||
logger.info('Not pasting resources because the clipboard contains plain text');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pastedHtml) {
|
||||
if (!htmlDocIsImageOnly(pastedHtml)) {
|
||||
logger.info('Not pasting resources because the clipboard contains HTML, which contains more than just one image');
|
||||
return false;
|
||||
} else {
|
||||
logger.info('Not pasting HTML because it only contains one image.');
|
||||
}
|
||||
|
||||
if (!resourceMds.length) {
|
||||
logger.info('Not pasting resources because there isn\'t any');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
logger.info('Pasting resources');
|
||||
|
||||
return true;
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/app-desktop",
|
||||
"version": "2.13.12",
|
||||
"version": "2.13.6",
|
||||
"description": "Joplin for Desktop",
|
||||
"main": "main.js",
|
||||
"private": true,
|
||||
@@ -117,11 +117,11 @@
|
||||
"devDependencies": {
|
||||
"@electron/rebuild": "3.3.0",
|
||||
"@joplin/tools": "~2.13",
|
||||
"@playwright/test": "1.38.1",
|
||||
"@playwright/test": "1.39.0",
|
||||
"@testing-library/react-hooks": "8.0.1",
|
||||
"@types/jest": "29.5.5",
|
||||
"@types/node": "18.18.7",
|
||||
"@types/react": "18.2.33",
|
||||
"@types/node": "18.18.8",
|
||||
"@types/react": "18.2.34",
|
||||
"@types/react-redux": "7.1.28",
|
||||
"@types/styled-components": "5.1.29",
|
||||
"electron": "26.5.0",
|
||||
@@ -159,7 +159,7 @@
|
||||
"electron-window-state": "5.0.3",
|
||||
"formatcoords": "1.1.3",
|
||||
"fs-extra": "11.1.1",
|
||||
"highlight.js": "11.8.0",
|
||||
"highlight.js": "11.9.0",
|
||||
"immer": "7.0.15",
|
||||
"keytar": "7.9.0",
|
||||
"mark.js": "8.11.1",
|
||||
|
||||
@@ -110,8 +110,8 @@ android {
|
||||
applicationId "net.cozic.joplin"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 2097730
|
||||
versionName "2.13.10"
|
||||
versionCode 2097727
|
||||
versionName "2.13.7"
|
||||
ndk {
|
||||
abiFilters "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
|
||||
}
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
const React = require('react');
|
||||
import { useState, useCallback, useMemo } from 'react';
|
||||
|
||||
const Icon = require('react-native-vector-icons/Ionicons').default;
|
||||
import { FAB, Portal } from 'react-native-paper';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import { Dispatch } from 'redux';
|
||||
const Icon = require('react-native-vector-icons/Ionicons').default;
|
||||
|
||||
// eslint-disable-next-line no-undef -- Don't know why it says React is undefined when it's defined above
|
||||
type FABGroupProps = React.ComponentProps<typeof FAB.Group>;
|
||||
|
||||
type OnButtonPress = ()=> void;
|
||||
interface ButtonSpec {
|
||||
@@ -21,7 +19,6 @@ interface ActionButtonProps {
|
||||
|
||||
// If not given, an "add" button will be used.
|
||||
mainButton?: ButtonSpec;
|
||||
dispatch: Dispatch;
|
||||
}
|
||||
|
||||
const defaultOnPress = () => {};
|
||||
@@ -39,12 +36,10 @@ const useIcon = (iconName: string) => {
|
||||
|
||||
const ActionButton = (props: ActionButtonProps) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const onMenuToggled: FABGroupProps['onStateChange'] = useCallback(state => {
|
||||
props.dispatch({
|
||||
type: 'SIDE_MENU_CLOSE',
|
||||
});
|
||||
setOpen(state.open);
|
||||
}, [setOpen, props.dispatch]);
|
||||
const onMenuToggled = useCallback(
|
||||
(state: { open: boolean }) => setOpen(state.open)
|
||||
, [setOpen]);
|
||||
|
||||
|
||||
const actions = useMemo(() => (props.buttons ?? []).map(button => {
|
||||
return {
|
||||
|
||||
@@ -124,6 +124,7 @@ export const createJsDrawEditor = (
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
if (!resourceUrl) {
|
||||
resolve('');
|
||||
return;
|
||||
}
|
||||
|
||||
// fetch seems to be unable to request file:// URLs.
|
||||
@@ -156,6 +157,10 @@ export const createJsDrawEditor = (
|
||||
// Load from a template if no initial data
|
||||
if (svgData === '') {
|
||||
await applyTemplateToEditor(editor, templateData);
|
||||
|
||||
// The editor expects to be saved initially (without
|
||||
// unsaved changes). Save now.
|
||||
saveNow();
|
||||
} else {
|
||||
await editor.loadFromSVG(svgData);
|
||||
}
|
||||
|
||||
@@ -270,7 +270,6 @@ function NoteEditor(props: Props, ref: any) {
|
||||
|
||||
const setInitialSelectionJS = props.initialSelection ? `
|
||||
cm.select(${props.initialSelection.start}, ${props.initialSelection.end});
|
||||
cm.execCommand('scrollSelectionIntoView');
|
||||
` : '';
|
||||
|
||||
const editorSettings: EditorSettings = {
|
||||
@@ -332,7 +331,6 @@ function NoteEditor(props: Props, ref: any) {
|
||||
const settings = ${JSON.stringify(editorSettings)};
|
||||
|
||||
cm = codeMirrorBundle.initCodeMirror(parentElement, initialText, settings);
|
||||
|
||||
${setInitialSelectionJS}
|
||||
|
||||
window.onresize = () => {
|
||||
|
||||
@@ -40,7 +40,9 @@ interface ActionButtonProps {
|
||||
onPress: Callback;
|
||||
}
|
||||
|
||||
const ActionButton = (props: ActionButtonProps) => {
|
||||
const ActionButton = (
|
||||
props: ActionButtonProps,
|
||||
) => {
|
||||
return (
|
||||
<CustomButton
|
||||
themeId={props.themeId}
|
||||
|
||||
@@ -10,7 +10,6 @@ import NoteEditor from '../NoteEditor/NoteEditor';
|
||||
const FileViewer = require('react-native-file-viewer').default;
|
||||
const React = require('react');
|
||||
const { Keyboard, View, TextInput, StyleSheet, Linking, Image, Share } = require('react-native');
|
||||
import type { NativeSyntheticEvent } from 'react-native';
|
||||
import { Platform, PermissionsAndroid } from 'react-native';
|
||||
const { connect } = require('react-redux');
|
||||
// const { MarkdownEditor } = require('@joplin/lib/../MarkdownEditor/index.js');
|
||||
@@ -51,9 +50,8 @@ import isEditableResource from '../NoteEditor/ImageEditor/isEditableResource';
|
||||
import VoiceTypingDialog from '../voiceTyping/VoiceTypingDialog';
|
||||
import { voskEnabled } from '../../services/voiceTyping/vosk';
|
||||
import { isSupportedLanguage } from '../../services/voiceTyping/vosk.android';
|
||||
import { ChangeEvent as EditorChangeEvent, SelectionRangeChangeEvent, UndoRedoDepthChangeEvent } from '@joplin/editor/events';
|
||||
import { ChangeEvent as EditorChangeEvent, UndoRedoDepthChangeEvent } from '@joplin/editor/events';
|
||||
import { join } from 'path';
|
||||
import { SelectionRange } from '../NoteEditor/types';
|
||||
const urlUtils = require('@joplin/lib/urlUtils');
|
||||
|
||||
// import Vosk from 'react-native-vosk';
|
||||
@@ -66,7 +64,6 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
// This isn't in this.state because we don't want changing scroll to trigger
|
||||
// a re-render.
|
||||
private lastBodyScroll: number|undefined = undefined;
|
||||
private selection: SelectionRange;
|
||||
|
||||
public static navigationOptions(): any {
|
||||
return { header: null };
|
||||
@@ -254,6 +251,7 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
this.undoRedoService_stackChange = this.undoRedoService_stackChange.bind(this);
|
||||
this.screenHeader_undoButtonPress = this.screenHeader_undoButtonPress.bind(this);
|
||||
this.screenHeader_redoButtonPress = this.screenHeader_redoButtonPress.bind(this);
|
||||
this.body_selectionChange = this.body_selectionChange.bind(this);
|
||||
this.onBodyViewerLoadEnd = this.onBodyViewerLoadEnd.bind(this);
|
||||
this.onBodyViewerCheckboxChange = this.onBodyViewerCheckboxChange.bind(this);
|
||||
this.onBodyChange = this.onBodyChange.bind(this);
|
||||
@@ -522,13 +520,13 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
this.scheduleSave();
|
||||
}
|
||||
|
||||
private onPlainEdtiorSelectionChange = (event: NativeSyntheticEvent<any>) => {
|
||||
this.selection = event.nativeEvent.selection;
|
||||
};
|
||||
|
||||
private onMarkdownEditorSelectionChange = (event: SelectionRangeChangeEvent) => {
|
||||
this.selection = { start: event.from, end: event.to };
|
||||
};
|
||||
private body_selectionChange(event: any) {
|
||||
if (this.useEditorBeta()) {
|
||||
this.selection = event.selection;
|
||||
} else {
|
||||
this.selection = event.nativeEvent.selection;
|
||||
}
|
||||
}
|
||||
|
||||
public makeSaveAction() {
|
||||
return async () => {
|
||||
@@ -751,11 +749,7 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
if (this.useEditorBeta()) {
|
||||
// The beta editor needs to be explicitly informed of changes
|
||||
// to the note's body
|
||||
if (this.editorRef.current) {
|
||||
this.editorRef.current.insertText(newText);
|
||||
} else {
|
||||
logger.error(`Tried to attach resource ${resource.id} to the note when the editor is not visible!`);
|
||||
}
|
||||
this.editorRef.current.insertText(newText);
|
||||
}
|
||||
} else {
|
||||
newNote.body += `\n${resourceTag}`;
|
||||
@@ -820,34 +814,31 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
}, 'image');
|
||||
}
|
||||
|
||||
private drawPicture_onPress = async () => {
|
||||
// Create a new empty drawing and attach it now.
|
||||
const resource = await this.attachNewDrawing('');
|
||||
await this.editDrawing(resource);
|
||||
};
|
||||
|
||||
private async updateDrawing(svgData: string) {
|
||||
let resource: ResourceEntity|null = this.state.imageEditorResource;
|
||||
|
||||
if (!resource) {
|
||||
resource = await this.attachNewDrawing(svgData);
|
||||
|
||||
// Set resouce and file path to allow
|
||||
// 1. subsequent saves to update the resource
|
||||
// 2. the editor to load from the resource's filepath (can happen
|
||||
// if the webview is reloaded).
|
||||
this.setState({
|
||||
imageEditorResourceFilepath: Resource.fullPath(resource),
|
||||
imageEditorResource: resource,
|
||||
});
|
||||
} else {
|
||||
logger.info('Saving drawing to resource', resource.id);
|
||||
|
||||
const tempFilePath = join(Setting.value('tempDir'), uuid.createNano());
|
||||
await shim.fsDriver().writeFile(tempFilePath, svgData, 'utf8');
|
||||
|
||||
resource = await Resource.updateResourceBlobContent(
|
||||
resource.id,
|
||||
tempFilePath,
|
||||
);
|
||||
await shim.fsDriver().remove(tempFilePath);
|
||||
|
||||
await this.refreshResource(resource);
|
||||
throw new Error('No resource is loaded in the editor');
|
||||
}
|
||||
|
||||
logger.info('Saving drawing to resource', resource.id);
|
||||
|
||||
const tempFilePath = join(Setting.value('tempDir'), uuid.createNano());
|
||||
await shim.fsDriver().writeFile(tempFilePath, svgData, 'utf8');
|
||||
|
||||
resource = await Resource.updateResourceBlobContent(
|
||||
resource.id,
|
||||
tempFilePath,
|
||||
);
|
||||
await shim.fsDriver().remove(tempFilePath);
|
||||
|
||||
await this.refreshResource(resource);
|
||||
}
|
||||
|
||||
private onSaveDrawing = async (svgData: string) => {
|
||||
@@ -858,23 +849,6 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
this.setState({ showImageEditor: false });
|
||||
};
|
||||
|
||||
private drawPicture_onPress = async () => {
|
||||
if (this.state.mode === 'edit') {
|
||||
// Create a new empty drawing and attach it now, before the image editor is opened.
|
||||
// With the present structure of Note.tsx, the we can't use this.editorRef while
|
||||
// the image editor is open, and thus can't attach drawings at the cursor locaiton.
|
||||
const resource = await this.attachNewDrawing('');
|
||||
await this.editDrawing(resource);
|
||||
} else {
|
||||
logger.info('Showing image editor...');
|
||||
this.setState({
|
||||
showImageEditor: true,
|
||||
imageEditorResourceFilepath: null,
|
||||
imageEditorResource: null,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
private async editDrawing(item: BaseItem) {
|
||||
const filePath = Resource.fullPath(item);
|
||||
this.setState({
|
||||
@@ -1394,7 +1368,7 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
multiline={true}
|
||||
value={note.body}
|
||||
onChangeText={(text: string) => this.body_changeText(text)}
|
||||
onSelectionChange={this.onPlainEdtiorSelectionChange}
|
||||
onSelectionChange={this.body_selectionChange}
|
||||
blurOnSubmit={false}
|
||||
selectionColor={theme.textSelectionColor}
|
||||
keyboardAppearance={theme.keyboardAppearance}
|
||||
@@ -1415,7 +1389,7 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
initialText={note.body}
|
||||
initialSelection={this.selection}
|
||||
onChange={this.onBodyChange}
|
||||
onSelectionChange={this.onMarkdownEditorSelectionChange}
|
||||
onSelectionChange={this.body_selectionChange}
|
||||
onUndoRedoDepthChange={this.onUndoRedoDepthChange}
|
||||
onAttach={() => this.showAttachMenu()}
|
||||
readOnly={this.state.readOnly}
|
||||
@@ -1448,7 +1422,7 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
|
||||
if (this.state.mode === 'edit') return null;
|
||||
|
||||
return <ActionButton mainButton={editButton} dispatch={this.props.dispatch} />;
|
||||
return <ActionButton mainButton={editButton} />;
|
||||
};
|
||||
|
||||
// Save button is not really needed anymore with the improved save logic
|
||||
|
||||
@@ -16,7 +16,6 @@ const DialogBox = require('react-native-dialogbox').default;
|
||||
const { BaseScreenComponent } = require('../base-screen');
|
||||
const { BackButtonService } = require('../../services/back-button.js');
|
||||
import { AppState } from '../../utils/types';
|
||||
const { ALL_NOTES_FILTER_ID } = require('@joplin/lib/reserved-ids.js');
|
||||
|
||||
class NotesScreenComponent extends BaseScreenComponent<any> {
|
||||
|
||||
@@ -109,7 +108,7 @@ class NotesScreenComponent extends BaseScreenComponent<any> {
|
||||
}
|
||||
|
||||
public async componentDidUpdate(prevProps: any) {
|
||||
if (prevProps.notesOrder !== this.props.notesOrder || prevProps.selectedFolderId !== this.props.selectedFolderId || prevProps.selectedTagId !== this.props.selectedTagId || prevProps.selectedSmartFilterId !== this.props.selectedSmartFilterId || prevProps.notesParentType !== this.props.notesParentType || prevProps.uncompletedTodosOnTop !== this.props.uncompletedTodosOnTop || prevProps.showCompletedTodos !== this.props.showCompletedTodos) {
|
||||
if (prevProps.notesOrder !== this.props.notesOrder || prevProps.selectedFolderId !== this.props.selectedFolderId || prevProps.selectedTagId !== this.props.selectedTagId || prevProps.selectedSmartFilterId !== this.props.selectedSmartFilterId || prevProps.notesParentType !== this.props.notesParentType) {
|
||||
await this.refreshNotes(this.props);
|
||||
}
|
||||
}
|
||||
@@ -224,32 +223,17 @@ class NotesScreenComponent extends BaseScreenComponent<any> {
|
||||
let buttonFolderId = this.props.selectedFolderId !== Folder.conflictFolderId() ? this.props.selectedFolderId : null;
|
||||
if (!buttonFolderId) buttonFolderId = this.props.activeFolderId;
|
||||
|
||||
const isAllNotes =
|
||||
this.props.notesParentType === 'SmartFilter'
|
||||
&& this.props.selectedSmartFilterId === ALL_NOTES_FILTER_ID;
|
||||
|
||||
// Usually, when showing all notes, activeFolderId/selectedFolderId is set to the last
|
||||
// active folder.
|
||||
// If the app starts showing all notes, activeFolderId/selectedFolderId are
|
||||
// empty or null. As such, we need a special case to show the buttons:
|
||||
const addFolderNoteButtons = !!buttonFolderId || isAllNotes;
|
||||
const addFolderNoteButtons = !!buttonFolderId;
|
||||
const thisComp = this;
|
||||
|
||||
const makeActionButtonComp = () => {
|
||||
const getTargetFolderId = async () => {
|
||||
if (!buttonFolderId && isAllNotes) {
|
||||
return (await Folder.defaultFolder()).id;
|
||||
}
|
||||
return buttonFolderId;
|
||||
};
|
||||
if (addFolderNoteButtons && this.props.folders.length > 0) {
|
||||
const buttons = [];
|
||||
buttons.push({
|
||||
label: _('New to-do'),
|
||||
onPress: async () => {
|
||||
const folderId = await getTargetFolderId();
|
||||
onPress: () => {
|
||||
const isTodo = true;
|
||||
void this.newNoteNavigate(folderId, isTodo);
|
||||
void this.newNoteNavigate(buttonFolderId, isTodo);
|
||||
},
|
||||
color: '#9b59b6',
|
||||
icon: 'checkbox-outline',
|
||||
@@ -257,15 +241,14 @@ class NotesScreenComponent extends BaseScreenComponent<any> {
|
||||
|
||||
buttons.push({
|
||||
label: _('New note'),
|
||||
onPress: async () => {
|
||||
const folderId = await getTargetFolderId();
|
||||
onPress: () => {
|
||||
const isTodo = false;
|
||||
void this.newNoteNavigate(folderId, isTodo);
|
||||
void this.newNoteNavigate(buttonFolderId, isTodo);
|
||||
},
|
||||
color: '#9b59b6',
|
||||
icon: 'document',
|
||||
});
|
||||
return <ActionButton buttons={buttons} dispatch={this.props.dispatch}/>;
|
||||
return <ActionButton buttons={buttons}/>;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
@@ -45,9 +45,6 @@ LogBox.ignoreLogs([
|
||||
// Apparently it can be safely ignored:
|
||||
// https://github.com/react-native-webview/react-native-webview/issues/124
|
||||
'Did not receive response to shouldStartLoad in time, defaulting to YES',
|
||||
|
||||
// Emitted by react-native-popup-menu
|
||||
'MenuContext is deprecated and it might be removed in future releases, use MenuProvider instead.',
|
||||
]);
|
||||
|
||||
AppRegistry.registerComponent('Joplin', () => Root);
|
||||
|
||||
@@ -523,13 +523,13 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Joplin/Joplin.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 107;
|
||||
CURRENT_PROJECT_VERSION = 104;
|
||||
DEVELOPMENT_TEAM = A9BXAFS6CT;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Joplin/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
MARKETING_VERSION = 12.13.10;
|
||||
MARKETING_VERSION = 12.13.7;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
@@ -552,12 +552,12 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Joplin/Joplin.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 107;
|
||||
CURRENT_PROJECT_VERSION = 104;
|
||||
DEVELOPMENT_TEAM = A9BXAFS6CT;
|
||||
INFOPLIST_FILE = Joplin/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
MARKETING_VERSION = 12.13.10;
|
||||
MARKETING_VERSION = 12.13.7;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
@@ -704,14 +704,14 @@
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 107;
|
||||
CURRENT_PROJECT_VERSION = 104;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = A9BXAFS6CT;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
INFOPLIST_FILE = ShareExtension/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
MARKETING_VERSION = 12.13.10;
|
||||
MARKETING_VERSION = 12.13.7;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = net.cozic.joplin.ShareExtension;
|
||||
@@ -735,14 +735,14 @@
|
||||
CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 107;
|
||||
CURRENT_PROJECT_VERSION = 104;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = A9BXAFS6CT;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
INFOPLIST_FILE = ShareExtension/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
MARKETING_VERSION = 12.13.10;
|
||||
MARKETING_VERSION = 12.13.7;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = net.cozic.joplin.ShareExtension;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"test": "jest",
|
||||
"test-ci": "yarn test",
|
||||
"watchInjectedJs": "gulp watchInjectedJs",
|
||||
"postinstall": "jetify && yarn run build"
|
||||
"postinstall": "jetify"
|
||||
},
|
||||
"dependencies": {
|
||||
"@bam.tech/react-native-image-resizer": "3.0.7",
|
||||
@@ -28,7 +28,7 @@
|
||||
"@react-native-community/clipboard": "1.5.1",
|
||||
"@react-native-community/datetimepicker": "7.6.1",
|
||||
"@react-native-community/geolocation": "3.1.0",
|
||||
"@react-native-community/netinfo": "9.4.1",
|
||||
"@react-native-community/netinfo": "9.4.2",
|
||||
"@react-native-community/push-notification-ios": "1.11.0",
|
||||
"@react-native-community/slider": "4.4.3",
|
||||
"assert-browserify": "2.0.0",
|
||||
@@ -42,7 +42,7 @@
|
||||
"md5": "2.3.0",
|
||||
"path-browserify": "1.0.1",
|
||||
"prop-types": "15.8.1",
|
||||
"punycode": "2.3.0",
|
||||
"punycode": "2.3.1",
|
||||
"react": "18.2.0",
|
||||
"react-native": "0.71.10",
|
||||
"react-native-camera": "4.2.1",
|
||||
@@ -88,14 +88,14 @@
|
||||
"@babel/preset-env": "7.20.2",
|
||||
"@babel/runtime": "7.20.0",
|
||||
"@joplin/tools": "~2.13",
|
||||
"@js-draw/material-icons": "1.14.0",
|
||||
"@js-draw/material-icons": "1.11.2",
|
||||
"@lezer/highlight": "1.1.4",
|
||||
"@testing-library/jest-native": "5.4.3",
|
||||
"@testing-library/react-native": "12.3.1",
|
||||
"@testing-library/react-native": "12.3.2",
|
||||
"@tsconfig/react-native": "2.0.2",
|
||||
"@types/fs-extra": "11.0.3",
|
||||
"@types/jest": "29.5.5",
|
||||
"@types/react": "18.2.33",
|
||||
"@types/react": "18.2.34",
|
||||
"@types/react-native": "0.70.6",
|
||||
"@types/react-redux": "7.1.28",
|
||||
"@types/tar-stream": "2.2.3",
|
||||
@@ -106,14 +106,14 @@
|
||||
"jest": "29.7.0",
|
||||
"jest-environment-jsdom": "29.7.0",
|
||||
"jetifier": "2.0.0",
|
||||
"js-draw": "1.14.0",
|
||||
"js-draw": "1.11.2",
|
||||
"jsdom": "22.1.0",
|
||||
"metro-react-native-babel-preset": "0.73.9",
|
||||
"nodemon": "3.0.1",
|
||||
"react-test-renderer": "18.2.0",
|
||||
"sqlite3": "5.1.6",
|
||||
"ts-jest": "29.1.1",
|
||||
"ts-loader": "9.4.4",
|
||||
"ts-loader": "9.5.0",
|
||||
"ts-node": "10.9.1",
|
||||
"typescript": "5.2.2",
|
||||
"uglify-js": "3.17.4",
|
||||
|
||||
@@ -66,7 +66,7 @@ const { SearchScreen } = require('./components/screens/search.js');
|
||||
const { OneDriveLoginScreen } = require('./components/screens/onedrive-login.js');
|
||||
import EncryptionConfigScreen from './components/screens/encryption-config';
|
||||
const { DropboxLoginScreen } = require('./components/screens/dropbox-login.js');
|
||||
const { MenuContext } = require('react-native-popup-menu');
|
||||
import { MenuProvider } from 'react-native-popup-menu';
|
||||
import SideMenu from './components/SideMenu';
|
||||
import SideMenuContent from './components/side-menu-content';
|
||||
const { SideMenuContentNote } = require('./components/side-menu-content-note.js');
|
||||
@@ -317,7 +317,6 @@ const appReducer = (state = appDefaultState, action: any) => {
|
||||
|
||||
if ('smartFilterId' in action) {
|
||||
newState.smartFilterId = action.smartFilterId;
|
||||
newState.selectedSmartFilterId = action.smartFilterId;
|
||||
newState.notesParentType = 'SmartFilter';
|
||||
}
|
||||
|
||||
@@ -1089,7 +1088,7 @@ class AppComponent extends React.Component {
|
||||
}}
|
||||
>
|
||||
<StatusBar barStyle={statusBarStyle} />
|
||||
<MenuContext style={{ flex: 1 }}>
|
||||
<MenuProvider style={{ flex: 1 }}>
|
||||
<SafeAreaView style={{ flex: 0, backgroundColor: theme.backgroundColor2 }}/>
|
||||
<SafeAreaView style={{ flex: 1 }}>
|
||||
<View style={{ flex: 1, backgroundColor: theme.backgroundColor }}>
|
||||
@@ -1102,7 +1101,7 @@ class AppComponent extends React.Component {
|
||||
sensorInfo={this.state.sensorInfo}
|
||||
/> }
|
||||
</SafeAreaView>
|
||||
</MenuContext>
|
||||
</MenuProvider>
|
||||
</SideMenu>
|
||||
</View>
|
||||
);
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
"exclude": [
|
||||
//Files that don't need transpilation
|
||||
"**/node_modules",
|
||||
"**/*.test.ts",
|
||||
"**/*.test.tsx",
|
||||
"gulpfile.ts",
|
||||
"tools/*.ts",
|
||||
],
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
import { EditorSelection } from '@codemirror/state';
|
||||
import createTestEditor from '../testUtil/createTestEditor';
|
||||
import decoratorExtension from './decoratorExtension';
|
||||
|
||||
jest.retryTimes(2);
|
||||
|
||||
describe('decoratorExtension', () => {
|
||||
it('should highlight code blocks within tables', async () => {
|
||||
// Regression test for https://github.com/laurent22/joplin/issues/9477
|
||||
const editorText = `
|
||||
left | right
|
||||
--------|-------
|
||||
\`foo\` | bar
|
||||
`;
|
||||
const editor = await createTestEditor(
|
||||
editorText,
|
||||
|
||||
// Put the initial cursor at the start of "foo"
|
||||
EditorSelection.cursor(editorText.indexOf('foo')),
|
||||
|
||||
['TableRow', 'InlineCode'],
|
||||
[decoratorExtension],
|
||||
);
|
||||
|
||||
const codeBlock = editor.contentDOM.querySelector('.cm-inlineCode');
|
||||
|
||||
expect(codeBlock.textContent).toBe('`foo`');
|
||||
expect(codeBlock.parentElement.classList.contains('.cm-tableRow'));
|
||||
});
|
||||
});
|
||||
@@ -72,7 +72,7 @@ const taskMarkerDecoration = Decoration.mark({
|
||||
attributes: { class: 'cm-taskMarker' },
|
||||
});
|
||||
|
||||
type DecorationDescription = { pos: number; length: number; decoration: Decoration };
|
||||
type DecorationDescription = { pos: number; length?: number; decoration: Decoration };
|
||||
|
||||
// Returns a set of [Decoration]s, associated with block syntax groups that require
|
||||
// full-line styling.
|
||||
@@ -87,7 +87,6 @@ const computeDecorations = (view: EditorView) => {
|
||||
const line = view.state.doc.lineAt(pos);
|
||||
decorations.push({
|
||||
pos: line.from,
|
||||
length: 0,
|
||||
decoration,
|
||||
});
|
||||
|
||||
@@ -186,23 +185,13 @@ const computeDecorations = (view: EditorView) => {
|
||||
});
|
||||
}
|
||||
|
||||
// Decorations need to be sorted in ascending order first by start position,
|
||||
// then by length. Adding items to the RangeSetBuilder in an incorrect order
|
||||
// causes an exception to be thrown.
|
||||
decorations.sort((a, b) => {
|
||||
const posComparison = a.pos - b.pos;
|
||||
if (posComparison !== 0) {
|
||||
return posComparison;
|
||||
}
|
||||
|
||||
const lengthComparison = a.length - b.length;
|
||||
return lengthComparison;
|
||||
});
|
||||
decorations.sort((a, b) => a.pos - b.pos);
|
||||
|
||||
// Items need to be added to a RangeSetBuilder in ascending order
|
||||
const decorationBuilder = new RangeSetBuilder<Decoration>();
|
||||
for (const { pos, length, decoration } of decorations) {
|
||||
// Zero length => entire line
|
||||
decorationBuilder.add(pos, pos + length, decoration);
|
||||
// Null length => entire line
|
||||
decorationBuilder.add(pos, pos + (length ?? 0), decoration);
|
||||
}
|
||||
return decorationBuilder.finish();
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { markdown } from '@codemirror/lang-markdown';
|
||||
import { GFM as GithubFlavoredMarkdownExt } from '@lezer/markdown';
|
||||
import { indentUnit, syntaxTree } from '@codemirror/language';
|
||||
import { SelectionRange, EditorSelection, EditorState, Extension } from '@codemirror/state';
|
||||
import { SelectionRange, EditorSelection, EditorState } from '@codemirror/state';
|
||||
import { EditorView } from '@codemirror/view';
|
||||
import { MarkdownMathExtension } from '../markdown/markdownMathParser';
|
||||
import forceFullParse from './forceFullParse';
|
||||
@@ -10,10 +10,7 @@ import loadLangauges from './loadLanguages';
|
||||
// Creates and returns a minimal editor with markdown extensions. Waits to return the editor
|
||||
// until all syntax tree tags in `expectedSyntaxTreeTags` exist.
|
||||
const createTestEditor = async (
|
||||
initialText: string,
|
||||
initialSelection: SelectionRange,
|
||||
expectedSyntaxTreeTags: string[],
|
||||
extraExtensions: Extension[] = [],
|
||||
initialText: string, initialSelection: SelectionRange, expectedSyntaxTreeTags: string[],
|
||||
): Promise<EditorView> => {
|
||||
await loadLangauges();
|
||||
|
||||
@@ -26,7 +23,6 @@ const createTestEditor = async (
|
||||
}),
|
||||
indentUnit.of('\t'),
|
||||
EditorState.tabSize.of(4),
|
||||
extraExtensions,
|
||||
],
|
||||
});
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"@joplin/lib": "~2.13",
|
||||
"@testing-library/react-hooks": "8.0.1",
|
||||
"@types/jest": "29.5.5",
|
||||
"@types/react": "18.2.33",
|
||||
"@types/react": "18.2.34",
|
||||
"@types/react-redux": "7.1.28",
|
||||
"@types/styled-components": "5.1.29",
|
||||
"jest": "29.7.0",
|
||||
@@ -26,7 +26,7 @@
|
||||
"typescript": "5.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "6.9.2",
|
||||
"@codemirror/autocomplete": "6.10.2",
|
||||
"@codemirror/commands": "6.2.5",
|
||||
"@codemirror/lang-cpp": "6.0.2",
|
||||
"@codemirror/lang-html": "6.4.6",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@joplin/fork-htmlparser2",
|
||||
"description": "Fast & forgiving HTML/XML/RSS parser",
|
||||
"version": "4.1.50",
|
||||
"version": "4.1.49",
|
||||
"author": "Felix Boehm <me@feedic.com>",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
@@ -46,7 +46,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "29.5.5",
|
||||
"@types/node": "18.18.7",
|
||||
"@types/node": "18.18.8",
|
||||
"@typescript-eslint/eslint-plugin": "6.7.2",
|
||||
"@typescript-eslint/parser": "6.7.2",
|
||||
"coveralls": "3.1.1",
|
||||
|
||||
@@ -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.54",
|
||||
"version": "1.2.53",
|
||||
"main": "lib/sax.js",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/fork-uslug",
|
||||
"version": "1.0.15",
|
||||
"version": "1.0.14",
|
||||
"description": "A permissive slug generator that works with unicode.",
|
||||
"author": "Jeremy Selier <jerem.selier@gmail.com>",
|
||||
"publishConfig": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/htmlpack",
|
||||
"version": "2.13.4",
|
||||
"version": "2.13.3",
|
||||
"description": "Pack an HTML file and all its linked resources into a single HTML file",
|
||||
"main": "dist/index.js",
|
||||
"types": "src/index.ts",
|
||||
@@ -14,7 +14,7 @@
|
||||
"author": "Laurent Cozic",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@joplin/fork-htmlparser2": "^4.1.50",
|
||||
"@joplin/fork-htmlparser2": "^4.1.49",
|
||||
"css": "3.0.0",
|
||||
"datauri": "4.1.0",
|
||||
"fs-extra": "11.1.1",
|
||||
|
||||
@@ -237,7 +237,7 @@ export default class BaseApplication {
|
||||
notes = await Tag.notes(parentId, options);
|
||||
} else if (parentType === BaseModel.TYPE_SEARCH) {
|
||||
const search = BaseModel.byId(state.searches, parentId);
|
||||
notes = await SearchEngineUtils.notesForQuery(search.query_pattern, true);
|
||||
notes = await SearchEngineUtils.notesForQuery(search.query_pattern, true, { appendWildCards: true });
|
||||
const parsedQuery = await SearchEngine.instance().parseQuery(search.query_pattern);
|
||||
highlightedWords = SearchEngine.instance().allParsedQueryTerms(parsedQuery);
|
||||
} else if (parentType === BaseModel.TYPE_SMART_FILTER) {
|
||||
|
||||
@@ -142,28 +142,20 @@ describe('import-enex-md-gen', () => {
|
||||
expect(all[0].mime).toBe('application/zip');
|
||||
});
|
||||
|
||||
// Disabled for now because the ENEX parser has become so error-tolerant
|
||||
// that it's no longer possible to generate a note that would generate a
|
||||
// failure.
|
||||
|
||||
// it('should keep importing notes when one of them is corrupted', async () => {
|
||||
// const filePath = `${enexSampleBaseDir}/ImportTestCorrupt.enex`;
|
||||
// const errors: any[] = [];
|
||||
// const consoleSpy = jest.spyOn(console, 'warn').mockImplementation(jest.fn());
|
||||
// await importEnex('', filePath, {
|
||||
// onError: (error: any) => errors.push(error),
|
||||
// });
|
||||
// consoleSpy.mockRestore();
|
||||
// const notes:NoteEntity[] = await Note.all();
|
||||
// expect(notes.length).toBe(2);
|
||||
// expect(notes.find(n => n.title === 'Note 1')).toBeTruthy();
|
||||
// expect(notes.find(n => n.title === 'Note 3')).toBeTruthy();
|
||||
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);
|
||||
// });
|
||||
// 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);
|
||||
});
|
||||
|
||||
it('should throw an error and stop if the outer XML is invalid', async () => {
|
||||
await expectThrow(async () => importEnexFile('invalid_html.enex'));
|
||||
@@ -212,12 +204,4 @@ describe('import-enex-md-gen', () => {
|
||||
expect(resource.title).toBe('app_images/resizable/961b875f-24ac-402f-9b76-37e2d4f03a6c/house_500.jpg.png');
|
||||
});
|
||||
|
||||
it('should sanitize resource filenames with colons', async () => {
|
||||
await importEnexFile('resource_filename_with_colons.enex');
|
||||
const resource: ResourceEntity = (await Resource.all())[0];
|
||||
expect(resource.filename).toBe('08.06.2014165855');
|
||||
expect(resource.file_extension).toBe('2014165855');
|
||||
expect(resource.title).toBe('08.06.2014 16:58:55');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -1239,14 +1239,6 @@ function drawTable(table: Section) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (typeof tr === 'string') {
|
||||
// A <TABLE> tag should only have <TR> tags as direct children.
|
||||
// However certain Evernote notes can contain other random tags
|
||||
// such as empty DIVs. In that case we just skip the content.
|
||||
// See test "table_with_invalid_content.html".
|
||||
continue;
|
||||
}
|
||||
|
||||
const isHeader = tr.isHeader;
|
||||
const line = [];
|
||||
const headerLine = [];
|
||||
@@ -1254,11 +1246,6 @@ function drawTable(table: Section) {
|
||||
for (let tdIndex = 0; tdIndex < tr.lines.length; tdIndex++) {
|
||||
const td = tr.lines[tdIndex];
|
||||
|
||||
if (typeof td === 'string') {
|
||||
// Same comment as above the <TR> tags.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (flatRender) {
|
||||
line.push(BLOCK_OPEN);
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import shim from './shim';
|
||||
import { NoteEntity, ResourceEntity } from './services/database/types';
|
||||
import { enexXmlToMd } from './import-enex-md-gen';
|
||||
import { MarkupToHtml } from '@joplin/renderer';
|
||||
import { fileExtension, friendlySafeFilename, safeFileExtension } from './path-utils';
|
||||
import { fileExtension, friendlySafeFilename } from './path-utils';
|
||||
const moment = require('moment');
|
||||
const { wrapError } = require('./errorUtils');
|
||||
const { enexXmlToHtml } = require('./import-enex-html-gen.js');
|
||||
@@ -151,22 +151,18 @@ interface ExtractedNote extends NoteEntity {
|
||||
tags?: string[];
|
||||
title?: string;
|
||||
bodyXml?: string;
|
||||
// is_todo?: boolean;
|
||||
}
|
||||
|
||||
// At this point we have the resource as it's been parsed from the XML, but
|
||||
// additional processing needs to be done to get the final resource file, its
|
||||
// size, MD5, etc.
|
||||
// At this point we have the resource has it's been parsed from the XML, but additional
|
||||
// processing needs to be done to get the final resource file, its size, MD5, etc.
|
||||
async function processNoteResource(resource: ExtractedResource) {
|
||||
const handleNoDataResource = async (resource: ExtractedResource, setId: boolean) => {
|
||||
if (setId) resource.id = md5(Date.now() + Math.random());
|
||||
if (!resource.hasData) {
|
||||
// Some resources have no data, go figure, so we need a special case for this.
|
||||
resource.id = md5(Date.now() + Math.random());
|
||||
resource.size = 0;
|
||||
resource.dataFilePath = `${Setting.value('tempDir')}/${resource.id}.empty`;
|
||||
await fs.writeFile(resource.dataFilePath, '');
|
||||
};
|
||||
|
||||
if (!resource.hasData) {
|
||||
// Some resources have no data, go figure, so we need a special case for this.
|
||||
await handleNoDataResource(resource, true);
|
||||
} else {
|
||||
if (resource.dataEncoding === 'base64') {
|
||||
const decodedFilePath = `${resource.dataFilePath}.decoded`;
|
||||
@@ -180,19 +176,16 @@ async function processNoteResource(resource: ExtractedResource) {
|
||||
resource.size = stats.size;
|
||||
|
||||
if (!resource.id) {
|
||||
// If no resource ID is present, the resource ID is actually the MD5
|
||||
// of the data. This ID will match the "hash" attribute of the
|
||||
// corresponding <en-media> tag. resourceId = md5(decodedData);
|
||||
// If no resource ID is present, the resource ID is actually the MD5 of the data.
|
||||
// This ID will match the "hash" attribute of the corresponding <en-media> tag.
|
||||
// resourceId = md5(decodedData);
|
||||
resource.id = await md5File(resource.dataFilePath);
|
||||
}
|
||||
|
||||
if (!resource.id || !resource.size) {
|
||||
// Don't throw an error because it happens semi-frequently,
|
||||
// especially on notes that comes from the Evernote Web Clipper and
|
||||
// we can't do anything about it. Previously we would throw the
|
||||
// error "This resource was not added because it has no ID or no
|
||||
// content".
|
||||
await handleNoDataResource(resource, !resource.id);
|
||||
const debugTemp = { ...resource };
|
||||
debugTemp.data = debugTemp.data ? `${debugTemp.data.substr(0, 32)}...` : debugTemp.data;
|
||||
throw new Error(`This resource was not added because it has no ID or no content: ${JSON.stringify(debugTemp)}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,7 +201,7 @@ async function saveNoteResources(note: ExtractedNote) {
|
||||
delete (toSave as any).dataFilePath;
|
||||
delete (toSave as any).dataEncoding;
|
||||
delete (toSave as any).hasData;
|
||||
toSave.file_extension = resource.filename ? safeFileExtension(fileExtension(resource.filename)) : '';
|
||||
toSave.file_extension = resource.filename ? fileExtension(resource.filename) : '';
|
||||
|
||||
// ENEX resource filenames can contain slashes, which may confuse other
|
||||
// parts of the app, which expect this `filename` field to be safe.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { defaultFolderIcon, FolderEntity, FolderIcon, NoteEntity, ResourceEntity } from '../services/database/types';
|
||||
import { defaultFolderIcon, FolderEntity, FolderIcon, NoteEntity } from '../services/database/types';
|
||||
import BaseModel, { DeleteOptions } from '../BaseModel';
|
||||
import time from '../time';
|
||||
import { _ } from '../locale';
|
||||
@@ -411,21 +411,14 @@ export default class Folder extends BaseItem {
|
||||
// resume the process from the start (thus the loop) so that we deal
|
||||
// with the right note/resource associations.
|
||||
|
||||
interface Row {
|
||||
id: string;
|
||||
share_id: string;
|
||||
is_shared: number;
|
||||
resource_is_shared: number;
|
||||
}
|
||||
|
||||
for (let i = 0; i < 5; i++) {
|
||||
// Find all resources where share_id is different from parent note
|
||||
// share_id. Then update share_id on all these resources. Essentially it
|
||||
// makes it match the resource share_id to the note share_id. At the
|
||||
// same time we also process the is_shared property.
|
||||
|
||||
const rows = (await this.db().selectAll(`
|
||||
SELECT r.id, n.share_id, n.is_shared, r.is_shared as resource_is_shared
|
||||
const rows = await this.db().selectAll(`
|
||||
SELECT r.id, n.share_id, n.is_shared
|
||||
FROM note_resources nr
|
||||
LEFT JOIN resources r ON nr.resource_id = r.id
|
||||
LEFT JOIN notes n ON nr.note_id = n.id
|
||||
@@ -433,7 +426,7 @@ export default class Folder extends BaseItem {
|
||||
n.share_id != r.share_id
|
||||
OR n.is_shared != r.is_shared
|
||||
) AND nr.is_associated = 1
|
||||
`)) as Row[];
|
||||
`);
|
||||
|
||||
if (!rows.length) return;
|
||||
|
||||
@@ -441,7 +434,7 @@ export default class Folder extends BaseItem {
|
||||
|
||||
const resourceIds = rows.map(r => r.id);
|
||||
|
||||
interface NoteResourceRow {
|
||||
interface Row {
|
||||
resource_id: string;
|
||||
note_id: string;
|
||||
share_id: string;
|
||||
@@ -457,9 +450,9 @@ export default class Folder extends BaseItem {
|
||||
LEFT JOIN notes ON notes.id = note_resources.note_id
|
||||
WHERE resource_id IN ('${resourceIds.join('\',\'')}')
|
||||
AND is_associated = 1
|
||||
`) as NoteResourceRow[];
|
||||
`) as Row[];
|
||||
|
||||
const resourceIdToNotes: Record<string, NoteResourceRow[]> = {};
|
||||
const resourceIdToNotes: Record<string, Row[]> = {};
|
||||
|
||||
for (const r of noteResourceAssociations) {
|
||||
if (!resourceIdToNotes[r.resource_id]) resourceIdToNotes[r.resource_id] = [];
|
||||
@@ -503,20 +496,13 @@ export default class Folder extends BaseItem {
|
||||
} else {
|
||||
// If all is good, we can set the share_id and is_shared
|
||||
// property of the resource.
|
||||
const now = Date.now();
|
||||
for (const row of rows) {
|
||||
const resource: ResourceEntity = {
|
||||
await Resource.save({
|
||||
id: row.id,
|
||||
share_id: row.share_id || '',
|
||||
is_shared: row.is_shared,
|
||||
updated_time: now,
|
||||
};
|
||||
|
||||
if (row.is_shared !== row.resource_is_shared) {
|
||||
resource.blob_updated_time = now;
|
||||
}
|
||||
|
||||
await Resource.save(resource, { autoTimestamp: false });
|
||||
updated_time: Date.now(),
|
||||
}, { autoTimestamp: false });
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/lib",
|
||||
"version": "2.13.4",
|
||||
"version": "2.13.3",
|
||||
"description": "Joplin Core library",
|
||||
"author": "Laurent Cozic",
|
||||
"homepage": "",
|
||||
@@ -19,9 +19,9 @@
|
||||
"@types/fs-extra": "11.0.3",
|
||||
"@types/jest": "29.5.5",
|
||||
"@types/js-yaml": "4.0.8",
|
||||
"@types/node": "18.18.7",
|
||||
"@types/node": "18.18.8",
|
||||
"@types/node-rsa": "1.1.3",
|
||||
"@types/react": "18.2.33",
|
||||
"@types/react": "18.2.34",
|
||||
"@types/uuid": "9.0.6",
|
||||
"clean-html": "1.5.0",
|
||||
"jest": "29.7.0",
|
||||
@@ -31,14 +31,14 @@
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "3.296.0",
|
||||
"@aws-sdk/s3-request-presigner": "3.296.0",
|
||||
"@joplin/fork-htmlparser2": "^4.1.50",
|
||||
"@joplin/fork-sax": "^1.2.54",
|
||||
"@joplin/fork-uslug": "^1.0.15",
|
||||
"@joplin/htmlpack": "^2.13.4",
|
||||
"@joplin/renderer": "^2.13.4",
|
||||
"@joplin/turndown": "^4.0.72",
|
||||
"@joplin/turndown-plugin-gfm": "^1.0.54",
|
||||
"@joplin/utils": "^2.13.4",
|
||||
"@joplin/fork-htmlparser2": "^4.1.49",
|
||||
"@joplin/fork-sax": "^1.2.53",
|
||||
"@joplin/fork-uslug": "^1.0.14",
|
||||
"@joplin/htmlpack": "^2.13.3",
|
||||
"@joplin/renderer": "^2.13.3",
|
||||
"@joplin/turndown": "^4.0.71",
|
||||
"@joplin/turndown-plugin-gfm": "^1.0.53",
|
||||
"@joplin/utils": "^2.13.3",
|
||||
"@types/nanoid": "3.0.0",
|
||||
"async-mutex": "0.4.0",
|
||||
"base-64": "1.0.0",
|
||||
|
||||
@@ -39,9 +39,6 @@ export function isHidden(path: string) {
|
||||
return b[0] === '.';
|
||||
}
|
||||
|
||||
// Note that this function only sanitizes a file extension - it does NOT extract
|
||||
// the file extension from a filename. So the way you'd normally call this is
|
||||
// `safeFileExtension(fileExtension(filename))`
|
||||
export function safeFileExtension(e: string, maxLength: number = null) {
|
||||
// In theory the file extension can have any length but in practice Joplin
|
||||
// expects a fixed length, so we limit it to 20 which should cover most cases.
|
||||
|
||||
@@ -63,6 +63,11 @@ type RequestNote = {
|
||||
stylesheets: any;
|
||||
};
|
||||
|
||||
type FetchOptions = {
|
||||
timeout?: number;
|
||||
maxRedirects?: number;
|
||||
};
|
||||
|
||||
async function requestNoteToNote(requestNote: RequestNote): Promise<NoteEntity> {
|
||||
const output: any = {
|
||||
title: requestNote.title ? requestNote.title : '',
|
||||
@@ -184,7 +189,7 @@ async function tryToGuessExtFromMimeType(response: any, mediaPath: string) {
|
||||
return newMediaPath;
|
||||
}
|
||||
|
||||
export async function downloadMediaFile(url: string /* , allowFileProtocolImages */) {
|
||||
export async function downloadMediaFile(url: string, fetchOptions?: FetchOptions) {
|
||||
logger.info('Downloading media file', url);
|
||||
|
||||
const tempDir = Setting.value('tempDir');
|
||||
@@ -225,7 +230,7 @@ export async function downloadMediaFile(url: string /* , allowFileProtocolImages
|
||||
const localPath = fileUriToPath(url);
|
||||
await shim.fsDriver().copy(localPath, mediaPath);
|
||||
} else {
|
||||
const response = await shim.fetchBlob(url, { path: mediaPath, maxRetry: 1 });
|
||||
const response = await shim.fetchBlob(url, { path: mediaPath, maxRetry: 1, ...fetchOptions });
|
||||
|
||||
// If we could not find the file extension from the URL, try to get it
|
||||
// now based on the Content-Type header.
|
||||
@@ -238,13 +243,13 @@ export async function downloadMediaFile(url: string /* , allowFileProtocolImages
|
||||
}
|
||||
}
|
||||
|
||||
async function downloadMediaFiles(urls: string[] /* , allowFileProtocolImages:boolean */) {
|
||||
async function downloadMediaFiles(urls: string[], fetchOptions?: FetchOptions) {
|
||||
const PromisePool = require('es6-promise-pool');
|
||||
|
||||
const output: any = {};
|
||||
|
||||
const downloadOne = async (url: string) => {
|
||||
const mediaPath = await downloadMediaFile(url); // , allowFileProtocolImages);
|
||||
const mediaPath = await downloadMediaFile(url, fetchOptions); // , allowFileProtocolImages);
|
||||
if (mediaPath) output[url] = { path: mediaPath, originalUrl: url };
|
||||
};
|
||||
|
||||
@@ -369,14 +374,14 @@ async function attachImageFromDataUrl(note: any, imageDataUrl: string, cropRect:
|
||||
return await shim.attachFileToNote(note, tempFilePath);
|
||||
}
|
||||
|
||||
export const extractNoteFromHTML = async (requestNote: RequestNote, requestId: number, imageSizes: any) => {
|
||||
export const extractNoteFromHTML = async (requestNote: RequestNote, requestId: number, imageSizes: any, fetchOptions?: FetchOptions) => {
|
||||
const note = await requestNoteToNote(requestNote);
|
||||
|
||||
const mediaUrls = extractMediaUrls(note.markup_language, note.body);
|
||||
|
||||
logger.info(`Request (${requestId}): Downloading media files: ${mediaUrls.length}`);
|
||||
|
||||
const mediaFiles = await downloadMediaFiles(mediaUrls); // , allowFileProtocolImages);
|
||||
const mediaFiles = await downloadMediaFiles(mediaUrls, fetchOptions); // , allowFileProtocolImages);
|
||||
|
||||
logger.info(`Request (${requestId}): Creating resources from paths: ${Object.getOwnPropertyNames(mediaFiles).length}`);
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { ErrorBadRequest, ErrorMethodNotAllowed } from '../utils/errors';
|
||||
import requestFields from '../utils/requestFields';
|
||||
import collectionToPaginatedResults from '../utils/collectionToPaginatedResults';
|
||||
import BaseItem from '../../../models/BaseItem';
|
||||
import SearchEngineUtils from '../../searchengine/SearchEngineUtils';
|
||||
import SearchEngineUtils, { NotesForQueryOptions } from '../../searchengine/SearchEngineUtils';
|
||||
|
||||
export default async function(request: Request) {
|
||||
if (request.method !== 'GET') throw new ErrorMethodNotAllowed();
|
||||
@@ -28,7 +28,11 @@ export default async function(request: Request) {
|
||||
options.caseInsensitive = true;
|
||||
results = await ModelClass.all(options);
|
||||
} else {
|
||||
results = await SearchEngineUtils.notesForQuery(query, false, defaultLoadOptions(request, ModelType.Note));
|
||||
const options: NotesForQueryOptions = {
|
||||
...defaultLoadOptions(request, ModelType.Note),
|
||||
appendWildCards: true,
|
||||
};
|
||||
results = await SearchEngineUtils.notesForQuery(query, false, options);
|
||||
}
|
||||
|
||||
return collectionToPaginatedResults(modelType, results, request);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import Note from '../../models/Note';
|
||||
import { createFolderTree, encryptionService, loadEncryptionMasterKey, msleep, resourceService, setupDatabaseAndSynchronizer, simulateReadOnlyShareEnv, supportDir, switchClient, synchronizerStart } from '../../testing/test-utils';
|
||||
import { createFolderTree, encryptionService, loadEncryptionMasterKey, msleep, resourceService, setupDatabaseAndSynchronizer, simulateReadOnlyShareEnv, supportDir, switchClient } from '../../testing/test-utils';
|
||||
import ShareService from './ShareService';
|
||||
import reducer, { defaultState } from '../../reducer';
|
||||
import { createStore } from 'redux';
|
||||
import { NoteEntity, ResourceEntity } from '../database/types';
|
||||
import { NoteEntity } from '../database/types';
|
||||
import Folder from '../../models/Folder';
|
||||
import { setEncryptionEnabled, setPpk } from '../synchronizer/syncInfoUtils';
|
||||
import { generateKeyPair } from '../e2ee/ppk';
|
||||
@@ -18,7 +18,6 @@ import BaseItem from '../../models/BaseItem';
|
||||
import ResourceService from '../ResourceService';
|
||||
import Setting from '../../models/Setting';
|
||||
import { ModelType } from '../../BaseModel';
|
||||
import { remoteNotesFoldersResources } from '../../testing/test-utils-synchronizer';
|
||||
|
||||
interface TestShareFolderServiceOptions {
|
||||
master_key_id?: string;
|
||||
@@ -37,18 +36,6 @@ function mockService(api: any) {
|
||||
return service;
|
||||
}
|
||||
|
||||
const mockServiceForNoteSharing = () => {
|
||||
return mockService({
|
||||
exec: (method: string, path = '', _query: Record<string, any> = null, _body: any = null, _headers: any = null, _options: any = null): Promise<any> => {
|
||||
if (method === 'GET' && path === 'api/shares') return { items: [] } as any;
|
||||
return null;
|
||||
},
|
||||
personalizedUserContentBaseUrl(_userId: string) {
|
||||
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
describe('ShareService', () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
@@ -58,7 +45,15 @@ describe('ShareService', () => {
|
||||
|
||||
it('should not change the note user timestamps when sharing or unsharing', async () => {
|
||||
let note = await Note.save({});
|
||||
const service = mockServiceForNoteSharing();
|
||||
const service = mockService({
|
||||
exec: (method: string, path = '', _query: Record<string, any> = null, _body: any = null, _headers: any = null, _options: any = null): Promise<any> => {
|
||||
if (method === 'GET' && path === 'api/shares') return { items: [] } as any;
|
||||
return null;
|
||||
},
|
||||
personalizedUserContentBaseUrl(_userId: string) {
|
||||
|
||||
},
|
||||
});
|
||||
await msleep(1);
|
||||
await service.shareNote(note.id, false);
|
||||
|
||||
@@ -87,46 +82,6 @@ describe('ShareService', () => {
|
||||
}
|
||||
});
|
||||
|
||||
it('should not encrypt items that are shared', async () => {
|
||||
const folder = await Folder.save({});
|
||||
const note = await Note.save({ parent_id: folder.id });
|
||||
await shim.attachFileToNote(note, testImagePath);
|
||||
|
||||
const service = mockServiceForNoteSharing();
|
||||
|
||||
setEncryptionEnabled(true);
|
||||
await loadEncryptionMasterKey();
|
||||
|
||||
await synchronizerStart();
|
||||
|
||||
let previousBlobUpdatedTime = Infinity;
|
||||
{
|
||||
const allItems = await remoteNotesFoldersResources();
|
||||
expect(allItems.map(it => it.encryption_applied)).toEqual([1, 1, 1]);
|
||||
previousBlobUpdatedTime = allItems.find(it => it.type_ === ModelType.Resource).blob_updated_time;
|
||||
}
|
||||
|
||||
await service.shareNote(note.id, false);
|
||||
await msleep(1);
|
||||
await Folder.updateAllShareIds(resourceService());
|
||||
|
||||
await synchronizerStart();
|
||||
|
||||
{
|
||||
const allItems = await remoteNotesFoldersResources();
|
||||
expect(allItems.find(it => it.type_ === ModelType.Note).encryption_applied).toBe(0);
|
||||
expect(allItems.find(it => it.type_ === ModelType.Folder).encryption_applied).toBe(1);
|
||||
|
||||
const resource: ResourceEntity = allItems.find(it => it.type_ === ModelType.Resource);
|
||||
expect(resource.encryption_applied).toBe(0);
|
||||
|
||||
// Indicates that both the metadata and blob have been decrypted on
|
||||
// the sync target.
|
||||
expect(resource.blob_updated_time).toBe(resource.updated_time);
|
||||
expect(resource.blob_updated_time).toBeGreaterThan(previousBlobUpdatedTime);
|
||||
}
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied
|
||||
function testShareFolderService(extraExecHandlers: Record<string, Function> = {}, options: TestShareFolderServiceOptions = {}) {
|
||||
return mockService({
|
||||
|
||||
@@ -460,6 +460,11 @@ function shimInit(options = null) {
|
||||
if (!options.method) options.method = 'GET';
|
||||
// if (!('maxRetry' in options)) options.maxRetry = 5;
|
||||
|
||||
// 21 maxRedirects is the default amount from follow-redirects library
|
||||
// 20 seems to be the max amount that most popular browsers will allow
|
||||
if (!options.maxRedirects) options.maxRedirects = 21;
|
||||
if (!options.timeout) options.timeout = undefined;
|
||||
|
||||
const urlParse = require('url').parse;
|
||||
|
||||
url = urlParse(url.trim());
|
||||
@@ -490,6 +495,8 @@ function shimInit(options = null) {
|
||||
method: method,
|
||||
path: url.pathname + (url.query ? `?${url.query}` : ''),
|
||||
headers: headers,
|
||||
timeout: options.timeout,
|
||||
maxRedirects: options.maxRedirects,
|
||||
};
|
||||
|
||||
const resolvedProxyUrl = resolveProxyUrl(proxySettings.proxyUrl);
|
||||
@@ -551,6 +558,10 @@ function shimInit(options = null) {
|
||||
});
|
||||
});
|
||||
|
||||
request.on('timeout', () => {
|
||||
request.destroy(new Error(`Request timed out. Timeout value: ${requestOptions.timeout}ms.`));
|
||||
});
|
||||
|
||||
request.on('error', (error) => {
|
||||
cleanUpOnError(error);
|
||||
});
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
"devDependencies": {
|
||||
"@types/jest": "29.5.5",
|
||||
"@types/pdfjs-dist": "2.10.378",
|
||||
"@types/react": "18.2.33",
|
||||
"@types/react": "18.2.34",
|
||||
"@types/react-dom": "18.2.14",
|
||||
"@types/styled-components": "5.1.29",
|
||||
"babel-jest": "29.7.0",
|
||||
@@ -30,7 +30,7 @@
|
||||
"jest-environment-jsdom": "29.7.0",
|
||||
"style-loader": "3.3.3",
|
||||
"ts-jest": "29.1.1",
|
||||
"ts-loader": "9.4.4",
|
||||
"ts-loader": "9.5.0",
|
||||
"typescript": "5.2.2",
|
||||
"webpack": "5.74.0",
|
||||
"webpack-cli": "4.10.0"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/plugin-repo-cli",
|
||||
"version": "2.13.4",
|
||||
"version": "2.13.3",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"bin": "./dist/index.js",
|
||||
@@ -18,9 +18,9 @@
|
||||
"author": "",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@joplin/lib": "^2.13.4",
|
||||
"@joplin/tools": "^2.13.4",
|
||||
"@joplin/utils": "^2.13.4",
|
||||
"@joplin/lib": "^2.13.3",
|
||||
"@joplin/tools": "^2.13.3",
|
||||
"@joplin/utils": "^2.13.3",
|
||||
"fs-extra": "11.1.1",
|
||||
"gh-release-assets": "2.0.1",
|
||||
"node-fetch": "2.6.7",
|
||||
@@ -30,7 +30,7 @@
|
||||
"devDependencies": {
|
||||
"@types/fs-extra": "11.0.3",
|
||||
"@types/jest": "29.5.5",
|
||||
"@types/node": "18.18.7",
|
||||
"@types/node": "18.18.8",
|
||||
"jest": "29.7.0",
|
||||
"source-map-loader": "4.0.1",
|
||||
"typescript": "5.2.2",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/react-native-saf-x",
|
||||
"version": "2.13.4",
|
||||
"version": "2.13.3",
|
||||
"description": "a module to help work with scoped storages on android easily",
|
||||
"main": "src/index",
|
||||
"react-native": "src/index",
|
||||
|
||||
@@ -43,22 +43,12 @@ function stringifyKatexOptions(options: any) {
|
||||
// \prob: {tokens: Array(12), numArgs: 1}
|
||||
// \expval: {tokens: Array(14), numArgs: 2}
|
||||
// \wf: {tokens: Array(6), numArgs: 0}
|
||||
// \@eqnsw: "1"
|
||||
//
|
||||
// Additionally, some KaTeX macros don't follow this general format. For example
|
||||
// \@eqnsw: "1"
|
||||
// is created by \begin{align}...\end{align} environments, and doesn't have a "tokens" property.
|
||||
|
||||
if (options.macros) {
|
||||
const toSerialize: any = {};
|
||||
for (const k of Object.keys(options.macros)) {
|
||||
const macro = options.macros[k];
|
||||
if (typeof macro === 'string') {
|
||||
toSerialize[k] = `${macro}_string`;
|
||||
} else {
|
||||
const macroText: string[] = macro.tokens.map((t: any) => t.text);
|
||||
toSerialize[k] = `${macroText.join('')}_${macro.numArgs}`;
|
||||
}
|
||||
const macroText: string[] = options.macros[k].tokens.map((t: any) => t.text);
|
||||
toSerialize[k] = `${macroText.join('')}_${options.macros[k].numArgs}`;
|
||||
}
|
||||
newOptions.macros = toSerialize;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import htmlUtils, { extractHtmlBody } from './htmlUtils';
|
||||
import htmlUtils, { extractHtmlBody, htmlDocIsImageOnly } from './htmlUtils';
|
||||
|
||||
describe('htmlUtils', () => {
|
||||
|
||||
@@ -51,4 +51,39 @@ describe('htmlUtils', () => {
|
||||
}
|
||||
});
|
||||
|
||||
test('should tell if an HTML document is an image only', () => {
|
||||
const testCases: [string, boolean][] = [
|
||||
[
|
||||
// This is the kind of HTML that's pasted when copying an image from Chrome
|
||||
'<meta charset=\'utf-8\'>\n<img src="https://example.com/img.png"/>',
|
||||
true,
|
||||
],
|
||||
[
|
||||
'',
|
||||
false,
|
||||
],
|
||||
[
|
||||
'<img src="https://example.com/img.png"/>',
|
||||
true,
|
||||
],
|
||||
[
|
||||
'<img src="https://example.com/img.png"/><img src="https://example.com/img.png"/>',
|
||||
false,
|
||||
],
|
||||
[
|
||||
'<img src="https://example.com/img.png"/><p>Some text</p>',
|
||||
false,
|
||||
],
|
||||
[
|
||||
'<img src="https://example.com/img.png"/> Some text',
|
||||
false,
|
||||
],
|
||||
];
|
||||
|
||||
for (const [input, expected] of testCases) {
|
||||
const actual = htmlDocIsImageOnly(input);
|
||||
expect(actual).toBe(expected);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -404,4 +404,33 @@ export const extractHtmlBody = (html: string) => {
|
||||
return bodyFound ? output.join('') : html;
|
||||
};
|
||||
|
||||
export const htmlDocIsImageOnly = (html: string) => {
|
||||
let imageCount = 0;
|
||||
let nonImageFound = false;
|
||||
let textFound = false;
|
||||
|
||||
const parser = new htmlparser2.Parser({
|
||||
|
||||
onopentag: (name: string) => {
|
||||
if (name === 'img') {
|
||||
imageCount++;
|
||||
} else if (['meta'].includes(name)) {
|
||||
// We allow these tags since they don't print anything
|
||||
} else {
|
||||
nonImageFound = true;
|
||||
}
|
||||
},
|
||||
|
||||
ontext: (text: string) => {
|
||||
if (text.trim()) textFound = true;
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
parser.write(html);
|
||||
parser.end();
|
||||
|
||||
return imageCount === 1 && !nonImageFound && !textFound;
|
||||
};
|
||||
|
||||
export default new HtmlUtils();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/renderer",
|
||||
"version": "2.13.4",
|
||||
"version": "2.13.3",
|
||||
"description": "The Joplin note renderer, used the mobile and desktop application",
|
||||
"repository": "https://github.com/laurent22/joplin/tree/dev/packages/renderer",
|
||||
"main": "index.js",
|
||||
@@ -21,19 +21,19 @@
|
||||
"devDependencies": {
|
||||
"@types/jest": "29.5.5",
|
||||
"@types/markdown-it": "13.0.5",
|
||||
"@types/node": "18.18.7",
|
||||
"@types/node": "18.18.8",
|
||||
"jest": "29.7.0",
|
||||
"jest-environment-jsdom": "29.7.0",
|
||||
"ts-jest": "29.1.1",
|
||||
"typescript": "5.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@joplin/fork-htmlparser2": "^4.1.50",
|
||||
"@joplin/fork-uslug": "^1.0.15",
|
||||
"@joplin/utils": "^2.13.4",
|
||||
"@joplin/fork-htmlparser2": "^4.1.49",
|
||||
"@joplin/fork-uslug": "^1.0.14",
|
||||
"@joplin/utils": "^2.13.3",
|
||||
"font-awesome-filetypes": "2.1.0",
|
||||
"fs-extra": "11.1.1",
|
||||
"highlight.js": "11.8.0",
|
||||
"highlight.js": "11.9.0",
|
||||
"html-entities": "1.4.0",
|
||||
"json-stringify-safe": "5.0.1",
|
||||
"katex": "0.16.9",
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
"**/*.tsx",
|
||||
],
|
||||
"exclude": [
|
||||
"**/node_modules",
|
||||
"**/*.test.ts",
|
||||
"**/node_modules"
|
||||
],
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/server",
|
||||
"version": "2.13.4",
|
||||
"version": "2.13.5",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start-dev": "yarn run build && JOPLIN_IS_TESTING=1 nodemon --config nodemon.json --ext ts,js,mustache,css,tsx dist/app.js --env dev",
|
||||
@@ -40,7 +40,7 @@
|
||||
"jquery": "3.7.1",
|
||||
"knex": "2.5.1",
|
||||
"koa": "2.14.2",
|
||||
"ldapts": "7.0.5",
|
||||
"ldapts": "7.0.6",
|
||||
"markdown-it": "13.0.2",
|
||||
"mustache": "4.2.0",
|
||||
"nanoid": "2.1.11",
|
||||
@@ -52,7 +52,7 @@
|
||||
"pretty-bytes": "5.6.0",
|
||||
"prettycron": "0.10.0",
|
||||
"query-string": "7.1.3",
|
||||
"rate-limiter-flexible": "2.4.2",
|
||||
"rate-limiter-flexible": "3.0.3",
|
||||
"raw-body": "2.5.2",
|
||||
"sqlite3": "5.1.6",
|
||||
"stripe": "8.222.0",
|
||||
|
||||
@@ -178,6 +178,14 @@ describe('ChangeModel', () => {
|
||||
expect(changeCount).toBe(SqliteMaxVariableNum);
|
||||
});
|
||||
|
||||
test('should tell if there are more changes', async () => {
|
||||
const { user } = await createUserAndSession(1, true);
|
||||
await models().item().makeTestItems(user.id, 500);
|
||||
|
||||
const result = await models().change().delta(user.id, { limit: 100 });
|
||||
expect(result.has_more).toBe(true);
|
||||
});
|
||||
|
||||
test('should delete old changes', async () => {
|
||||
// Create the following events:
|
||||
//
|
||||
|
||||
@@ -139,8 +139,6 @@ export default class ChangeModel extends BaseModel<Change> {
|
||||
// as the `changes` table grew. So it is now split into two queries
|
||||
// merged by a UNION ALL.
|
||||
|
||||
const subQueryLimit = Math.ceil(limit / 2);
|
||||
|
||||
const fields = [
|
||||
'id',
|
||||
'item_id',
|
||||
@@ -169,7 +167,7 @@ export default class ChangeModel extends BaseModel<Change> {
|
||||
userId,
|
||||
];
|
||||
|
||||
if (!doCountQuery) subParams1.push(subQueryLimit);
|
||||
if (!doCountQuery) subParams1.push(limit);
|
||||
|
||||
const subQuery2 = `
|
||||
SELECT ${fieldsSql}
|
||||
@@ -187,7 +185,7 @@ export default class ChangeModel extends BaseModel<Change> {
|
||||
userId,
|
||||
];
|
||||
|
||||
if (!doCountQuery) subParams2.push(subQueryLimit);
|
||||
if (!doCountQuery) subParams2.push(limit);
|
||||
|
||||
let query: Knex.Raw<any> = null;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/tools",
|
||||
"version": "2.13.4",
|
||||
"version": "2.13.3",
|
||||
"description": "Various tools for Joplin",
|
||||
"main": "index.js",
|
||||
"author": "Laurent Cozic",
|
||||
@@ -20,9 +20,9 @@
|
||||
},
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@joplin/lib": "^2.13.4",
|
||||
"@joplin/renderer": "^2.13.4",
|
||||
"@joplin/utils": "^2.13.4",
|
||||
"@joplin/lib": "^2.13.3",
|
||||
"@joplin/renderer": "^2.13.3",
|
||||
"@joplin/utils": "^2.13.3",
|
||||
"compare-versions": "6.1.0",
|
||||
"dayjs": "1.11.10",
|
||||
"execa": "4.1.0",
|
||||
@@ -43,15 +43,15 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docusaurus/plugin-sitemap": "2.4.3",
|
||||
"@joplin/fork-htmlparser2": "^4.1.50",
|
||||
"@joplin/fork-htmlparser2": "^4.1.49",
|
||||
"@rmp135/sql-ts": "1.18.0",
|
||||
"@types/fs-extra": "11.0.3",
|
||||
"@types/jest": "29.5.5",
|
||||
"@types/js-yaml": "4.0.8",
|
||||
"@types/markdown-it": "13.0.5",
|
||||
"@types/mustache": "4.2.4",
|
||||
"@types/node": "18.18.7",
|
||||
"@types/node-fetch": "2.6.7",
|
||||
"@types/node": "18.18.8",
|
||||
"@types/node-fetch": "2.6.8",
|
||||
"@types/yargs": "17.0.29",
|
||||
"gettext-extractor": "3.8.0",
|
||||
"gulp": "4.0.2",
|
||||
@@ -61,7 +61,7 @@
|
||||
"rss": "1.2.2",
|
||||
"sass": "1.69.5",
|
||||
"sqlite3": "5.1.6",
|
||||
"style-to-js": "1.1.8",
|
||||
"style-to-js": "1.1.9",
|
||||
"typescript": "5.2.2"
|
||||
},
|
||||
"gitHead": "05a29b450962bf05a8642bbd39446a1f679a96ba"
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"processedReleases":{"v2.13.1":true,"v2.13.2":true,"v2.13.3":true,"v2.13.4":true,"v2.13.5":true}}
|
||||
{"processedReleases":{"v2.13.1":true,"v2.13.2":true,"v2.13.3":true,"v2.13.4":true,"v2.13.5":true,"v2.13.6":true}}
|
||||
@@ -4,7 +4,7 @@
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"version": "1.0.54",
|
||||
"version": "1.0.53",
|
||||
"author": "Dom Christie",
|
||||
"main": "lib/turndown-plugin-gfm.cjs.js",
|
||||
"devDependencies": {
|
||||
|
||||
@@ -74,8 +74,8 @@ rules.tableRow = {
|
||||
rules.table = {
|
||||
// Only convert tables that can result in valid Markdown
|
||||
// Other tables are kept as HTML using `keep` (see below).
|
||||
filter: function (node, options) {
|
||||
return node.nodeName === 'TABLE' && !tableShouldBeHtml(node, options);
|
||||
filter: function (node) {
|
||||
return node.nodeName === 'TABLE' && !tableShouldBeHtml(node);
|
||||
},
|
||||
|
||||
replacement: function (content, node) {
|
||||
@@ -174,7 +174,7 @@ const nodeContains = (node, types) => {
|
||||
return false;
|
||||
}
|
||||
|
||||
const tableShouldBeHtml = (tableNode, options) => {
|
||||
const tableShouldBeHtml = (tableNode, preserveNestedTables) => {
|
||||
const possibleTags = [
|
||||
'UL',
|
||||
'OL',
|
||||
@@ -193,7 +193,7 @@ const tableShouldBeHtml = (tableNode, options) => {
|
||||
// that's made of HTML tables. In that case we have this logic of removing the
|
||||
// outer table and keeping only the inner ones. For the Rich Text editor
|
||||
// however we always want to keep nested tables.
|
||||
if (options.preserveNestedTables) possibleTags.push('TABLE');
|
||||
if (preserveNestedTables) possibleTags.push('TABLE');
|
||||
|
||||
return nodeContains(tableNode, 'code') ||
|
||||
nodeContains(tableNode, possibleTags);
|
||||
@@ -249,7 +249,7 @@ export default function tables (turndownService) {
|
||||
isCodeBlock_ = turndownService.isCodeBlock;
|
||||
|
||||
turndownService.keep(function (node) {
|
||||
if (node.nodeName === 'TABLE' && tableShouldBeHtml(node, turndownService.options)) return true;
|
||||
if (node.nodeName === 'TABLE' && tableShouldBeHtml(node, turndownService.options.preserveNestedTables)) return true;
|
||||
return false;
|
||||
});
|
||||
for (var key in rules) turndownService.addRule(key, rules[key])
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@joplin/turndown",
|
||||
"description": "A library that converts HTML to Markdown",
|
||||
"version": "4.0.72",
|
||||
"version": "4.0.71",
|
||||
"author": "Dom Christie",
|
||||
"main": "lib/turndown.cjs.js",
|
||||
"publishConfig": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/utils",
|
||||
"version": "2.13.4",
|
||||
"version": "2.13.3",
|
||||
"description": "Utilities for Joplin",
|
||||
"repository": "https://github.com/laurent22/joplin/tree/dev/packages/utils",
|
||||
"exports": {
|
||||
@@ -38,7 +38,7 @@
|
||||
"devDependencies": {
|
||||
"@types/fs-extra": "11.0.3",
|
||||
"@types/jest": "29.5.5",
|
||||
"@types/node-fetch": "2.6.7",
|
||||
"@types/node-fetch": "2.6.8",
|
||||
"jest": "29.7.0",
|
||||
"ts-jest": "29.1.1"
|
||||
},
|
||||
|
||||
@@ -1,20 +1,5 @@
|
||||
# Joplin Android Changelog
|
||||
|
||||
## [android-v2.13.10](https://github.com/laurent22/joplin/releases/tag/android-v2.13.10) (Pre-release) - 2023-12-01T11:16:17Z
|
||||
|
||||
- Improved: Drawing: Revert recent changes to input system (#9426) (#9427 by Henry Heino)
|
||||
|
||||
## [android-v2.13.9](https://github.com/laurent22/joplin/releases/tag/android-v2.13.9) (Pre-release) - 2023-11-30T17:55:54Z
|
||||
|
||||
- Improved: Don't attach empty drawings when a user exits without saving (#9386) (#9377 by Henry Heino)
|
||||
- Fixed: Fix tooltips don't disappear on some devices (upgrade to js-draw 1.13.2) (#9401) (#9374 by Henry Heino)
|
||||
|
||||
## [android-v2.13.8](https://github.com/laurent22/joplin/releases/tag/android-v2.13.8) (Pre-release) - 2023-11-26T12:37:00Z
|
||||
|
||||
- Fixed: Fix to-dos options toggle don't toggle a rerender (#9364) (#9361 by [@pedr](https://github.com/pedr))
|
||||
- Fixed: Fix new note/to-do buttons not visible on app startup in some cases (#9329) (#9328 by Henry Heino)
|
||||
- Fixed: Sidebar is not dismissed when creating a note (#9376)
|
||||
|
||||
## [android-v2.13.7](https://github.com/laurent22/joplin/releases/tag/android-v2.13.7) (Pre-release) - 2023-11-16T13:17:53Z
|
||||
|
||||
- Improved: Add more space between settings title and description (#9270) (#9258 by Henry Heino)
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
# Joplin Terminal App Changelog
|
||||
|
||||
## [cli-v2.13.2](https://github.com/laurent22/joplin/releases/tag/cli-v2.13.2) - 2023-11-30T18:11:38Z
|
||||
|
||||
- Improved: Updated packages mermaid (v10.5.1), sass (v1.69.5)
|
||||
- Fixed: Import of inter-linked md files has incorrect notebook structure (#9269) (#9151 by [@pedr](https://github.com/pedr))
|
||||
- Fixed: Work around WebDAV sync issues over ipv6 (#9286) (#8788 by Henry Heino)
|
||||
|
||||
## [cli-v2.13.1](https://github.com/laurent22/joplin/releases/tag/cli-v2.13.1) - 2023-11-09T20:08:17Z
|
||||
|
||||
- Improved: Allow modifying a resource metadata only when synchronising (#9114)
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
# Joplin Desktop Changelog
|
||||
|
||||
## [v2.13.6](https://github.com/laurent22/joplin/releases/tag/v2.13.6) (Pre-release) - 2023-11-17T19:24:03Z
|
||||
|
||||
- Improved: Improve toolbar button wrapping on RTE ([ccf1c8e](https://github.com/laurent22/joplin/commit/ccf1c8e))
|
||||
- Improved: Install script: Work around unprivileged user namespace restrictions by adding the --no-sandbox flag to the launcher ([#9137](https://github.com/laurent22/joplin/issues/9137)) ([#9136](https://github.com/laurent22/joplin/issues/9136) by Henry Heino)
|
||||
- Improved: Make settings tabs focusable by keyboard ([#9253](https://github.com/laurent22/joplin/issues/9253)) ([#9250](https://github.com/laurent22/joplin/issues/9250) by Henry Heino)
|
||||
- Improved: Preserve nested tables in RTE ([#9293](https://github.com/laurent22/joplin/issues/9293))
|
||||
- Improved: Updated packages mermaid (v10.5.1), sass (v1.69.5)
|
||||
- Fixed: Fixed import error report ([6211606](https://github.com/laurent22/joplin/commit/6211606))
|
||||
- Fixed: Import of inter-linked md files has incorrect notebook structure ([#9269](https://github.com/laurent22/joplin/issues/9269)) ([#9151](https://github.com/laurent22/joplin/issues/9151) by [@pedr](https://github.com/pedr))
|
||||
- Fixed: Work around WebDAV sync issues over ipv6 ([#9286](https://github.com/laurent22/joplin/issues/9286)) ([#8788](https://github.com/laurent22/joplin/issues/8788) by Henry Heino)
|
||||
|
||||
## [v2.13.5](https://github.com/laurent22/joplin/releases/tag/v2.13.5) (Pre-release) - 2023-11-09T20:24:09Z
|
||||
|
||||
- New: Plugins: Add support for getting plugin settings from a Markdown renderer ([8be22ed](https://github.com/laurent22/joplin/commit/8be22ed))
|
||||
|
||||
@@ -1,20 +1,5 @@
|
||||
# Joplin iOS Changelog
|
||||
|
||||
## [ios-v12.13.10](https://github.com/laurent22/joplin/releases/tag/ios-v12.13.10) - 2023-12-01T12:07:57Z
|
||||
|
||||
- Improved: Drawing: Revert recent changes to input system (#9426) (#9427 by Henry Heino)
|
||||
|
||||
## [ios-v12.13.9](https://github.com/laurent22/joplin/releases/tag/ios-v12.13.9) - 2023-11-30T17:56:37Z
|
||||
|
||||
- Improved: Don't attach empty drawings when a user exits without saving (#9386) (#9377 by Henry Heino)
|
||||
- Fixed: Fix tooltips don't disappear on some devices (upgrade to js-draw 1.13.2) (#9401) (#9374 by Henry Heino)
|
||||
|
||||
## [ios-v12.13.8](https://github.com/laurent22/joplin/releases/tag/ios-v12.13.8) - 2023-11-26T12:54:44Z
|
||||
|
||||
- Fixed: Fix to-dos options toggle don't toggle a rerender (#9364) (#9361 by [@pedr](https://github.com/pedr))
|
||||
- Fixed: Fix new note/to-do buttons not visible on app startup in some cases (#9329) (#9328 by Henry Heino)
|
||||
- Fixed: Sidebar is not dismissed when creating a note (#9376)
|
||||
|
||||
## [ios-v12.13.7](https://github.com/laurent22/joplin/releases/tag/ios-v12.13.7) - 2023-11-16T13:37:03Z
|
||||
|
||||
- Improved: Add more space between settings title and description (#9270) (#9258 by Henry Heino)
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# Joplin Server Changelog
|
||||
|
||||
## [server-v2.13.5](https://github.com/laurent22/joplin/releases/tag/server-v2.13.5) - 2023-11-19T09:33:53Z
|
||||
|
||||
- Improved: Increase number of items that are returned during sync (767bf9f)
|
||||
- Improved: Updated packages highlight.js (v11.9.0), ldapts (v7.0.6), sass (v1.69.5)
|
||||
- Fixed: Fix severe performance issue for certain delta calls (f698068)
|
||||
- Fixed: Fixed issue with sync not immediately returning all items in certain cases (87aeffa)
|
||||
|
||||
## [server-v2.13.4](https://github.com/laurent22/joplin/releases/tag/server-v2.13.4) - 2023-11-15T15:30:19Z
|
||||
|
||||
- New: Added LDAP authentication (#9150 by Marco Rombach)
|
||||
|
||||
458
yarn.lock
458
yarn.lock
@@ -3978,9 +3978,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@codemirror/autocomplete@npm:6.9.2":
|
||||
version: 6.9.2
|
||||
resolution: "@codemirror/autocomplete@npm:6.9.2"
|
||||
"@codemirror/autocomplete@npm:6.10.2":
|
||||
version: 6.10.2
|
||||
resolution: "@codemirror/autocomplete@npm:6.10.2"
|
||||
dependencies:
|
||||
"@codemirror/language": ^6.0.0
|
||||
"@codemirror/state": ^6.0.0
|
||||
@@ -3991,7 +3991,7 @@ __metadata:
|
||||
"@codemirror/state": ^6.0.0
|
||||
"@codemirror/view": ^6.0.0
|
||||
"@lezer/common": ^1.0.0
|
||||
checksum: 8bdf06c2b4eb1cd6c8a6e1df2eb5c92011fda0bc8970f9d68cc8dad8e4f9d3c243aaa3e42505252af542be8bbaf0a3ed7e23a6b7f603171077cc36845e188190
|
||||
checksum: 360cea6a87ae9c4e3c996903f636a8f47f8ea6cd44504181e69dd8ccf666bad3e8cc6d8935e0eedd8aa118fdfe86ea78f41bc15288f3a7517dbb87115e057563
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -5696,6 +5696,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@gar/promisify@npm:^1.1.3":
|
||||
version: 1.1.3
|
||||
resolution: "@gar/promisify@npm:1.1.3"
|
||||
checksum: 4059f790e2d07bf3c3ff3e0fec0daa8144fe35c1f6e0111c9921bd32106adaa97a4ab096ad7dab1e28ee6a9060083c4d1a4ada42a7f5f3f7a96b8812e2b757c1
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@github/browserslist-config@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "@github/browserslist-config@npm:1.0.0"
|
||||
@@ -6213,12 +6220,12 @@ __metadata:
|
||||
"@joplin/renderer": ~2.13
|
||||
"@joplin/tools": ~2.13
|
||||
"@joplin/utils": ~2.13
|
||||
"@playwright/test": 1.38.1
|
||||
"@playwright/test": 1.39.0
|
||||
"@testing-library/react-hooks": 8.0.1
|
||||
"@types/jest": 29.5.5
|
||||
"@types/mustache": 4.2.4
|
||||
"@types/node": 18.18.7
|
||||
"@types/react": 18.2.33
|
||||
"@types/node": 18.18.8
|
||||
"@types/react": 18.2.34
|
||||
"@types/react-redux": 7.1.28
|
||||
"@types/styled-components": 5.1.29
|
||||
async-mutex: 0.4.0
|
||||
@@ -6234,7 +6241,7 @@ __metadata:
|
||||
fs-extra: 11.1.1
|
||||
glob: 10.3.10
|
||||
gulp: 4.0.2
|
||||
highlight.js: 11.8.0
|
||||
highlight.js: 11.9.0
|
||||
immer: 7.0.15
|
||||
jest: 29.7.0
|
||||
jest-environment-jsdom: 29.7.0
|
||||
@@ -6293,20 +6300,20 @@ __metadata:
|
||||
"@joplin/renderer": ~2.13
|
||||
"@joplin/tools": ~2.13
|
||||
"@joplin/utils": ~2.13
|
||||
"@js-draw/material-icons": 1.14.0
|
||||
"@js-draw/material-icons": 1.11.2
|
||||
"@lezer/highlight": 1.1.4
|
||||
"@react-native-community/clipboard": 1.5.1
|
||||
"@react-native-community/datetimepicker": 7.6.1
|
||||
"@react-native-community/geolocation": 3.1.0
|
||||
"@react-native-community/netinfo": 9.4.1
|
||||
"@react-native-community/netinfo": 9.4.2
|
||||
"@react-native-community/push-notification-ios": 1.11.0
|
||||
"@react-native-community/slider": 4.4.3
|
||||
"@testing-library/jest-native": 5.4.3
|
||||
"@testing-library/react-native": 12.3.1
|
||||
"@testing-library/react-native": 12.3.2
|
||||
"@tsconfig/react-native": 2.0.2
|
||||
"@types/fs-extra": 11.0.3
|
||||
"@types/jest": 29.5.5
|
||||
"@types/react": 18.2.33
|
||||
"@types/react": 18.2.34
|
||||
"@types/react-native": 0.70.6
|
||||
"@types/react-redux": 7.1.28
|
||||
"@types/tar-stream": 2.2.3
|
||||
@@ -6323,7 +6330,7 @@ __metadata:
|
||||
jest: 29.7.0
|
||||
jest-environment-jsdom: 29.7.0
|
||||
jetifier: 2.0.0
|
||||
js-draw: 1.14.0
|
||||
js-draw: 1.11.2
|
||||
jsc-android: 241213.1.0
|
||||
jsdom: 22.1.0
|
||||
lodash: 4.17.21
|
||||
@@ -6332,7 +6339,7 @@ __metadata:
|
||||
nodemon: 3.0.1
|
||||
path-browserify: 1.0.1
|
||||
prop-types: 15.8.1
|
||||
punycode: 2.3.0
|
||||
punycode: 2.3.1
|
||||
react: 18.2.0
|
||||
react-native: 0.71.10
|
||||
react-native-camera: 4.2.1
|
||||
@@ -6374,7 +6381,7 @@ __metadata:
|
||||
tar-stream: 3.1.6
|
||||
timers: 0.1.1
|
||||
ts-jest: 29.1.1
|
||||
ts-loader: 9.4.4
|
||||
ts-loader: 9.5.0
|
||||
ts-node: 10.9.1
|
||||
typescript: 5.2.2
|
||||
uglify-js: 3.17.4
|
||||
@@ -6408,7 +6415,7 @@ __metadata:
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@joplin/editor@workspace:packages/editor"
|
||||
dependencies:
|
||||
"@codemirror/autocomplete": 6.9.2
|
||||
"@codemirror/autocomplete": 6.10.2
|
||||
"@codemirror/commands": 6.2.5
|
||||
"@codemirror/lang-cpp": 6.0.2
|
||||
"@codemirror/lang-html": 6.4.6
|
||||
@@ -6427,7 +6434,7 @@ __metadata:
|
||||
"@replit/codemirror-vim": 6.0.14
|
||||
"@testing-library/react-hooks": 8.0.1
|
||||
"@types/jest": 29.5.5
|
||||
"@types/react": 18.2.33
|
||||
"@types/react": 18.2.34
|
||||
"@types/react-redux": 7.1.28
|
||||
"@types/styled-components": 5.1.29
|
||||
jest: 29.7.0
|
||||
@@ -6437,12 +6444,12 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@joplin/fork-htmlparser2@^4.1.50, @joplin/fork-htmlparser2@workspace:packages/fork-htmlparser2":
|
||||
"@joplin/fork-htmlparser2@^4.1.49, @joplin/fork-htmlparser2@workspace:packages/fork-htmlparser2":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@joplin/fork-htmlparser2@workspace:packages/fork-htmlparser2"
|
||||
dependencies:
|
||||
"@types/jest": 29.5.5
|
||||
"@types/node": 18.18.7
|
||||
"@types/node": 18.18.8
|
||||
"@typescript-eslint/eslint-plugin": 6.7.2
|
||||
"@typescript-eslint/parser": 6.7.2
|
||||
coveralls: 3.1.1
|
||||
@@ -6458,7 +6465,7 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@joplin/fork-sax@^1.2.54, @joplin/fork-sax@workspace:packages/fork-sax":
|
||||
"@joplin/fork-sax@^1.2.53, @joplin/fork-sax@workspace:packages/fork-sax":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@joplin/fork-sax@workspace:packages/fork-sax"
|
||||
dependencies:
|
||||
@@ -6467,7 +6474,7 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@joplin/fork-uslug@^1.0.15, @joplin/fork-uslug@workspace:packages/fork-uslug":
|
||||
"@joplin/fork-uslug@^1.0.14, @joplin/fork-uslug@workspace:packages/fork-uslug":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@joplin/fork-uslug@workspace:packages/fork-uslug"
|
||||
dependencies:
|
||||
@@ -6477,11 +6484,11 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@joplin/htmlpack@^2.13.4, @joplin/htmlpack@workspace:packages/htmlpack":
|
||||
"@joplin/htmlpack@^2.13.3, @joplin/htmlpack@workspace:packages/htmlpack":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@joplin/htmlpack@workspace:packages/htmlpack"
|
||||
dependencies:
|
||||
"@joplin/fork-htmlparser2": ^4.1.50
|
||||
"@joplin/fork-htmlparser2": ^4.1.49
|
||||
"@types/fs-extra": 11.0.3
|
||||
css: 3.0.0
|
||||
datauri: 4.1.0
|
||||
@@ -6490,27 +6497,27 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@joplin/lib@^2.13.4, @joplin/lib@workspace:packages/lib, @joplin/lib@~2.13":
|
||||
"@joplin/lib@^2.13.3, @joplin/lib@workspace:packages/lib, @joplin/lib@~2.13":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@joplin/lib@workspace:packages/lib"
|
||||
dependencies:
|
||||
"@aws-sdk/client-s3": 3.296.0
|
||||
"@aws-sdk/s3-request-presigner": 3.296.0
|
||||
"@joplin/fork-htmlparser2": ^4.1.50
|
||||
"@joplin/fork-sax": ^1.2.54
|
||||
"@joplin/fork-uslug": ^1.0.15
|
||||
"@joplin/htmlpack": ^2.13.4
|
||||
"@joplin/renderer": ^2.13.4
|
||||
"@joplin/turndown": ^4.0.72
|
||||
"@joplin/turndown-plugin-gfm": ^1.0.54
|
||||
"@joplin/utils": ^2.13.4
|
||||
"@joplin/fork-htmlparser2": ^4.1.49
|
||||
"@joplin/fork-sax": ^1.2.53
|
||||
"@joplin/fork-uslug": ^1.0.14
|
||||
"@joplin/htmlpack": ^2.13.3
|
||||
"@joplin/renderer": ^2.13.3
|
||||
"@joplin/turndown": ^4.0.71
|
||||
"@joplin/turndown-plugin-gfm": ^1.0.53
|
||||
"@joplin/utils": ^2.13.3
|
||||
"@types/fs-extra": 11.0.3
|
||||
"@types/jest": 29.5.5
|
||||
"@types/js-yaml": 4.0.8
|
||||
"@types/nanoid": 3.0.0
|
||||
"@types/node": 18.18.7
|
||||
"@types/node": 18.18.8
|
||||
"@types/node-rsa": 1.1.3
|
||||
"@types/react": 18.2.33
|
||||
"@types/react": 18.2.34
|
||||
"@types/uuid": 9.0.6
|
||||
async-mutex: 0.4.0
|
||||
base-64: 1.0.0
|
||||
@@ -6582,7 +6589,7 @@ __metadata:
|
||||
"@joplin/lib": ~2.13
|
||||
"@types/jest": 29.5.5
|
||||
"@types/pdfjs-dist": 2.10.378
|
||||
"@types/react": 18.2.33
|
||||
"@types/react": 18.2.34
|
||||
"@types/react-dom": 18.2.14
|
||||
"@types/styled-components": 5.1.29
|
||||
async-mutex: 0.4.0
|
||||
@@ -6596,7 +6603,7 @@ __metadata:
|
||||
style-loader: 3.3.3
|
||||
styled-components: 5.3.11
|
||||
ts-jest: 29.1.1
|
||||
ts-loader: 9.4.4
|
||||
ts-loader: 9.5.0
|
||||
typescript: 5.2.2
|
||||
webpack: 5.74.0
|
||||
webpack-cli: 4.10.0
|
||||
@@ -6607,12 +6614,12 @@ __metadata:
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@joplin/plugin-repo-cli@workspace:packages/plugin-repo-cli"
|
||||
dependencies:
|
||||
"@joplin/lib": ^2.13.4
|
||||
"@joplin/tools": ^2.13.4
|
||||
"@joplin/utils": ^2.13.4
|
||||
"@joplin/lib": ^2.13.3
|
||||
"@joplin/tools": ^2.13.3
|
||||
"@joplin/utils": ^2.13.3
|
||||
"@types/fs-extra": 11.0.3
|
||||
"@types/jest": 29.5.5
|
||||
"@types/node": 18.18.7
|
||||
"@types/node": 18.18.8
|
||||
fs-extra: 11.1.1
|
||||
gh-release-assets: 2.0.1
|
||||
jest: 29.7.0
|
||||
@@ -6658,19 +6665,19 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@joplin/renderer@^2.13.4, @joplin/renderer@workspace:packages/renderer, @joplin/renderer@~2.13":
|
||||
"@joplin/renderer@^2.13.3, @joplin/renderer@workspace:packages/renderer, @joplin/renderer@~2.13":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@joplin/renderer@workspace:packages/renderer"
|
||||
dependencies:
|
||||
"@joplin/fork-htmlparser2": ^4.1.50
|
||||
"@joplin/fork-uslug": ^1.0.15
|
||||
"@joplin/utils": ^2.13.4
|
||||
"@joplin/fork-htmlparser2": ^4.1.49
|
||||
"@joplin/fork-uslug": ^1.0.14
|
||||
"@joplin/utils": ^2.13.3
|
||||
"@types/jest": 29.5.5
|
||||
"@types/markdown-it": 13.0.5
|
||||
"@types/node": 18.18.7
|
||||
"@types/node": 18.18.8
|
||||
font-awesome-filetypes: 2.1.0
|
||||
fs-extra: 11.1.1
|
||||
highlight.js: 11.8.0
|
||||
highlight.js: 11.9.0
|
||||
html-entities: 1.4.0
|
||||
jest: 29.7.0
|
||||
jest-environment-jsdom: 29.7.0
|
||||
@@ -6736,7 +6743,7 @@ __metadata:
|
||||
jsdom: 22.1.0
|
||||
knex: 2.5.1
|
||||
koa: 2.14.2
|
||||
ldapts: 7.0.5
|
||||
ldapts: 7.0.6
|
||||
markdown-it: 13.0.2
|
||||
mustache: 4.2.0
|
||||
nanoid: 2.1.11
|
||||
@@ -6749,7 +6756,7 @@ __metadata:
|
||||
pretty-bytes: 5.6.0
|
||||
prettycron: 0.10.0
|
||||
query-string: 7.1.3
|
||||
rate-limiter-flexible: 2.4.2
|
||||
rate-limiter-flexible: 3.0.3
|
||||
raw-body: 2.5.2
|
||||
source-map-support: 0.5.21
|
||||
sqlite3: 5.1.6
|
||||
@@ -6761,23 +6768,23 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@joplin/tools@^2.13.4, @joplin/tools@workspace:packages/tools, @joplin/tools@~2.13":
|
||||
"@joplin/tools@^2.13.3, @joplin/tools@workspace:packages/tools, @joplin/tools@~2.13":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@joplin/tools@workspace:packages/tools"
|
||||
dependencies:
|
||||
"@docusaurus/plugin-sitemap": 2.4.3
|
||||
"@joplin/fork-htmlparser2": ^4.1.50
|
||||
"@joplin/lib": ^2.13.4
|
||||
"@joplin/renderer": ^2.13.4
|
||||
"@joplin/utils": ^2.13.4
|
||||
"@joplin/fork-htmlparser2": ^4.1.49
|
||||
"@joplin/lib": ^2.13.3
|
||||
"@joplin/renderer": ^2.13.3
|
||||
"@joplin/utils": ^2.13.3
|
||||
"@rmp135/sql-ts": 1.18.0
|
||||
"@types/fs-extra": 11.0.3
|
||||
"@types/jest": 29.5.5
|
||||
"@types/js-yaml": 4.0.8
|
||||
"@types/markdown-it": 13.0.5
|
||||
"@types/mustache": 4.2.4
|
||||
"@types/node": 18.18.7
|
||||
"@types/node-fetch": 2.6.7
|
||||
"@types/node": 18.18.8
|
||||
"@types/node-fetch": 2.6.8
|
||||
"@types/yargs": 17.0.29
|
||||
compare-versions: 6.1.0
|
||||
dayjs: 1.11.10
|
||||
@@ -6802,14 +6809,14 @@ __metadata:
|
||||
sharp: 0.32.6
|
||||
source-map-support: 0.5.21
|
||||
sqlite3: 5.1.6
|
||||
style-to-js: 1.1.8
|
||||
style-to-js: 1.1.9
|
||||
typescript: 5.2.2
|
||||
uri-template: 2.0.0
|
||||
yargs: 17.7.2
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@joplin/turndown-plugin-gfm@^1.0.54, @joplin/turndown-plugin-gfm@workspace:packages/turndown-plugin-gfm":
|
||||
"@joplin/turndown-plugin-gfm@^1.0.53, @joplin/turndown-plugin-gfm@workspace:packages/turndown-plugin-gfm":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@joplin/turndown-plugin-gfm@workspace:packages/turndown-plugin-gfm"
|
||||
dependencies:
|
||||
@@ -6821,7 +6828,7 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@joplin/turndown@^4.0.72, @joplin/turndown@workspace:packages/turndown":
|
||||
"@joplin/turndown@^4.0.71, @joplin/turndown@workspace:packages/turndown":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@joplin/turndown@workspace:packages/turndown"
|
||||
dependencies:
|
||||
@@ -6838,13 +6845,13 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@joplin/utils@^2.13.4, @joplin/utils@workspace:packages/utils, @joplin/utils@~2.13":
|
||||
"@joplin/utils@^2.13.3, @joplin/utils@workspace:packages/utils, @joplin/utils@~2.13":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@joplin/utils@workspace:packages/utils"
|
||||
dependencies:
|
||||
"@types/fs-extra": 11.0.3
|
||||
"@types/jest": 29.5.5
|
||||
"@types/node-fetch": 2.6.7
|
||||
"@types/node-fetch": 2.6.8
|
||||
async-mutex: 0.4.0
|
||||
execa: 5.1.1
|
||||
fs-extra: 11.1.1
|
||||
@@ -6990,12 +6997,12 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@js-draw/material-icons@npm:1.14.0":
|
||||
version: 1.14.0
|
||||
resolution: "@js-draw/material-icons@npm:1.14.0"
|
||||
"@js-draw/material-icons@npm:1.11.2":
|
||||
version: 1.11.2
|
||||
resolution: "@js-draw/material-icons@npm:1.11.2"
|
||||
peerDependencies:
|
||||
js-draw: ^1.0.1
|
||||
checksum: 6e67ee6399b9b4f9e5891952e71a978acd69c0d386fe80c957ad884ab8e9f4f954aa0d9dd1b08e78f314b0b8f3807989a482ed4a153457a8bba67f5989dd7a0c
|
||||
checksum: 6a6bbdf936d3a97fab43321d807672f157b12201290a98bd3fd33a7e53966647ed9c5a8aba5dfd6d743bfc37ab9ddff14cbb7fc3f4ffb8b79ff7617a7e886160
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -8095,6 +8102,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@npmcli/fs@npm:^2.1.0":
|
||||
version: 2.1.2
|
||||
resolution: "@npmcli/fs@npm:2.1.2"
|
||||
dependencies:
|
||||
"@gar/promisify": ^1.1.3
|
||||
semver: ^7.3.5
|
||||
checksum: 405074965e72d4c9d728931b64d2d38e6ea12066d4fad651ac253d175e413c06fe4350970c783db0d749181da8fe49c42d3880bd1cbc12cd68e3a7964d820225
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@npmcli/fs@npm:^3.1.0":
|
||||
version: 3.1.0
|
||||
resolution: "@npmcli/fs@npm:3.1.0"
|
||||
@@ -8142,6 +8159,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@npmcli/move-file@npm:^2.0.0":
|
||||
version: 2.0.1
|
||||
resolution: "@npmcli/move-file@npm:2.0.1"
|
||||
dependencies:
|
||||
mkdirp: ^1.0.4
|
||||
rimraf: ^3.0.2
|
||||
checksum: 52dc02259d98da517fae4cb3a0a3850227bdae4939dda1980b788a7670636ca2b4a01b58df03dd5f65c1e3cb70c50fa8ce5762b582b3f499ec30ee5ce1fd9380
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@npmcli/node-gyp@npm:^3.0.0":
|
||||
version: 3.0.0
|
||||
resolution: "@npmcli/node-gyp@npm:3.0.0"
|
||||
@@ -8459,14 +8486,14 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@playwright/test@npm:1.38.1":
|
||||
version: 1.38.1
|
||||
resolution: "@playwright/test@npm:1.38.1"
|
||||
"@playwright/test@npm:1.39.0":
|
||||
version: 1.39.0
|
||||
resolution: "@playwright/test@npm:1.39.0"
|
||||
dependencies:
|
||||
playwright: 1.38.1
|
||||
playwright: 1.39.0
|
||||
bin:
|
||||
playwright: cli.js
|
||||
checksum: c5ec0b23261fe1ef163b6234f69263bc10e7e5a3fb676c7773ffc70b87459a7ab225f57c03b9de649475771638a04c2e00d9b2739304a4dcf5d3edf20a7a4a82
|
||||
checksum: e93e58fc1af4239f239b890374f066c9a758e2492d25e2c1a532f3f00782ab8e7706956a07540fd14882c74e75f5de36273621adce9b79afb8e36e6c15f1d539
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -8949,12 +8976,12 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@react-native-community/netinfo@npm:9.4.1":
|
||||
version: 9.4.1
|
||||
resolution: "@react-native-community/netinfo@npm:9.4.1"
|
||||
"@react-native-community/netinfo@npm:9.4.2":
|
||||
version: 9.4.2
|
||||
resolution: "@react-native-community/netinfo@npm:9.4.2"
|
||||
peerDependencies:
|
||||
react-native: ">=0.59"
|
||||
checksum: cf6471a50a5282f858797cda7531c61ac3d94de2e1c379b14a11f6b049f582606dae55a041dd900c56b01faf69eb5cfef9b4e84b0ea7f02de52804aa5a6e22df
|
||||
checksum: b7783d615dec52e89dfd5f435101c06a1b17b11d6702685ad0ad73fb5c9d3ab6997e7a640b7f0f1f5bb068135331adfb5fb77280ec7b3a19e4332f50f055efd8
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -9662,9 +9689,9 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@testing-library/react-native@npm:12.3.1":
|
||||
version: 12.3.1
|
||||
resolution: "@testing-library/react-native@npm:12.3.1"
|
||||
"@testing-library/react-native@npm:12.3.2":
|
||||
version: 12.3.2
|
||||
resolution: "@testing-library/react-native@npm:12.3.2"
|
||||
dependencies:
|
||||
jest-matcher-utils: ^29.7.0
|
||||
pretty-format: ^29.7.0
|
||||
@@ -9677,7 +9704,7 @@ __metadata:
|
||||
peerDependenciesMeta:
|
||||
jest:
|
||||
optional: true
|
||||
checksum: ad50508e35b077533d5a711c01d96758a82da6bca255bc37f0c9f037c44cde67efbd5984862aec8cb7c4c0c8648b21f3f09378b2fe9e067aa593e5fcb49038e7
|
||||
checksum: c6fdaf64865a079b885ff83ae172330b354dbd13cb9a4370578a544080d87f21cc7a93e079a3bc4256ab0893c5de36feae4bcf6edf24b3a6617019f4369a6053
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -9770,12 +9797,12 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/asn1@npm:>=0.2.1":
|
||||
version: 0.2.2
|
||||
resolution: "@types/asn1@npm:0.2.2"
|
||||
"@types/asn1@npm:>=0.2.2":
|
||||
version: 0.2.3
|
||||
resolution: "@types/asn1@npm:0.2.3"
|
||||
dependencies:
|
||||
"@types/node": "*"
|
||||
checksum: cd64dab0a214a88360995adf86f307565bf13f14d27552590cbb8cefea30585d65385be831b644fee790654bf7d29eae6ed07ba1db0bed59075aac4fb0b8b63d
|
||||
checksum: c5debd9088d664e71d87816d15a3dcd1d200ffd36b22fc82d0a0f53fba4b7a35f83e1ad1142abfb8052e47a9e516e14d4256341a11415f8b67cfb032f01a08a1
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -10413,13 +10440,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/node-fetch@npm:2.6.7":
|
||||
version: 2.6.7
|
||||
resolution: "@types/node-fetch@npm:2.6.7"
|
||||
"@types/node-fetch@npm:2.6.8":
|
||||
version: 2.6.8
|
||||
resolution: "@types/node-fetch@npm:2.6.8"
|
||||
dependencies:
|
||||
"@types/node": "*"
|
||||
form-data: ^4.0.0
|
||||
checksum: 543a540186941e81ca4dda283b5f7bce1d7a93af3ee2c8161fc48d078789e9ce976332ce70f22644293414f680e3f9627d3ef8f59105cf2ea901d5e4acf58d3f
|
||||
checksum: f40e5e2fa3ca05a45453397e891776619739f093f913199c00c141735f8098e4f2ffdea04b9d608182aede2df9607605c71e0fdb97d2614899545ce81bac7005
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -10439,21 +10466,12 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/node@npm:18.18.7":
|
||||
version: 18.18.7
|
||||
resolution: "@types/node@npm:18.18.7"
|
||||
"@types/node@npm:18.18.8":
|
||||
version: 18.18.8
|
||||
resolution: "@types/node@npm:18.18.8"
|
||||
dependencies:
|
||||
undici-types: ~5.26.4
|
||||
checksum: 972f8b214f961b6c8d99f84aab8bfadc656bb71fc7ad4a543ad3405286c95f27385ee0c3844f88d612f3cf225cd4d49ce8a7d9aea05a2aba9b2524ac525040aa
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/node@npm:>=18":
|
||||
version: 20.8.9
|
||||
resolution: "@types/node@npm:20.8.9"
|
||||
dependencies:
|
||||
undici-types: ~5.26.4
|
||||
checksum: 0c05f3502a9507ff27e91dd6fd574fa6f391b3fafedcfe8e0c8d33351fb22d02c0121f854e5b6b3ecb9a8a468407ddf6e7ac0029fb236d4c7e1361ffc758a01f
|
||||
checksum: d6a82bfc28bca8e4e32ffc9526798d1aea62f6993ea3a535cd3f47ac3f725a48efe3f484d68168dd154af0001c89935e4e1d77e7b1809c3824c6382bf99b86f6
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -10641,14 +10659,14 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/react@npm:18.2.33":
|
||||
version: 18.2.33
|
||||
resolution: "@types/react@npm:18.2.33"
|
||||
"@types/react@npm:18.2.34":
|
||||
version: 18.2.34
|
||||
resolution: "@types/react@npm:18.2.34"
|
||||
dependencies:
|
||||
"@types/prop-types": "*"
|
||||
"@types/scheduler": "*"
|
||||
csstype: ^3.0.2
|
||||
checksum: 75903c4d53898c69dd23d0b2730eac4676dc5ade15c25c793dec855f0d7c650cb823832bb1dd881efe8895724f15b06d4bf7081ea0b82391aa3059512ad49ccf
|
||||
checksum: 16446542228cba827143caf0ecb4718cbf02ae5befd4a6bc6d67ed144fe1c0cb4b06b20facf3d2b972d86c67a17cc82f5ec8a03fce42d50e12b2dcd0592fc66e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -14370,6 +14388,32 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"cacache@npm:^16.1.0":
|
||||
version: 16.1.3
|
||||
resolution: "cacache@npm:16.1.3"
|
||||
dependencies:
|
||||
"@npmcli/fs": ^2.1.0
|
||||
"@npmcli/move-file": ^2.0.0
|
||||
chownr: ^2.0.0
|
||||
fs-minipass: ^2.1.0
|
||||
glob: ^8.0.1
|
||||
infer-owner: ^1.0.4
|
||||
lru-cache: ^7.7.1
|
||||
minipass: ^3.1.6
|
||||
minipass-collect: ^1.0.2
|
||||
minipass-flush: ^1.0.5
|
||||
minipass-pipeline: ^1.2.4
|
||||
mkdirp: ^1.0.4
|
||||
p-map: ^4.0.0
|
||||
promise-inflight: ^1.0.1
|
||||
rimraf: ^3.0.2
|
||||
ssri: ^9.0.0
|
||||
tar: ^6.1.11
|
||||
unique-filename: ^2.0.0
|
||||
checksum: d91409e6e57d7d9a3a25e5dcc589c84e75b178ae8ea7de05cbf6b783f77a5fae938f6e8fda6f5257ed70000be27a681e1e44829251bfffe4c10216002f8f14e6
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"cacache@npm:^17.0.0":
|
||||
version: 17.1.3
|
||||
resolution: "cacache@npm:17.1.3"
|
||||
@@ -21533,7 +21577,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"fs-minipass@npm:^2.0.0":
|
||||
"fs-minipass@npm:^2.0.0, fs-minipass@npm:^2.1.0":
|
||||
version: 2.1.0
|
||||
resolution: "fs-minipass@npm:2.1.0"
|
||||
dependencies:
|
||||
@@ -22287,6 +22331,19 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"glob@npm:^8.0.1":
|
||||
version: 8.1.0
|
||||
resolution: "glob@npm:8.1.0"
|
||||
dependencies:
|
||||
fs.realpath: ^1.0.0
|
||||
inflight: ^1.0.4
|
||||
inherits: 2
|
||||
minimatch: ^5.0.1
|
||||
once: ^1.3.0
|
||||
checksum: 92fbea3221a7d12075f26f0227abac435de868dd0736a17170663783296d0dd8d3d532a5672b4488a439bf5d7fb85cdd07c11185d6cd39184f0385cbdfb86a47
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"glob@npm:^8.0.3":
|
||||
version: 8.0.3
|
||||
resolution: "glob@npm:8.0.3"
|
||||
@@ -23072,10 +23129,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"highlight.js@npm:11.8.0":
|
||||
version: 11.8.0
|
||||
resolution: "highlight.js@npm:11.8.0"
|
||||
checksum: d2578a57aee7315946ff19379053fd0a28b127baabf7617ab1d28d62cdc4eaf3d75053569cb8479a5afdc7a68f1ba9a6c1d612d8ae399b4b9aa43093b4fb6831
|
||||
"highlight.js@npm:11.9.0":
|
||||
version: 11.9.0
|
||||
resolution: "highlight.js@npm:11.9.0"
|
||||
checksum: 4043d31c5de9d27d13387d9a9e5e1939557254b7b85f0fab85d9cae0e420e131a3456ebf6148552020a1d8a216d671d583f2433d6c4de6179b8a66487a8325cb
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -26239,7 +26296,7 @@ __metadata:
|
||||
"@joplin/utils": ~2.13
|
||||
"@types/fs-extra": 11.0.3
|
||||
"@types/jest": 29.5.5
|
||||
"@types/node": 18.18.7
|
||||
"@types/node": 18.18.8
|
||||
"@types/proper-lockfile": ^4.1.2
|
||||
aws-sdk: 2.1340.0
|
||||
chalk: 4.1.2
|
||||
@@ -26295,13 +26352,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"js-draw@npm:1.14.0":
|
||||
version: 1.14.0
|
||||
resolution: "js-draw@npm:1.14.0"
|
||||
"js-draw@npm:1.11.2":
|
||||
version: 1.11.2
|
||||
resolution: "js-draw@npm:1.11.2"
|
||||
dependencies:
|
||||
"@js-draw/math": ^1.11.1
|
||||
"@melloware/coloris": 0.22.0
|
||||
checksum: 0e2bbf318a8ebc645ed83f8cf0ef1f43a49d85b5f83e0be1616ec200d37817070a002bda54ef21df72d74a37597aa61e61e94559b27fbe4de8fcdb70effa04d4
|
||||
checksum: 59669bbe37f4c980f8532b96ec7a80880966beca3a82973fa0681c3988d8ed12745d5c1b27645853806087664c14fa49530fc8815a471346f03b3ef7c4366ea9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -27161,18 +27218,17 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ldapts@npm:7.0.5":
|
||||
version: 7.0.5
|
||||
resolution: "ldapts@npm:7.0.5"
|
||||
"ldapts@npm:7.0.6":
|
||||
version: 7.0.6
|
||||
resolution: "ldapts@npm:7.0.6"
|
||||
dependencies:
|
||||
"@types/asn1": ">=0.2.1"
|
||||
"@types/node": ">=18"
|
||||
"@types/asn1": ">=0.2.2"
|
||||
"@types/uuid": ">=9"
|
||||
asn1: ~0.2.6
|
||||
debug: ~4.3.4
|
||||
strict-event-emitter-types: ~2.0.0
|
||||
uuid: ~9.0.1
|
||||
checksum: 063a84b6ed2ce55f1eeff374da0a5b7f12431e2c54e03bcb35fe1a5eecb6bdf6e95130b80ab28ea6b36db09a442e3e07c4e04e9bb827276e1cc1f5269597a828
|
||||
checksum: 43ca9b4924459154b3692147dbe140274e164c1dc34a31692c23b742541a97ba0fe42a52193854ee0aa6f5fd9dcdaa70bc39fc16a617768ea1a260fa2ff49cb3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -27957,6 +28013,30 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"make-fetch-happen@npm:^10.0.3":
|
||||
version: 10.2.1
|
||||
resolution: "make-fetch-happen@npm:10.2.1"
|
||||
dependencies:
|
||||
agentkeepalive: ^4.2.1
|
||||
cacache: ^16.1.0
|
||||
http-cache-semantics: ^4.1.0
|
||||
http-proxy-agent: ^5.0.0
|
||||
https-proxy-agent: ^5.0.0
|
||||
is-lambda: ^1.0.1
|
||||
lru-cache: ^7.7.1
|
||||
minipass: ^3.1.6
|
||||
minipass-collect: ^1.0.2
|
||||
minipass-fetch: ^2.0.3
|
||||
minipass-flush: ^1.0.5
|
||||
minipass-pipeline: ^1.2.4
|
||||
negotiator: ^0.6.3
|
||||
promise-retry: ^2.0.1
|
||||
socks-proxy-agent: ^7.0.0
|
||||
ssri: ^9.0.0
|
||||
checksum: 2332eb9a8ec96f1ffeeea56ccefabcb4193693597b132cd110734d50f2928842e22b84cfa1508e921b8385cdfd06dda9ad68645fed62b50fff629a580f5fb72c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"make-fetch-happen@npm:^11.0.0, make-fetch-happen@npm:^11.0.1, make-fetch-happen@npm:^11.0.3, make-fetch-happen@npm:^11.1.1":
|
||||
version: 11.1.1
|
||||
resolution: "make-fetch-happen@npm:11.1.1"
|
||||
@@ -29737,6 +29817,21 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"minipass-fetch@npm:^2.0.3":
|
||||
version: 2.1.2
|
||||
resolution: "minipass-fetch@npm:2.1.2"
|
||||
dependencies:
|
||||
encoding: ^0.1.13
|
||||
minipass: ^3.1.6
|
||||
minipass-sized: ^1.0.3
|
||||
minizlib: ^2.1.2
|
||||
dependenciesMeta:
|
||||
encoding:
|
||||
optional: true
|
||||
checksum: 3f216be79164e915fc91210cea1850e488793c740534985da017a4cbc7a5ff50506956d0f73bb0cb60e4fe91be08b6b61ef35101706d3ef5da2c8709b5f08f91
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"minipass-fetch@npm:^3.0.0":
|
||||
version: 3.0.3
|
||||
resolution: "minipass-fetch@npm:3.0.3"
|
||||
@@ -30548,7 +30643,28 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"node-gyp@npm:9.4.0, node-gyp@npm:^9.0.0, node-gyp@npm:latest":
|
||||
"node-gyp@npm:9.4.1":
|
||||
version: 9.4.1
|
||||
resolution: "node-gyp@npm:9.4.1"
|
||||
dependencies:
|
||||
env-paths: ^2.2.0
|
||||
exponential-backoff: ^3.1.1
|
||||
glob: ^7.1.4
|
||||
graceful-fs: ^4.2.6
|
||||
make-fetch-happen: ^10.0.3
|
||||
nopt: ^6.0.0
|
||||
npmlog: ^6.0.0
|
||||
rimraf: ^3.0.2
|
||||
semver: ^7.3.5
|
||||
tar: ^6.1.2
|
||||
which: ^2.0.2
|
||||
bin:
|
||||
node-gyp: bin/node-gyp.js
|
||||
checksum: 8576c439e9e925ab50679f87b7dfa7aa6739e42822e2ad4e26c36341c0ba7163fdf5a946f0a67a476d2f24662bc40d6c97bd9e79ced4321506738e6b760a1577
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"node-gyp@npm:^9.0.0, node-gyp@npm:latest":
|
||||
version: 9.4.0
|
||||
resolution: "node-gyp@npm:9.4.0"
|
||||
dependencies:
|
||||
@@ -32744,27 +32860,27 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"playwright-core@npm:1.38.1":
|
||||
version: 1.38.1
|
||||
resolution: "playwright-core@npm:1.38.1"
|
||||
"playwright-core@npm:1.39.0":
|
||||
version: 1.39.0
|
||||
resolution: "playwright-core@npm:1.39.0"
|
||||
bin:
|
||||
playwright-core: cli.js
|
||||
checksum: 66e83fe040f309b13ad94ba39dea40ac207bfcbbc22de13141af88dbdedd64e1c4e3ce1d0cb070d4efd8050d7e579953ec3681dd8a0acf2c1cc738d9c50e545e
|
||||
checksum: 556e78dee4f9890facf2af8249972e0d6e01a5ae98737b0f6b0166c660a95ffee4cb79350335b1ef96430a0ef01d3669daae9099fa46c8d403d11c623988238b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"playwright@npm:1.38.1":
|
||||
version: 1.38.1
|
||||
resolution: "playwright@npm:1.38.1"
|
||||
"playwright@npm:1.39.0":
|
||||
version: 1.39.0
|
||||
resolution: "playwright@npm:1.39.0"
|
||||
dependencies:
|
||||
fsevents: 2.3.2
|
||||
playwright-core: 1.38.1
|
||||
playwright-core: 1.39.0
|
||||
dependenciesMeta:
|
||||
fsevents:
|
||||
optional: true
|
||||
bin:
|
||||
playwright: cli.js
|
||||
checksum: 4e01d4ee52d9ccf75a80d8492829106802590721d56bff7c5957ff1f21eb3c328ee5bc3c1784a59c4b515df1b98d08ef92e4a35a807f454cd00dc481d30fadc2
|
||||
checksum: 96d8ca5aa25465c1c5d554d0d6071981d55e22477800ff8f5d47a53ca75193d60ece2df538a01b7165b3277dd5493c67603a5acda713029df7fbd95ce2417bc9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -34026,10 +34142,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"punycode@npm:2.3.0, punycode@npm:^2.3.0":
|
||||
version: 2.3.0
|
||||
resolution: "punycode@npm:2.3.0"
|
||||
checksum: 39f760e09a2a3bbfe8f5287cf733ecdad69d6af2fe6f97ca95f24b8921858b91e9ea3c9eeec6e08cede96181b3bb33f95c6ffd8c77e63986508aa2e8159fa200
|
||||
"punycode@npm:2.3.1":
|
||||
version: 2.3.1
|
||||
resolution: "punycode@npm:2.3.1"
|
||||
checksum: bb0a0ceedca4c3c57a9b981b90601579058903c62be23c5e8e843d2c2d4148a3ecf029d5133486fb0e1822b098ba8bba09e89d6b21742d02fa26bda6441a6fb2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -34047,6 +34163,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"punycode@npm:^2.3.0":
|
||||
version: 2.3.0
|
||||
resolution: "punycode@npm:2.3.0"
|
||||
checksum: 39f760e09a2a3bbfe8f5287cf733ecdad69d6af2fe6f97ca95f24b8921858b91e9ea3c9eeec6e08cede96181b3bb33f95c6ffd8c77e63986508aa2e8159fa200
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"pupa@npm:^2.1.1":
|
||||
version: 2.1.1
|
||||
resolution: "pupa@npm:2.1.1"
|
||||
@@ -34256,10 +34379,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"rate-limiter-flexible@npm:2.4.2":
|
||||
version: 2.4.2
|
||||
resolution: "rate-limiter-flexible@npm:2.4.2"
|
||||
checksum: 039e58b664991963ba2668a83d0406a72e5822683103acbe416854deb92ed834b840ce6e0acfea35917d9b49685bd53946ae47435a9f5916c2e7550395dec9dc
|
||||
"rate-limiter-flexible@npm:3.0.3":
|
||||
version: 3.0.3
|
||||
resolution: "rate-limiter-flexible@npm:3.0.3"
|
||||
checksum: 3854577d78511e225028ec592987a64d2daab3235e159ce64bf875eb47090f8c01073d8095283cff2a253708b0a81c7a413844f8f8077af8528716fb1b44a50f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -36581,7 +36704,7 @@ __metadata:
|
||||
lerna: 3.22.1
|
||||
lint-staged: 14.0.1
|
||||
madge: 6.1.0
|
||||
node-gyp: 9.4.0
|
||||
node-gyp: 9.4.1
|
||||
nodemon: 3.0.1
|
||||
npm-package-json-lint: 7.0.0
|
||||
typescript: 5.2.2
|
||||
@@ -37967,6 +38090,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"source-map@npm:^0.7.4":
|
||||
version: 0.7.4
|
||||
resolution: "source-map@npm:0.7.4"
|
||||
checksum: 01cc5a74b1f0e1d626a58d36ad6898ea820567e87f18dfc9d24a9843a351aaa2ec09b87422589906d6ff1deed29693e176194dc88bcae7c9a852dc74b311dbf5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"space-separated-tokens@npm:^1.0.0":
|
||||
version: 1.1.5
|
||||
resolution: "space-separated-tokens@npm:1.1.5"
|
||||
@@ -38209,6 +38339,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ssri@npm:^9.0.0":
|
||||
version: 9.0.1
|
||||
resolution: "ssri@npm:9.0.1"
|
||||
dependencies:
|
||||
minipass: ^3.1.1
|
||||
checksum: fb58f5e46b6923ae67b87ad5ef1c5ab6d427a17db0bead84570c2df3cd50b4ceb880ebdba2d60726588272890bae842a744e1ecce5bd2a2a582fccd5068309eb
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"stable@npm:^0.1.8":
|
||||
version: 0.1.8
|
||||
resolution: "stable@npm:0.1.8"
|
||||
@@ -38909,12 +39048,12 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"style-to-js@npm:1.1.8":
|
||||
version: 1.1.8
|
||||
resolution: "style-to-js@npm:1.1.8"
|
||||
"style-to-js@npm:1.1.9":
|
||||
version: 1.1.9
|
||||
resolution: "style-to-js@npm:1.1.9"
|
||||
dependencies:
|
||||
style-to-object: 1.0.3
|
||||
checksum: cc4d4284af587bf74559a6da17dadb88c96c8054755666cce1b768615ac2bd6231ce332a8cee118acafb577f51f243b795b716326b3c617ec12151d23f660d8f
|
||||
style-to-object: 1.0.4
|
||||
checksum: f05dcd9edc7c2b530159c3eea7be558ebd324073dad444220ca3c12a15bdfa55f5690625238597190d0e21cc87433d6b745eb757055e0e781998153863fdc105
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -38927,12 +39066,12 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"style-to-object@npm:1.0.3":
|
||||
version: 1.0.3
|
||||
resolution: "style-to-object@npm:1.0.3"
|
||||
"style-to-object@npm:1.0.4":
|
||||
version: 1.0.4
|
||||
resolution: "style-to-object@npm:1.0.4"
|
||||
dependencies:
|
||||
inline-style-parser: 0.2.2
|
||||
checksum: fca6b35dc704656163c4b11d514ada9f9998fb434c9cec5995445d7d7d595ba3a4fda0476016d625cbb282d43ba5123ef0b5871d855d391400bb0dc2c2beeae1
|
||||
checksum: d3d2ea838b7777d3d6db165df8322e0f6b4f550f081e5833c89c4d91e5de2f7a09fa81cfd2208221683a94e476d4fc24df65c4d3ab75ddd45b419bef9426fbaf
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -40238,18 +40377,19 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ts-loader@npm:9.4.4":
|
||||
version: 9.4.4
|
||||
resolution: "ts-loader@npm:9.4.4"
|
||||
"ts-loader@npm:9.5.0":
|
||||
version: 9.5.0
|
||||
resolution: "ts-loader@npm:9.5.0"
|
||||
dependencies:
|
||||
chalk: ^4.1.0
|
||||
enhanced-resolve: ^5.0.0
|
||||
micromatch: ^4.0.0
|
||||
semver: ^7.3.4
|
||||
source-map: ^0.7.4
|
||||
peerDependencies:
|
||||
typescript: "*"
|
||||
webpack: ^5.0.0
|
||||
checksum: 8e5e6b839b0edfa40d2156c880d88ccab58226894ea5978221bc48c7db3215e2e856bfd0093f148e925a2befc42d6c94cafa9a994a7da274541efaa916012b63
|
||||
checksum: a319575faa07145917a7050ac6be7e7f8d97745c6b6ecf8097ac51cebd2d459e8f8b2519d0c39066a065f4d73ae331d2aba9de3d62ea38bc59fd84395794d428
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -41082,6 +41222,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"unique-filename@npm:^2.0.0":
|
||||
version: 2.0.1
|
||||
resolution: "unique-filename@npm:2.0.1"
|
||||
dependencies:
|
||||
unique-slug: ^3.0.0
|
||||
checksum: 807acf3381aff319086b64dc7125a9a37c09c44af7620bd4f7f3247fcd5565660ac12d8b80534dcbfd067e6fe88a67e621386dd796a8af828d1337a8420a255f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"unique-filename@npm:^3.0.0":
|
||||
version: 3.0.0
|
||||
resolution: "unique-filename@npm:3.0.0"
|
||||
@@ -41100,6 +41249,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"unique-slug@npm:^3.0.0":
|
||||
version: 3.0.0
|
||||
resolution: "unique-slug@npm:3.0.0"
|
||||
dependencies:
|
||||
imurmurhash: ^0.1.4
|
||||
checksum: 49f8d915ba7f0101801b922062ee46b7953256c93ceca74303bd8e6413ae10aa7e8216556b54dc5382895e8221d04f1efaf75f945c2e4a515b4139f77aa6640c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"unique-slug@npm:^4.0.0":
|
||||
version: 4.0.0
|
||||
resolution: "unique-slug@npm:4.0.0"
|
||||
|
||||
Reference in New Issue
Block a user