joplin-plugin-backup 1.0.5 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/auto-assign-issue.yml +14 -0
- package/LICENSE +21 -21
- package/README.md +26 -2
- package/__test__/backup.test.ts +69 -20
- package/__test__/sevenZip.test.ts +3 -1
- package/package.json +1 -1
- package/publish/io.github.jackgruber.backup.jpl +0 -0
- package/publish/io.github.jackgruber.backup.json +3 -3
- package/.ENV +0 -1
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2021 Gruber Alexander
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021 Gruber Alexander
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -34,7 +34,6 @@ Go to `Tools > Options > Backup`
|
|
|
34
34
|
| Option | Description | Default |
|
|
35
35
|
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------- |
|
|
36
36
|
| `Backup path` | Where to save the backups to. <br>This path is exclusive for the Joplin backups, there should be no other data in it! | |
|
|
37
|
-
| `Single JEX` | Create only one JEX file for all notebooks | `false` |
|
|
38
37
|
| `Keep x backups` | How many backups should be kept | `1` |
|
|
39
38
|
| `Backups interval in hours` | Create a backup every X hours | `24` |
|
|
40
39
|
| `Only on change` | Creates a backup at the specified backup interval only if there was a change to a `note`, `tag`, `resource` or `notebook` | `false` |
|
|
@@ -44,6 +43,9 @@ Go to `Tools > Options > Backup`
|
|
|
44
43
|
| `Zip compression Level` | Compression level for zip archive archive | `Copy (no compression)` |
|
|
45
44
|
| `Temporary export path` | The data is first exported into this path before it is copied to the backup `Backup path`. | `` |
|
|
46
45
|
| `Backup set name` | Name of the backup set if multiple backups are to be keep. [Available moment tokens](https://momentjs.com/docs/#/displaying/format/), which can be used with `{<TOKEN>}` | `{YYYYMMDDHHmm}` |
|
|
46
|
+
| `Single JEX` | Create only one JEX file for all, this option is recommended to prevent the loss of internal note links or folder structure during a restore! | `true` |
|
|
47
|
+
| `Create Subfolder` | Create a sub folder `JoplinBackup` in the configured `Backup path`. Deactivate only if there is no other data in the `Backup path`! | `true` |
|
|
48
|
+
| `Backup plugins` | Backup the plugin folder from the Joplin profile with all installed plugin jpl files. | `true` |
|
|
47
49
|
|
|
48
50
|
## Keyboard Shortcuts
|
|
49
51
|
|
|
@@ -59,13 +61,14 @@ Under `Options > Keyboard Shortcuts` you can assign a keyboard shortcut for the
|
|
|
59
61
|
- The `userchrome.css` (Your Joplin customization)
|
|
60
62
|
- The `userstyle.css` (Your Joplin customization)
|
|
61
63
|
- The `templates` folder (Note templates)
|
|
64
|
+
- The `plugin` folder (All installed plugins, no plugin settings!)
|
|
62
65
|
|
|
63
66
|
## Restore
|
|
64
67
|
|
|
65
68
|
### Settings
|
|
66
69
|
|
|
67
70
|
To restore the Settings, copy the desired files from `<Backup Path>\Profile` to the Joplin directory `.config\joplin-desktop`.
|
|
68
|
-
The exact path can be found in Joplin under `Tools > Options >
|
|
71
|
+
The exact path can be found in Joplin under `Tools > Options > General`:
|
|
69
72
|
|
|
70
73
|
<img src=img/joplin_path_in_gui.jpg>
|
|
71
74
|
|
|
@@ -78,6 +81,27 @@ The notes are imported via `File > Import > JEX - Joplin Export File`.
|
|
|
78
81
|
The notes are imported additionally, no check for duplicates is performed.
|
|
79
82
|
If the folder in which the note was located already exists in you Joplin, than the folder name is extended by one (1).
|
|
80
83
|
|
|
84
|
+
## FAQ
|
|
85
|
+
|
|
86
|
+
### Internal Joplin links betwen notes are lost
|
|
87
|
+
|
|
88
|
+
If several JEX files are imported and the notes have links to each other, these links will be lost.
|
|
89
|
+
Therefore it is recommended to create a Single JEX Backup!
|
|
90
|
+
|
|
91
|
+
### Compine multiple JEX Files to one
|
|
92
|
+
|
|
93
|
+
By combining the JEX files into one, the Joplin internal links will work again after the import.
|
|
94
|
+
|
|
95
|
+
1. Open one of the JEX files in a ZIP program like 7-Zip
|
|
96
|
+
2. Open a second JEX and add all files to the first JEX
|
|
97
|
+
3. Repeat step 2 for all files
|
|
98
|
+
4. Import first JEX which now contains all notes
|
|
99
|
+
|
|
100
|
+
## Open a JEX Backup file
|
|
101
|
+
|
|
102
|
+
A Joplin JEX Backup file is a tar archive which can be opened with any zip program that supports TAR archive.
|
|
103
|
+
The file names in the archive correspond to the Joplin internal IDs.
|
|
104
|
+
|
|
81
105
|
## Changelog
|
|
82
106
|
|
|
83
107
|
See [CHANGELOG.md](CHANGELOG.md)
|
package/__test__/backup.test.ts
CHANGED
|
@@ -24,6 +24,7 @@ let spyOnLogVerbose = null;
|
|
|
24
24
|
let spyOnLogInfo = null;
|
|
25
25
|
let spyOnLogWarn = null;
|
|
26
26
|
let spyOnLogError = null;
|
|
27
|
+
let spyOnShowError = null;
|
|
27
28
|
let spyOnSaveBackupInfo = null;
|
|
28
29
|
|
|
29
30
|
const spyOnsSettingsValue = jest.spyOn(joplin.settings, "value");
|
|
@@ -73,6 +74,10 @@ describe("Backup", function () {
|
|
|
73
74
|
spyOnLogError = jest
|
|
74
75
|
.spyOn(backup.log, "error")
|
|
75
76
|
.mockImplementation(() => {});
|
|
77
|
+
|
|
78
|
+
spyOnShowError = jest
|
|
79
|
+
.spyOn(backup, "showError")
|
|
80
|
+
.mockImplementation(() => {});
|
|
76
81
|
});
|
|
77
82
|
|
|
78
83
|
afterEach(async () => {
|
|
@@ -80,6 +85,7 @@ describe("Backup", function () {
|
|
|
80
85
|
spyOnLogInfo.mockReset();
|
|
81
86
|
spyOnLogWarn.mockReset();
|
|
82
87
|
spyOnLogError.mockReset();
|
|
88
|
+
spyOnShowError.mockReset();
|
|
83
89
|
spyOnsSettingsValue.mockReset();
|
|
84
90
|
spyOnGlobalValue.mockReset();
|
|
85
91
|
spyOnSaveBackupInfo.mockReset();
|
|
@@ -88,29 +94,72 @@ describe("Backup", function () {
|
|
|
88
94
|
afterAll(async () => {
|
|
89
95
|
fs.removeSync(testPath.base);
|
|
90
96
|
});
|
|
91
|
-
|
|
92
97
|
describe("Backup path", function () {
|
|
93
|
-
it(`
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
98
|
+
it(`Path tests`, async () => {
|
|
99
|
+
const testCases = [
|
|
100
|
+
{
|
|
101
|
+
backupPath: testPath.joplinProfile,
|
|
102
|
+
createSubfolder: false,
|
|
103
|
+
expectedBackupPath: null,
|
|
104
|
+
expectedBackupPathExist: null,
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
backupPath: testPath.joplinProfile,
|
|
108
|
+
createSubfolder: true,
|
|
109
|
+
expectedBackupPath: path.join(testPath.joplinProfile, "JoplinBackup"),
|
|
110
|
+
expectedBackupPathExist: true,
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
backupPath: testPath.backupBasePath,
|
|
114
|
+
createSubfolder: false,
|
|
115
|
+
expectedBackupPath: testPath.backupBasePath,
|
|
116
|
+
expectedBackupPathExist: true,
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
backupPath: testPath.backupBasePath,
|
|
120
|
+
createSubfolder: true,
|
|
121
|
+
expectedBackupPath: path.join(
|
|
122
|
+
testPath.backupBasePath,
|
|
123
|
+
"JoplinBackup"
|
|
124
|
+
),
|
|
125
|
+
expectedBackupPathExist: true,
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
backupPath: path.join(testPath.backupBasePath, "NotExisting"),
|
|
129
|
+
createSubfolder: false,
|
|
130
|
+
expectedBackupPath: path.join(testPath.backupBasePath, "NotExisting"),
|
|
131
|
+
expectedBackupPathExist: false,
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
backupPath: path.join(testPath.backupBasePath, "NotExisting"),
|
|
135
|
+
createSubfolder: true,
|
|
136
|
+
expectedBackupPath: path.join(
|
|
137
|
+
testPath.backupBasePath,
|
|
138
|
+
"NotExisting",
|
|
139
|
+
"JoplinBackup"
|
|
140
|
+
),
|
|
141
|
+
expectedBackupPathExist: false,
|
|
142
|
+
},
|
|
143
|
+
];
|
|
104
144
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
145
|
+
for (const testCase of testCases) {
|
|
146
|
+
when(spyOnsSettingsValue)
|
|
147
|
+
.calledWith("path")
|
|
148
|
+
.mockImplementation(() => Promise.resolve(testCase.backupPath));
|
|
149
|
+
backup.createSubfolder = testCase.createSubfolder;
|
|
150
|
+
await backup.loadBackupPath();
|
|
151
|
+
expect(backup.backupBasePath).toBe(testCase.expectedBackupPath);
|
|
152
|
+
expect(backup.backupBasePath).not.toBe(testPath.joplinProfile);
|
|
153
|
+
|
|
154
|
+
if (testCase.expectedBackupPathExist !== null) {
|
|
155
|
+
expect(fs.existsSync(backup.backupBasePath)).toBe(
|
|
156
|
+
testCase.expectedBackupPathExist
|
|
157
|
+
);
|
|
158
|
+
}
|
|
111
159
|
|
|
112
|
-
|
|
113
|
-
|
|
160
|
+
expect(backup.log.error).toHaveBeenCalledTimes(0);
|
|
161
|
+
expect(backup.log.warn).toHaveBeenCalledTimes(0);
|
|
162
|
+
}
|
|
114
163
|
});
|
|
115
164
|
|
|
116
165
|
it(`relative paths`, async () => {
|
|
@@ -32,7 +32,9 @@ describe("Test sevenZip", function () {
|
|
|
32
32
|
expect(fs.existsSync(file3)).toBe(true);
|
|
33
33
|
expect(fs.existsSync(zip)).toBe(false);
|
|
34
34
|
|
|
35
|
-
expect(await sevenZip.add(zip, testBaseDir
|
|
35
|
+
expect(await sevenZip.add(zip, path.join(testBaseDir, "*"), "secret")).toBe(
|
|
36
|
+
true
|
|
37
|
+
);
|
|
36
38
|
expect(fs.existsSync(zip)).toBe(true);
|
|
37
39
|
|
|
38
40
|
expect(await sevenZip.passwordProtected(zip)).toBe(true);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "joplin-plugin-backup",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"dist": "webpack --joplin-plugin-config buildMain && webpack --joplin-plugin-config buildExtraScripts && webpack --joplin-plugin-config createArchive",
|
|
6
6
|
"prepare": "npm run dist && husky install",
|
|
Binary file
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"manifest_version": 1,
|
|
3
3
|
"id": "io.github.jackgruber.backup",
|
|
4
4
|
"app_min_version": "2.1.3",
|
|
5
|
-
"version": "1.0
|
|
5
|
+
"version": "1.1.0",
|
|
6
6
|
"name": "Simple Backup",
|
|
7
7
|
"description": "Plugin to create manual and automatic backups.",
|
|
8
8
|
"author": "JackGruber",
|
|
@@ -16,6 +16,6 @@
|
|
|
16
16
|
"7zip",
|
|
17
17
|
"encrypted"
|
|
18
18
|
],
|
|
19
|
-
"_publish_hash": "sha256:
|
|
20
|
-
"_publish_commit": "master:
|
|
19
|
+
"_publish_hash": "sha256:8d8c6a3bb92fafc587269aea58b623b05242d42c0766a05bbe25c3ba2bbdf8ee",
|
|
20
|
+
"_publish_commit": "master:00ed52133c659e0f3ac1a55f70b776c42fca0a6d"
|
|
21
21
|
}
|
package/.ENV
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
GITHUB_TOKEN=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
|