You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-12-14 23:26:58 +02:00
Compare commits
166 Commits
safe-mode-
...
mac-binary
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
357277cda0 | ||
|
|
8c1568ae81 | ||
|
|
66e479d13d | ||
|
|
700c1410fa | ||
|
|
3873e15a21 | ||
|
|
72ec2d3b1e | ||
|
|
7eddbc7002 | ||
|
|
d593ed130e | ||
|
|
b2eabb3836 | ||
|
|
5e1c789926 | ||
|
|
4f552b396c | ||
|
|
132bcbd477 | ||
|
|
8f6192464b | ||
|
|
897addec4e | ||
|
|
f3eea43d24 | ||
|
|
8babaddbcb | ||
|
|
13cdaabb17 | ||
|
|
a94aa21088 | ||
|
|
6116bed4e3 | ||
|
|
fabd0b4dda | ||
|
|
6b72f86e7b | ||
|
|
02cf546124 | ||
|
|
eecb012d64 | ||
|
|
04e9b40769 | ||
|
|
efdbaeb397 | ||
|
|
46425b920c | ||
|
|
f5be43c2ac | ||
|
|
51e865c467 | ||
|
|
080541a2fe | ||
|
|
ac8b3ae0cc | ||
|
|
0b3919fd62 | ||
|
|
7dc638edf4 | ||
|
|
db69125e8f | ||
|
|
3b686194d8 | ||
|
|
ccabc778f6 | ||
|
|
5c2640f88f | ||
|
|
eca0f92dff | ||
|
|
260fa6c038 | ||
|
|
8ec6bc9138 | ||
|
|
93fa92369b | ||
|
|
56b9c9fbc9 | ||
|
|
bc6c5ab7a7 | ||
|
|
c68d196baa | ||
|
|
1826625e4f | ||
|
|
20b8fb2719 | ||
|
|
f813e71b29 | ||
|
|
02422a6e31 | ||
|
|
69a34e87f3 | ||
|
|
cbeaa16b61 | ||
|
|
05917ac142 | ||
|
|
897fd0f727 | ||
|
|
9edb402b18 | ||
|
|
36ae58ffe1 | ||
|
|
5ef8b86957 | ||
|
|
c7228cfcd6 | ||
|
|
7a791dbf98 | ||
|
|
a543588527 | ||
|
|
998ad142a6 | ||
|
|
b6a53f96f7 | ||
|
|
841a9c6e09 | ||
|
|
d25c078ef0 | ||
|
|
0c8de68b80 | ||
|
|
44d93d52d3 | ||
|
|
073bec9e8c | ||
|
|
e6a8c2bea5 | ||
|
|
81c316cd2c | ||
|
|
659c851960 | ||
|
|
572701d9a0 | ||
|
|
ff69ac17be | ||
|
|
b44945b3a0 | ||
|
|
2584224026 | ||
|
|
46136871bf | ||
|
|
66ef37bd4e | ||
|
|
9ddf75604d | ||
|
|
3ed7e1d7e8 | ||
|
|
b2b412105a | ||
|
|
60a3c4f65e | ||
|
|
9645414c17 | ||
|
|
af0136ef39 | ||
|
|
b76586c4fd | ||
|
|
376e4ebde0 | ||
|
|
1439b8787f | ||
|
|
b8854a99be | ||
|
|
6cf02173dc | ||
|
|
4d8a53d8c9 | ||
|
|
7f43718e1d | ||
|
|
690ce637b1 | ||
|
|
4d023e679e | ||
|
|
6e220a978f | ||
|
|
39757cd90e | ||
|
|
5ccbbea757 | ||
|
|
309222c082 | ||
|
|
50f5fe2c91 | ||
|
|
eacae83182 | ||
|
|
403d770b1d | ||
|
|
a481bf1b53 | ||
|
|
0d32570c9e | ||
|
|
f017e99b02 | ||
|
|
a89d64d435 | ||
|
|
3a27086534 | ||
|
|
413c1e41b5 | ||
|
|
8b879464b8 | ||
|
|
97c9bbc1fe | ||
|
|
e5bebef7b2 | ||
|
|
73752c4b3f | ||
|
|
dcf7c9838d | ||
|
|
f325e7694b | ||
|
|
75d204c9ca | ||
|
|
cf4008951d | ||
|
|
d67818d096 | ||
|
|
6aaea8ad4f | ||
|
|
de41278096 | ||
|
|
f01ab70907 | ||
|
|
bbdb221a67 | ||
|
|
7d053f8c79 | ||
|
|
fcad0bf3ca | ||
|
|
58f929f6b5 | ||
|
|
943198c56e | ||
|
|
2112ad4004 | ||
|
|
5995dc81f3 | ||
|
|
104e752634 | ||
|
|
fc335cd15d | ||
|
|
45923ba0d3 | ||
|
|
8fefa99d81 | ||
|
|
85d652cd67 | ||
|
|
88e41e9c7d | ||
|
|
26750488d0 | ||
|
|
a0f582b2b9 | ||
|
|
917b53bec2 | ||
|
|
e44a93422a | ||
|
|
e115ef4259 | ||
|
|
bcec699124 | ||
|
|
d23c728a1a | ||
|
|
0a2d507dec | ||
|
|
0c08617606 | ||
|
|
29fba45c33 | ||
|
|
1071a455b6 | ||
|
|
57e4b36fd7 | ||
|
|
f08fa92294 | ||
|
|
3a8d87d292 | ||
|
|
53302c9e90 | ||
|
|
28a24d8c03 | ||
|
|
3e52411bc4 | ||
|
|
1548ea18e1 | ||
|
|
f8cd1ba8e5 | ||
|
|
d18a4be31f | ||
|
|
c56f270ed6 | ||
|
|
2bca3d1032 | ||
|
|
9f81d69c5e | ||
|
|
815419260d | ||
|
|
6729a3d51f | ||
|
|
6d8ce280dd | ||
|
|
9e5b455065 | ||
|
|
09cbac3019 | ||
|
|
5354ad3934 | ||
|
|
7754048b80 | ||
|
|
ffeeff260f | ||
|
|
71ea74d273 | ||
|
|
3a744c79ae | ||
|
|
d9ba27a1ec | ||
|
|
0a3540049c | ||
|
|
ab50ca9bbd | ||
|
|
0bee793ab8 | ||
|
|
89fc5e19d9 | ||
|
|
6a3bf51084 | ||
|
|
df1e298c84 |
@@ -66,6 +66,7 @@ packages/lib/welcomeAssets.js
|
||||
packages/plugins/**/api
|
||||
packages/plugins/**/dist
|
||||
packages/server/dist/
|
||||
packages/utils/dist/
|
||||
packages/tools/node_modules
|
||||
packages/tools/PortableAppsLauncher
|
||||
packages/turndown-plugin-gfm/
|
||||
@@ -329,6 +330,7 @@ packages/app-desktop/gui/style/StyledTextInput.js
|
||||
packages/app-desktop/gui/utils/NoteListUtils.js
|
||||
packages/app-desktop/gui/utils/convertToScreenCoordinates.js
|
||||
packages/app-desktop/gui/utils/loadScript.js
|
||||
packages/app-desktop/gulpfile.js
|
||||
packages/app-desktop/plugins/GotoAnything.js
|
||||
packages/app-desktop/services/bridge.js
|
||||
packages/app-desktop/services/commands/stateToWhenClauseContext.js
|
||||
@@ -404,6 +406,7 @@ packages/app-mobile/components/SideMenu.js
|
||||
packages/app-mobile/components/TextInput.js
|
||||
packages/app-mobile/components/app-nav.js
|
||||
packages/app-mobile/components/biometrics/BiometricPopup.js
|
||||
packages/app-mobile/components/biometrics/biometricAuthenticate.js
|
||||
packages/app-mobile/components/biometrics/sensorInfo.js
|
||||
packages/app-mobile/components/getResponsiveValue.js
|
||||
packages/app-mobile/components/getResponsiveValue.test.js
|
||||
@@ -862,6 +865,7 @@ packages/tools/update-readme-download.js
|
||||
packages/tools/update-readme-sponsors.js
|
||||
packages/tools/updateMarkdownDoc.js
|
||||
packages/tools/utils/discourse.js
|
||||
packages/tools/utils/loadSponsors.js
|
||||
packages/tools/utils/translation.js
|
||||
packages/tools/website/build.js
|
||||
packages/tools/website/buildTranslations.js
|
||||
|
||||
3
.github/scripts/run_ci.sh
vendored
3
.github/scripts/run_ci.sh
vendored
@@ -180,9 +180,6 @@ cd "$ROOT_DIR/packages/app-desktop"
|
||||
|
||||
if [[ $GIT_TAG_NAME = v* ]]; then
|
||||
echo "Step: Building and publishing desktop application..."
|
||||
# cd "$ROOT_DIR/packages/tools"
|
||||
# node bundleDefaultPlugins.js
|
||||
cd "$ROOT_DIR/packages/app-desktop"
|
||||
USE_HARD_LINKS=false yarn run dist
|
||||
elif [[ $IS_LINUX = 1 ]] && [[ $GIT_TAG_NAME = $SERVER_TAG_PREFIX-* ]]; then
|
||||
echo "Step: Building Docker Image..."
|
||||
|
||||
2
.github/workflows/build-android.yml
vendored
2
.github/workflows/build-android.yml
vendored
@@ -6,6 +6,7 @@ on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
pre_job:
|
||||
if: github.repository == 'laurent22/joplin'
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
should_skip: ${{ steps.skip_check.outputs.should_skip }}
|
||||
@@ -16,6 +17,7 @@ jobs:
|
||||
concurrent_skipping: 'same_content_newer'
|
||||
|
||||
BuildAndroidDebug:
|
||||
if: github.repository == 'laurent22/joplin'
|
||||
needs: pre_job
|
||||
if: needs.pre_job.outputs.should_skip != 'true'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
1
.github/workflows/cla.yml
vendored
1
.github/workflows/cla.yml
vendored
@@ -7,6 +7,7 @@ on:
|
||||
|
||||
jobs:
|
||||
CLAAssistant:
|
||||
if: github.repository == 'laurent22/joplin'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: "CLA Assistant"
|
||||
|
||||
1
.github/workflows/close-stale-issues.yml
vendored
1
.github/workflows/close-stale-issues.yml
vendored
@@ -6,6 +6,7 @@ permissions:
|
||||
issues: write
|
||||
jobs:
|
||||
ProcessStaleIssues:
|
||||
if: github.repository == 'laurent22/joplin'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v4
|
||||
|
||||
6
.github/workflows/github-actions-main.yml
vendored
6
.github/workflows/github-actions-main.yml
vendored
@@ -2,6 +2,7 @@ name: Joplin Continuous Integration
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
pre_job:
|
||||
if: github.repository == 'laurent22/joplin'
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
should_skip: ${{ steps.skip_check.outputs.should_skip }}
|
||||
@@ -14,7 +15,7 @@ jobs:
|
||||
Main:
|
||||
needs: pre_job
|
||||
# We always process server or desktop release tags, because they also publish the release
|
||||
if: needs.pre_job.outputs.should_skip != 'true' || startsWith(github.ref, 'refs/tags/server-v') || startsWith(github.ref, 'refs/tags/v')
|
||||
if: github.repository == 'laurent22/joplin' && (needs.pre_job.outputs.should_skip != 'true' || startsWith(github.ref, 'refs/tags/server-v') || startsWith(github.ref, 'refs/tags/v'))
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
@@ -92,6 +93,7 @@ jobs:
|
||||
APPLE_ASC_PROVIDER: ${{ secrets.APPLE_ASC_PROVIDER }}
|
||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||||
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
||||
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
|
||||
CSC_KEY_PASSWORD: ${{ secrets.APPLE_CSC_KEY_PASSWORD }}
|
||||
CSC_LINK: ${{ secrets.APPLE_CSC_LINK }}
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
@@ -129,7 +131,7 @@ jobs:
|
||||
|
||||
ServerDockerImage:
|
||||
needs: pre_job
|
||||
if: needs.pre_job.outputs.should_skip != 'true'
|
||||
if: github.repository == 'laurent22/joplin' && needs.pre_job.outputs.should_skip != 'true'
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -317,6 +317,7 @@ packages/app-desktop/gui/style/StyledTextInput.js
|
||||
packages/app-desktop/gui/utils/NoteListUtils.js
|
||||
packages/app-desktop/gui/utils/convertToScreenCoordinates.js
|
||||
packages/app-desktop/gui/utils/loadScript.js
|
||||
packages/app-desktop/gulpfile.js
|
||||
packages/app-desktop/plugins/GotoAnything.js
|
||||
packages/app-desktop/services/bridge.js
|
||||
packages/app-desktop/services/commands/stateToWhenClauseContext.js
|
||||
@@ -392,6 +393,7 @@ packages/app-mobile/components/SideMenu.js
|
||||
packages/app-mobile/components/TextInput.js
|
||||
packages/app-mobile/components/app-nav.js
|
||||
packages/app-mobile/components/biometrics/BiometricPopup.js
|
||||
packages/app-mobile/components/biometrics/biometricAuthenticate.js
|
||||
packages/app-mobile/components/biometrics/sensorInfo.js
|
||||
packages/app-mobile/components/getResponsiveValue.js
|
||||
packages/app-mobile/components/getResponsiveValue.test.js
|
||||
@@ -850,6 +852,7 @@ packages/tools/update-readme-download.js
|
||||
packages/tools/update-readme-sponsors.js
|
||||
packages/tools/updateMarkdownDoc.js
|
||||
packages/tools/utils/discourse.js
|
||||
packages/tools/utils/loadSponsors.js
|
||||
packages/tools/utils/translation.js
|
||||
packages/tools/website/build.js
|
||||
packages/tools/website/buildTranslations.js
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
"@joplin/turndown-plugin-gfm",
|
||||
"@joplin/tools",
|
||||
"@joplin/react-native-saf-x",
|
||||
"@joplin/react-native-alarm-notification"
|
||||
"@joplin/react-native-alarm-notification",
|
||||
"@joplin/utils"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -30,6 +30,7 @@ COPY packages/fork-uslug ./packages/fork-uslug
|
||||
COPY packages/htmlpack ./packages/htmlpack
|
||||
COPY packages/renderer ./packages/renderer
|
||||
COPY packages/tools ./packages/tools
|
||||
COPY packages/utils ./packages/utils
|
||||
COPY packages/lib ./packages/lib
|
||||
COPY packages/server ./packages/server
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ A community maintained list of these distributions can be found here: [Unofficia
|
||||
# Sponsors
|
||||
|
||||
<!-- SPONSORS-ORG -->
|
||||
<a href="https://seirei.ne.jp"><img title="Serei Network" width="256" src="https://joplinapp.org/images/sponsors/SeireiNetwork.png"/></a> <a href="https://usrigging.com/"><img title="U.S. Ringing Supply" width="256" src="https://joplinapp.org/images/sponsors/RingingSupply.svg"/></a> <a href="https://www.hosting.de/nextcloud/?mtm_campaign=managed-nextcloud&mtm_kwd=joplinapp&mtm_source=joplinapp-github&mtm_medium=banner"><img title="Hosting.de" width="256" src="https://joplinapp.org/images/sponsors/HostingDe.png"/></a> <a href="https://residence-greece.com/"><img title="Greece Golden Visa" width="256" src="https://joplinapp.org/images/sponsors/ResidenceGreece.jpg"/></a> <a href="https://grundstueckspreise.info/"><img title="SP Software GmbH" width="256" src="https://joplinapp.org/images/sponsors/Grundstueckspreise.png"/></a>
|
||||
<a href="https://seirei.ne.jp"><img title="Serei Network" width="256" src="https://joplinapp.org/images/sponsors/SeireiNetwork.png"/></a> <a href="https://www.hosting.de/nextcloud/?mtm_campaign=managed-nextcloud&mtm_kwd=joplinapp&mtm_source=joplinapp-webseite&mtm_medium=banner"><img title="Hosting.de" width="256" src="https://joplinapp.org/images/sponsors/HostingDe.png"/></a> <a href="https://residence-greece.com/"><img title="Greece Golden Visa" width="256" src="https://joplinapp.org/images/sponsors/ResidenceGreece.jpg"/></a> <a href="https://grundstueckspreise.info/"><img title="SP Software GmbH" width="256" src="https://joplinapp.org/images/sponsors/Grundstueckspreise.png"/></a>
|
||||
<!-- SPONSORS-ORG -->
|
||||
|
||||
* * *
|
||||
@@ -126,6 +126,7 @@ A community maintained list of these distributions can be found here: [Unofficia
|
||||
- [Writing a technical spec](https://github.com/laurent22/joplin/blob/dev/readme/technical_spec.md)
|
||||
- [Desktop application styling](https://github.com/laurent22/joplin/blob/dev/readme/spec/desktop_styling.md)
|
||||
- [Note History spec](https://github.com/laurent22/joplin/blob/dev/readme/spec/history.md)
|
||||
- [Synchronisation spec](https://github.com/laurent22/joplin/blob/dev/readme/spec/sync.md)
|
||||
- [Sync Lock spec](https://github.com/laurent22/joplin/blob/dev/readme/spec/sync_lock.md)
|
||||
- [Synchronous Scroll spec](https://github.com/laurent22/joplin/blob/dev/readme/spec/sync_scroll.md)
|
||||
- [Plugin Architecture spec](https://github.com/laurent22/joplin/blob/dev/readme/spec/plugins.md)
|
||||
|
||||
54
gulpfile.js
54
gulpfile.js
@@ -1,26 +1,52 @@
|
||||
const gulp = require('gulp');
|
||||
const utils = require('./packages/tools/gulp/utils');
|
||||
const execa = require('execa');
|
||||
const { stdout } = require('process');
|
||||
|
||||
const execCommand = async (executableName, args, options = null) => {
|
||||
options = {
|
||||
showInput: true,
|
||||
showStdout: true,
|
||||
showStderr: true,
|
||||
quiet: false,
|
||||
...options,
|
||||
};
|
||||
|
||||
if (options.quiet) {
|
||||
options.showInput = false;
|
||||
options.showStdout = false;
|
||||
options.showStderr = false;
|
||||
}
|
||||
|
||||
if (options.showInput) {
|
||||
stdout.write(`> ${executableName} ${args.join(' ')}\n`);
|
||||
}
|
||||
|
||||
const promise = execa(executableName, args);
|
||||
if (options.showStdout && promise.stdout) promise.stdout.pipe(process.stdout);
|
||||
if (options.showStderr && promise.stderr) promise.stderr.pipe(process.stderr);
|
||||
const result = await promise;
|
||||
return result.stdout.trim();
|
||||
};
|
||||
|
||||
|
||||
const tasks = {
|
||||
updateIgnoredTypeScriptBuild: require('./packages/tools/gulp/tasks/updateIgnoredTypeScriptBuild'),
|
||||
buildCommandIndex: require('./packages/tools/gulp/tasks/buildCommandIndex'),
|
||||
completePublishAll: {
|
||||
fn: async () => {
|
||||
await utils.execCommandVerbose('git', ['add', '-A']);
|
||||
await utils.execCommandVerbose('git', ['commit', '-m', 'Releasing sub-packages']);
|
||||
await execCommand('git', ['add', '-A']);
|
||||
await execCommand('git', ['commit', '-m', 'Releasing sub-packages']);
|
||||
|
||||
// Lerna does some unnecessary auth check that doesn't work with
|
||||
// automation tokens, thus the --no-verify-access. Automation token
|
||||
// is still used for access when publishing even with this flag
|
||||
// (publishing would fail otherwise).
|
||||
// https://github.com/lerna/lerna/issues/2788
|
||||
await utils.execCommandVerbose('lerna', ['publish', 'from-package', '-y', '--no-verify-access']);
|
||||
await execCommand('lerna', ['publish', 'from-package', '-y', '--no-verify-access']);
|
||||
|
||||
await utils.execCommandVerbose('yarn', ['install']);
|
||||
await utils.execCommandVerbose('git', ['add', '-A']);
|
||||
await utils.execCommandVerbose('git', ['commit', '-m', 'Lock file']);
|
||||
await execCommand('yarn', ['install']);
|
||||
await execCommand('git', ['add', '-A']);
|
||||
await execCommand('git', ['commit', '-m', 'Lock file']);
|
||||
|
||||
await utils.execCommandVerbose('git', ['push']);
|
||||
await execCommand('git', ['push']);
|
||||
},
|
||||
},
|
||||
build: {
|
||||
@@ -33,12 +59,14 @@ const tasks = {
|
||||
// faster, especially when having to rebuild after adding a
|
||||
// dependency.
|
||||
if (process.env.BUILD_SEQUENCIAL === '1') {
|
||||
await utils.execCommandVerbose('yarn', ['run', 'buildSequential']);
|
||||
await execCommand('yarn', ['run', 'buildSequential']);
|
||||
} else {
|
||||
await utils.execCommandVerbose('yarn', ['run', 'buildParallel']);
|
||||
await execCommand('yarn', ['run', 'buildParallel']);
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
utils.registerGulpTasks(gulp, tasks);
|
||||
for (const taskName in tasks) {
|
||||
gulp.task(taskName, tasks[taskName].fn);
|
||||
}
|
||||
|
||||
@@ -329,6 +329,7 @@
|
||||
"packages/renderer/MdToHtml/rules/sanitize_html.js": true,
|
||||
"packages/server/db-*.sqlite": true,
|
||||
"packages/server/dist/": true,
|
||||
"packages/utils/dist/": true,
|
||||
"packages/server/temp": true,
|
||||
"packages/server/test.pid": true,
|
||||
"phpunit.xml": true,
|
||||
|
||||
14
package.json
14
package.json
@@ -13,9 +13,9 @@
|
||||
},
|
||||
"scripts": {
|
||||
"buildParallel": "yarn workspaces foreach --verbose --interlaced --parallel --jobs 2 --topological run build && yarn run tsc",
|
||||
"buildSequential": "yarn workspaces foreach --verbose --interlaced --topological run build && yarn run tsc",
|
||||
"buildSequential": "yarn run tsc && yarn workspaces foreach --verbose --interlaced --topological-dev run build",
|
||||
"buildApiDoc": "yarn workspace joplin start apidoc ../../readme/api/references/rest_api.md",
|
||||
"buildCommandIndex": "gulp buildCommandIndex",
|
||||
"buildCommandIndex": "node packages/tools/gulp/tasks/buildCommandIndexRun.js",
|
||||
"buildPluginDoc": "typedoc --name 'Joplin Plugin API Documentation' --mode file -theme './Assets/PluginDocTheme/' --readme './Assets/PluginDocTheme/index.md' --excludeNotExported --excludeExternals --excludePrivate --excludeProtected --out ../joplin-website/docs/api/references/plugin_api packages/lib/services/plugins/api/",
|
||||
"updateMarkdownDoc": "node ./packages/tools/updateMarkdownDoc",
|
||||
"updateNews": "node ./packages/tools/website/updateNews",
|
||||
@@ -53,7 +53,7 @@
|
||||
"test-ci": "yarn workspaces foreach --parallel --verbose --interlaced --jobs 2 run test-ci",
|
||||
"test": "yarn workspaces foreach --parallel --verbose --interlaced --jobs 2 run test",
|
||||
"tsc": "yarn workspaces foreach --parallel --verbose --interlaced run tsc",
|
||||
"updateIgnored": "gulp updateIgnoredTypeScriptBuild",
|
||||
"updateIgnored": "node packages/tools/gulp/tasks/updateIgnoredTypeScriptBuildRun.js",
|
||||
"updatePluginTypes": "./packages/generator-joplin/updateTypes.sh",
|
||||
"watch": "yarn workspaces foreach --parallel --verbose --interlaced --jobs 999 run watch",
|
||||
"watchWebsite": "nodemon --verbose --watch Assets/WebsiteAssets --watch packages/tools/website --watch packages/tools/website/utils --ext md,ts,js,mustache,css,tsx,gif,png,svg --exec \"node packages/tools/website/build.js && http-server --port 8077 ../joplin-website/docs -a localhost\""
|
||||
@@ -64,6 +64,7 @@
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@joplin/utils": "~2.11",
|
||||
"@seiyab/eslint-plugin-react-hooks": "4.5.1-beta.0",
|
||||
"@typescript-eslint/eslint-plugin": "5.48.2",
|
||||
"@typescript-eslint/parser": "5.48.2",
|
||||
@@ -74,12 +75,13 @@
|
||||
"eslint-plugin-jest": "27.2.1",
|
||||
"eslint-plugin-promise": "6.1.1",
|
||||
"eslint-plugin-react": "7.32.0",
|
||||
"fs-extra": "11.1.0",
|
||||
"execa": "5.1.1",
|
||||
"fs-extra": "11.1.1",
|
||||
"glob": "8.1.0",
|
||||
"gulp": "4.0.2",
|
||||
"husky": "3.1.0",
|
||||
"lerna": "3.22.1",
|
||||
"lint-staged": "13.1.2",
|
||||
"lint-staged": "13.2.0",
|
||||
"madge": "6.0.0",
|
||||
"npm-package-json-lint": "6.4.0",
|
||||
"typedoc": "0.17.8",
|
||||
@@ -89,7 +91,7 @@
|
||||
"@types/fs-extra": "9.0.13",
|
||||
"http-server": "14.1.1",
|
||||
"node-gyp": "9.3.1",
|
||||
"nodemon": "2.0.21"
|
||||
"nodemon": "2.0.22"
|
||||
},
|
||||
"packageManager": "yarn@3.3.1",
|
||||
"resolutions": {
|
||||
|
||||
@@ -8,7 +8,7 @@ const Resource = require('@joplin/lib/models/Resource').default;
|
||||
const Setting = require('@joplin/lib/models/Setting').default;
|
||||
const reducer = require('@joplin/lib/reducer').default;
|
||||
const { defaultState } = require('@joplin/lib/reducer');
|
||||
const { splitCommandString } = require('@joplin/lib/string-utils.js');
|
||||
const { splitCommandString } = require('@joplin/utils');
|
||||
const { reg } = require('@joplin/lib/registry.js');
|
||||
const { _ } = require('@joplin/lib/locale');
|
||||
const shim = require('@joplin/lib/shim').default;
|
||||
|
||||
@@ -9,7 +9,8 @@ const Tag = require('@joplin/lib/models/Tag').default;
|
||||
const Setting = require('@joplin/lib/models/Setting').default;
|
||||
const { reg } = require('@joplin/lib/registry.js');
|
||||
const { fileExtension } = require('@joplin/lib/path-utils');
|
||||
const { splitCommandString, splitCommandBatch } = require('@joplin/lib/string-utils');
|
||||
const { splitCommandString } = require('@joplin/utils');
|
||||
const { splitCommandBatch } = require('@joplin/lib/string-utils');
|
||||
const { _ } = require('@joplin/lib/locale');
|
||||
const fs = require('fs-extra');
|
||||
const { cliUtils } = require('./cli-utils.js');
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const fs = require('fs-extra');
|
||||
const BaseCommand = require('./base-command').default;
|
||||
const { splitCommandString } = require('@joplin/lib/string-utils.js');
|
||||
const { splitCommandString } = require('@joplin/utils');
|
||||
const uuid = require('@joplin/lib/uuid').default;
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('@joplin/lib/locale');
|
||||
|
||||
@@ -30,22 +30,24 @@
|
||||
2019,
|
||||
2020,
|
||||
2021,
|
||||
2022
|
||||
2022,
|
||||
2023
|
||||
],
|
||||
"owner": "Laurent Cozic"
|
||||
},
|
||||
"version": "2.10.3",
|
||||
"version": "2.11.0",
|
||||
"bin": "./main.js",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@joplin/lib": "~2.10",
|
||||
"@joplin/renderer": "~2.10",
|
||||
"@joplin/lib": "~2.11",
|
||||
"@joplin/renderer": "~2.11",
|
||||
"@joplin/utils": "~2.11",
|
||||
"aws-sdk": "2.1290.0",
|
||||
"chalk": "4.1.2",
|
||||
"compare-version": "0.1.2",
|
||||
"fs-extra": "11.1.0",
|
||||
"fs-extra": "11.1.1",
|
||||
"html-entities": "1.4.0",
|
||||
"image-type": "3.1.0",
|
||||
"keytar": "7.9.0",
|
||||
@@ -57,7 +59,7 @@
|
||||
"server-destroy": "1.0.1",
|
||||
"sharp": "0.31.3",
|
||||
"sprintf-js": "1.1.2",
|
||||
"sqlite3": "5.1.4",
|
||||
"sqlite3": "5.1.6",
|
||||
"string-padding": "1.0.2",
|
||||
"strip-ansi": "6.0.1",
|
||||
"tcp-port-used": "1.0.2",
|
||||
@@ -68,7 +70,7 @@
|
||||
"yargs-parser": "21.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@joplin/tools": "~2.10",
|
||||
"@joplin/tools": "~2.11",
|
||||
"@types/fs-extra": "9.0.13",
|
||||
"@types/jest": "29.2.6",
|
||||
"@types/node": "18.11.18",
|
||||
|
||||
@@ -47,9 +47,11 @@ describe('services_plugins_RepositoryApi', () => {
|
||||
|
||||
it('should tell if a plugin can be updated', (async () => {
|
||||
const api = await newRepoApi();
|
||||
expect(await api.pluginCanBeUpdated('org.joplinapp.plugins.ToggleSidebars', '1.0.0')).toBe(true);
|
||||
expect(await api.pluginCanBeUpdated('org.joplinapp.plugins.ToggleSidebars', '1.0.2')).toBe(false);
|
||||
expect(await api.pluginCanBeUpdated('does.not.exist', '1.0.0')).toBe(false);
|
||||
|
||||
expect(await api.pluginCanBeUpdated('org.joplinapp.plugins.ToggleSidebars', '1.0.0', '3.0.0')).toBe(true);
|
||||
expect(await api.pluginCanBeUpdated('org.joplinapp.plugins.ToggleSidebars', '1.0.0', '1.0.0')).toBe(false);
|
||||
expect(await api.pluginCanBeUpdated('org.joplinapp.plugins.ToggleSidebars', '1.0.2', '3.0.0')).toBe(false);
|
||||
expect(await api.pluginCanBeUpdated('does.not.exist', '1.0.0', '3.0.0')).toBe(false);
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
import * as fs from 'fs-extra';
|
||||
import { homedir } from 'os';
|
||||
import { execCommand2 } from '@joplin/tools/tool-utils';
|
||||
import { execCommand } from '@joplin/utils';
|
||||
import { chdir } from 'process';
|
||||
|
||||
const minUserNum = 1;
|
||||
@@ -66,7 +66,7 @@ const processUser = async (userNum: number) => {
|
||||
|
||||
await chdir(cliDir);
|
||||
|
||||
await execCommand2(['yarn', 'run', 'start-no-build', '--', '--profile', profileDir, 'batch', commandFile]);
|
||||
await execCommand(['yarn', 'run', 'start-no-build', '--', '--profile', profileDir, 'batch', commandFile]);
|
||||
} catch (error) {
|
||||
console.error(`Could not process user ${userNum}:`, error);
|
||||
} finally {
|
||||
@@ -90,7 +90,7 @@ const main = async () => {
|
||||
|
||||
// Build the app once before starting, because we'll use start-no-build to
|
||||
// run the scripts (faster)
|
||||
await execCommand2(['yarn', 'run', 'build']);
|
||||
await execCommand(['yarn', 'run', 'build']);
|
||||
|
||||
const focusUserNum = 0;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"manifest_version": 2,
|
||||
"name": "Joplin Web Clipper [DEV]",
|
||||
"version": "2.10.0",
|
||||
"version": "2.11.2",
|
||||
"description": "Capture and save web pages and screenshots from your browser to Joplin.",
|
||||
"homepage_url": "https://joplinapp.org",
|
||||
"content_security_policy": "script-src 'self'; object-src 'self'",
|
||||
|
||||
@@ -126,4 +126,4 @@
|
||||
"react-app"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ export default function(props: Props) {
|
||||
let cancelled = false;
|
||||
|
||||
async function fetchPluginIds() {
|
||||
const pluginIds = await repoApi().canBeUpdatedPlugins(pluginItems.map(p => p.manifest));
|
||||
const pluginIds = await repoApi().canBeUpdatedPlugins(pluginItems.map(p => p.manifest), pluginService.appVersion);
|
||||
if (cancelled) return;
|
||||
const conv: Record<string, boolean> = {};
|
||||
pluginIds.forEach(id => conv[id] = true);
|
||||
@@ -155,7 +155,7 @@ export default function(props: Props) {
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [manifestsLoaded, pluginItems]);
|
||||
}, [manifestsLoaded, pluginItems, pluginService.appVersion]);
|
||||
|
||||
const onDelete = useCallback(async (event: ItemEvent) => {
|
||||
const item = event.item;
|
||||
|
||||
@@ -21,7 +21,7 @@ import checkForUpdates from '../checkForUpdates';
|
||||
const { connect } = require('react-redux');
|
||||
import { reg } from '@joplin/lib/registry';
|
||||
import { ProfileConfig } from '@joplin/lib/services/profileConfig/types';
|
||||
import PluginService from '@joplin/lib/services/plugins/PluginService';
|
||||
import PluginService, { PluginSettings } from '@joplin/lib/services/plugins/PluginService';
|
||||
const packageInfo = require('../packageInfo.js');
|
||||
const { clipboard } = require('electron');
|
||||
const Menu = bridge().Menu;
|
||||
@@ -128,6 +128,7 @@ interface Props {
|
||||
customCss: string;
|
||||
locale: string;
|
||||
profileConfig: ProfileConfig;
|
||||
pluginSettings: PluginSettings;
|
||||
}
|
||||
|
||||
const commandNames: string[] = menuCommandNames();
|
||||
@@ -487,8 +488,7 @@ function useMenu(props: Props) {
|
||||
}
|
||||
|
||||
function _showAbout() {
|
||||
const v = versionInfo(packageInfo, PluginService.instance().plugins);
|
||||
|
||||
const v = versionInfo(packageInfo, PluginService.instance().enabledPlugins(props.pluginSettings));
|
||||
|
||||
const copyToClipboard = bridge().showMessageBox(v.message, {
|
||||
icon: `${bridge().electronApp().buildDir()}/icons/128x128.png`,
|
||||
@@ -931,6 +931,7 @@ function useMenu(props: Props) {
|
||||
props['spellChecker.languages'],
|
||||
// eslint-disable-next-line @seiyab/react-hooks/exhaustive-deps -- Old code before rule was applied
|
||||
props['spellChecker.enabled'],
|
||||
props.pluginSettings,
|
||||
props.customCss,
|
||||
props.locale,
|
||||
props.profileConfig,
|
||||
@@ -986,6 +987,7 @@ const mapStateToProps = (state: AppState) => {
|
||||
['folders.sortOrder.field']: state.settings['folders.sortOrder.field'],
|
||||
['notes.sortOrder.reverse']: state.settings['notes.sortOrder.reverse'],
|
||||
['folders.sortOrder.reverse']: state.settings['folders.sortOrder.reverse'],
|
||||
pluginSettings: state.settings['plugins.states'],
|
||||
showNoteCounts: state.settings.showNoteCounts,
|
||||
uncompletedTodosOnTop: state.settings.uncompletedTodosOnTop,
|
||||
showCompletedTodos: state.settings.showCompletedTodos,
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useCallback, useMemo } from 'react';
|
||||
import { ResourceInfos } from './types';
|
||||
import markupLanguageUtils from '../../../utils/markupLanguageUtils';
|
||||
import Setting from '@joplin/lib/models/Setting';
|
||||
import shim from '@joplin/lib/shim';
|
||||
|
||||
const { themeStyle } = require('@joplin/lib/theme');
|
||||
import Note from '@joplin/lib/models/Note';
|
||||
@@ -23,6 +24,7 @@ export interface MarkupToHtmlOptions {
|
||||
useCustomPdfViewer?: boolean;
|
||||
noteId?: string;
|
||||
vendorDir?: string;
|
||||
platformName?: string;
|
||||
}
|
||||
|
||||
export default function useMarkupToHtml(deps: HookDependencies) {
|
||||
@@ -40,6 +42,7 @@ export default function useMarkupToHtml(deps: HookDependencies) {
|
||||
options = {
|
||||
replaceResourceInternalToExternalLinks: false,
|
||||
resourceInfos: {},
|
||||
platformName: shim.platformName(),
|
||||
...options,
|
||||
};
|
||||
|
||||
|
||||
@@ -241,6 +241,7 @@ const NoteListComponent = (props: Props) => {
|
||||
event.dataTransfer.setDragImage(new Image(), 1, 1);
|
||||
event.dataTransfer.clearData();
|
||||
event.dataTransfer.setData('text/x-jop-note-ids', JSON.stringify(noteIds));
|
||||
event.dataTransfer.effectAllowed = 'move';
|
||||
};
|
||||
|
||||
const renderItem = useCallback((item: any, index: number) => {
|
||||
|
||||
@@ -12,9 +12,9 @@ const { connect } = require('react-redux');
|
||||
const styled = require('styled-components').default;
|
||||
|
||||
enum BaseBreakpoint {
|
||||
Sm = 160,
|
||||
Md = 190,
|
||||
Lg = 40,
|
||||
Sm = 75,
|
||||
Md = 80,
|
||||
Lg = 120,
|
||||
Xl = 474,
|
||||
}
|
||||
|
||||
@@ -50,7 +50,9 @@ const StyledButton = styled(Button)`
|
||||
width: auto;
|
||||
height: 26px;
|
||||
min-height: 26px;
|
||||
min-width: 37px;
|
||||
max-width: none;
|
||||
white-space: nowrap;
|
||||
|
||||
.fa, .fas {
|
||||
font-size: 11px;
|
||||
|
||||
@@ -48,6 +48,15 @@ const StyledFoldersHolder = styled.div`
|
||||
}}
|
||||
}
|
||||
`;
|
||||
const TagsHolder = styled.div`
|
||||
// linux bug: https://github.com/laurent22/joplin/issues/8000
|
||||
// solution ref: https://github.com/laurent22/joplin/issues/7506#issuecomment-1447101057
|
||||
& a.list-item {
|
||||
${shim.isLinux() && {
|
||||
opacity: 1,
|
||||
}}
|
||||
}
|
||||
`;
|
||||
|
||||
interface Props {
|
||||
themeId: number;
|
||||
@@ -738,9 +747,9 @@ const SidebarComponent = (props: Props) => {
|
||||
tagItemsOrder_.current = result.order;
|
||||
|
||||
items.push(
|
||||
<div className="tags" key="tag_items" style={{ display: props.tagHeaderIsExpanded ? 'block' : 'none' }}>
|
||||
<TagsHolder className="tags" key="tag_items" style={{ display: props.tagHeaderIsExpanded ? 'block' : 'none' }}>
|
||||
{tagItems}
|
||||
</div>
|
||||
</TagsHolder>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -56,6 +56,19 @@ if (typeof module !== 'undefined') {
|
||||
|
||||
const markJsUtils = {};
|
||||
|
||||
const isInsideContainer = (node, tagName) => {
|
||||
if (!node) return false;
|
||||
|
||||
tagName = tagName.toLowerCase();
|
||||
|
||||
while (node) {
|
||||
if (node.tagName && node.tagName.toLowerCase() === tagName) return true;
|
||||
node = node.parentNode;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
markJsUtils.markKeyword = (mark, keyword, stringUtils, extraOptions = null) => {
|
||||
if (typeof keyword === 'string') {
|
||||
keyword = {
|
||||
@@ -71,12 +84,13 @@ markJsUtils.markKeyword = (mark, keyword, stringUtils, extraOptions = null) => {
|
||||
if (isBasicSearch) accuracy = 'partially';
|
||||
if (keyword.type === 'regex') {
|
||||
accuracy = 'complementary';
|
||||
// Remove the trailing wildcard and "accuracy = complementary" will take care of
|
||||
// highlighting the relevant keywords.
|
||||
// Remove the trailing wildcard and "accuracy = complementary" will take
|
||||
// care of highlighting the relevant keywords.
|
||||
|
||||
// Known bug: it will also highlight word that contain the term as a suffix for example for "ent*", it will highlight "present"
|
||||
// which is incorrect (it should only highlight what starts with "ent") but for now will do. Mark.js doesn't have an option
|
||||
// to tweak this behaviour.
|
||||
// Known bug: it will also highlight word that contain the term as a
|
||||
// suffix for example for "ent*", it will highlight "present" which is
|
||||
// incorrect (it should only highlight what starts with "ent") but for
|
||||
// now will do. Mark.js doesn't have an option to tweak this behaviour.
|
||||
value = keyword.value.substr(0, keyword.value.length - 1);
|
||||
}
|
||||
|
||||
@@ -86,6 +100,18 @@ markJsUtils.markKeyword = (mark, keyword, stringUtils, extraOptions = null) => {
|
||||
{},
|
||||
{
|
||||
accuracy: accuracy,
|
||||
filter: (node, _term, _totalCounter, _counter) => {
|
||||
// We exclude SVG because it creates a "<mark>" tag inside
|
||||
// the document, which is not a valid SVG tag. As a result
|
||||
// the content within that tag disappears.
|
||||
//
|
||||
// mark.js has an "exclude" parameter, but it doesn't work
|
||||
// so we use "filter" instead.
|
||||
//
|
||||
// https://github.com/joplin/plugin-abc-sheet-music
|
||||
if (isInsideContainer(node, 'SVG')) return false;
|
||||
return true;
|
||||
},
|
||||
},
|
||||
extraOptions
|
||||
)
|
||||
|
||||
@@ -2,6 +2,7 @@ const gulp = require('gulp');
|
||||
const utils = require('@joplin/tools/gulp/utils');
|
||||
const compileSass = require('@joplin/tools/compileSass');
|
||||
const compilePackageInfo = require('@joplin/tools/compilePackageInfo');
|
||||
const bundleDefaultPlugins = require('@joplin/tools/bundleDefaultPlugins');
|
||||
|
||||
const tasks = {
|
||||
compileScripts: {
|
||||
@@ -35,6 +36,11 @@ const tasks = {
|
||||
);
|
||||
},
|
||||
},
|
||||
bundleDefaultPlugins: {
|
||||
fn: async () => {
|
||||
await bundleDefaultPlugins();
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
utils.registerGulpTasks(gulp, tasks);
|
||||
@@ -1,11 +1,12 @@
|
||||
{
|
||||
"name": "@joplin/app-desktop",
|
||||
"version": "2.10.10",
|
||||
"version": "2.11.1",
|
||||
"description": "Joplin for Desktop",
|
||||
"main": "main.js",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dist": "yarn run electronRebuild && npx electron-builder",
|
||||
"dist": "yarn run bundleDefaultPlugins && yarn run electronRebuild && npx electron-builder",
|
||||
"bundleDefaultPlugins": "gulp bundleDefaultPlugins",
|
||||
"build": "gulp build",
|
||||
"postinstall": "yarn run build",
|
||||
"electronBuilder": "gulp electronBuilder",
|
||||
@@ -90,7 +91,10 @@
|
||||
"CFBundleURLName": "org.joplinapp.x-callback-url"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"binaries": [
|
||||
"Contents/Resources/build/defaultPlugins/io.github.jackgruber.backup/plugin.jpl"
|
||||
]
|
||||
},
|
||||
"linux": {
|
||||
"icon": "../../Assets/LinuxIcons",
|
||||
@@ -107,7 +111,9 @@
|
||||
},
|
||||
"homepage": "https://github.com/laurent22/joplin#readme",
|
||||
"devDependencies": {
|
||||
"@joplin/tools": "~2.10",
|
||||
"@electron/notarize": "1.2.3",
|
||||
"@electron/rebuild": "3.2.10",
|
||||
"@joplin/tools": "~2.11",
|
||||
"@testing-library/react-hooks": "8.0.1",
|
||||
"@types/jest": "29.2.6",
|
||||
"@types/node": "18.11.18",
|
||||
@@ -115,9 +121,7 @@
|
||||
"@types/react-redux": "7.1.25",
|
||||
"@types/styled-components": "5.1.26",
|
||||
"electron": "19.1.4",
|
||||
"electron-builder": "23.6.0",
|
||||
"electron-notarize": "1.2.2",
|
||||
"electron-rebuild": "3.2.9",
|
||||
"electron-builder": "24.1.2",
|
||||
"glob": "8.1.0",
|
||||
"gulp": "4.0.2",
|
||||
"jest": "29.4.3",
|
||||
@@ -125,6 +129,7 @@
|
||||
"js-sha512": "0.8.0",
|
||||
"nan": "2.17.0",
|
||||
"react-test-renderer": "18.2.0",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "4.9.4"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
@@ -136,9 +141,9 @@
|
||||
"@electron/remote": "2.0.9",
|
||||
"@fortawesome/fontawesome-free": "5.15.4",
|
||||
"@joeattardi/emoji-button": "4.6.4",
|
||||
"@joplin/lib": "~2.10",
|
||||
"@joplin/pdf-viewer": "~2.10",
|
||||
"@joplin/renderer": "~2.10",
|
||||
"@joplin/lib": "~2.11",
|
||||
"@joplin/pdf-viewer": "~2.11",
|
||||
"@joplin/renderer": "~2.11",
|
||||
"async-mutex": "0.4.0",
|
||||
"codemirror": "5.65.9",
|
||||
"color": "3.2.1",
|
||||
@@ -147,7 +152,7 @@
|
||||
"debounce": "1.2.1",
|
||||
"electron-window-state": "5.0.3",
|
||||
"formatcoords": "1.1.3",
|
||||
"fs-extra": "11.1.0",
|
||||
"fs-extra": "11.1.1",
|
||||
"highlight.js": "11.7.0",
|
||||
"immer": "7.0.15",
|
||||
"keytar": "7.9.0",
|
||||
@@ -163,15 +168,15 @@
|
||||
"react-datetime": "3.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-redux": "8.0.5",
|
||||
"react-select": "5.7.0",
|
||||
"react-select": "5.7.2",
|
||||
"react-toggle-button": "2.2.0",
|
||||
"react-tooltip": "4.5.1",
|
||||
"redux": "4.2.1",
|
||||
"reselect": "4.1.7",
|
||||
"roboto-fontface": "0.10.0",
|
||||
"smalltalk": "2.5.1",
|
||||
"sqlite3": "5.1.4",
|
||||
"styled-components": "5.3.8",
|
||||
"sqlite3": "5.1.6",
|
||||
"styled-components": "5.3.9",
|
||||
"styled-system": "5.1.5",
|
||||
"taboverride": "4.0.3",
|
||||
"tinymce": "5.10.6"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const electron_notarize = require('electron-notarize');
|
||||
const electron_notarize = require('@electron/notarize');
|
||||
const execCommand = require('./execCommand');
|
||||
|
||||
function isDesktopAppTag(tagName) {
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"include": [
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
"include": [
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
],
|
||||
"exclude": [
|
||||
"**/node_modules",
|
||||
"**/dist",
|
||||
"gulpfile.ts",
|
||||
],
|
||||
"compilerOptions": {
|
||||
"types": [
|
||||
"jest",
|
||||
"node"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
module.exports = {
|
||||
bracketSpacing: false,
|
||||
jsxBracketSameLine: true,
|
||||
singleQuote: true,
|
||||
trailingComma: 'all',
|
||||
};
|
||||
@@ -150,8 +150,8 @@ android {
|
||||
applicationId "net.cozic.joplin"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 2097684
|
||||
versionName "2.10.8"
|
||||
versionCode 2097687
|
||||
versionName "2.11.2"
|
||||
// ndk {
|
||||
// abiFilters "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
|
||||
// }
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* @jest-environment jsdom
|
||||
*/
|
||||
|
||||
|
||||
import { EditorSettings } from '../types';
|
||||
import { initCodeMirror } from './CodeMirror';
|
||||
import { themeStyle } from '@joplin/lib/theme';
|
||||
@@ -9,6 +10,8 @@ import Setting from '@joplin/lib/models/Setting';
|
||||
import { forceParsing } from '@codemirror/language';
|
||||
import loadLangauges from './testUtil/loadLanguages';
|
||||
|
||||
import { expect, describe, it } from '@jest/globals';
|
||||
|
||||
|
||||
const createEditorSettings = (themeId: number) => {
|
||||
const themeData = themeStyle(themeId);
|
||||
@@ -23,6 +26,14 @@ const createEditorSettings = (themeId: number) => {
|
||||
};
|
||||
|
||||
describe('CodeMirror', () => {
|
||||
// This checks for a regression -- occasionally, when updating packages,
|
||||
// syntax highlighting in the CodeMirror editor stops working. This is usually
|
||||
// fixed by
|
||||
// 1. removing all `@codemirror/` and `@lezer/` dependencies from yarn.lock,
|
||||
// 2. upgrading all CodeMirror packages to the latest versions in package.json, and
|
||||
// 3. re-running `yarn install`.
|
||||
//
|
||||
// See https://github.com/laurent22/joplin/issues/7253
|
||||
it('should give headings a different style', async () => {
|
||||
const headerLineText = '# Testing...';
|
||||
const initialText = `${headerLineText}\nThis is a test.`;
|
||||
|
||||
@@ -30,6 +30,7 @@ interface Props {
|
||||
initialSelection?: Selection;
|
||||
style: ViewStyle;
|
||||
contentStyle?: ViewStyle;
|
||||
toolbarEnabled: boolean;
|
||||
|
||||
onChange: ChangeEventHandler;
|
||||
onSelectionChange: SelectionChangeEventHandler;
|
||||
@@ -364,6 +365,19 @@ function NoteEditor(props: Props, ref: any) {
|
||||
console.error('NoteEditor: webview error');
|
||||
}, []);
|
||||
|
||||
const toolbar = <MarkdownToolbar
|
||||
style={{
|
||||
// Don't show the markdown toolbar if there isn't enough space
|
||||
// for it:
|
||||
flexShrink: 1,
|
||||
}}
|
||||
editorSettings={editorSettings}
|
||||
editorControl={editorControl}
|
||||
selectionState={selectionState}
|
||||
searchState={searchState}
|
||||
onAttach={props.onAttach}
|
||||
/>;
|
||||
|
||||
// - `scrollEnabled` prevents iOS from scrolling the document (has no effect on Android)
|
||||
// when an editable region (e.g. a the full-screen NoteEditor) is focused.
|
||||
return (
|
||||
@@ -401,18 +415,7 @@ function NoteEditor(props: Props, ref: any) {
|
||||
searchState={searchState}
|
||||
/>
|
||||
|
||||
<MarkdownToolbar
|
||||
style={{
|
||||
// Don't show the markdown toolbar if there isn't enough space
|
||||
// for it:
|
||||
flexShrink: 1,
|
||||
}}
|
||||
editorSettings={editorSettings}
|
||||
editorControl={editorControl}
|
||||
selectionState={selectionState}
|
||||
searchState={searchState}
|
||||
onAttach={props.onAttach}
|
||||
/>
|
||||
{props.toolbarEnabled ? toolbar : null}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,9 +2,12 @@ const React = require('react');
|
||||
import Setting from '@joplin/lib/models/Setting';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { View, Dimensions, Alert, Button } from 'react-native';
|
||||
import FingerprintScanner from 'react-native-fingerprint-scanner';
|
||||
import { SensorInfo } from './sensorInfo';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import Logger from '@joplin/lib/Logger';
|
||||
import biometricAuthenticate from './biometricAuthenticate';
|
||||
|
||||
const logger = Logger.create('BiometricPopup');
|
||||
|
||||
interface Props {
|
||||
themeId: number;
|
||||
@@ -13,24 +16,36 @@ interface Props {
|
||||
}
|
||||
|
||||
export default (props: Props) => {
|
||||
const [initialPromptDone, setInitialPromptDone] = useState(Setting.value('security.biometricsInitialPromptDone'));
|
||||
const [display, setDisplay] = useState(!!props.sensorInfo.supportedSensors && (props.sensorInfo.enabled || !initialPromptDone));
|
||||
// The initial prompt is there so that the user can choose to opt-in to
|
||||
// biometrics auth the first time the app is launched. However since it
|
||||
// doesn't work properly, we disable it. We only want the user to enable the
|
||||
// feature after they've read the description in the config screen.
|
||||
const [initialPromptDone, setInitialPromptDone] = useState(true); // useState(Setting.value('security.biometricsInitialPromptDone'));
|
||||
const [display, setDisplay] = useState(props.sensorInfo.enabled || !initialPromptDone);
|
||||
const [tryBiometricsCheck, setTryBiometricsCheck] = useState(initialPromptDone);
|
||||
|
||||
logger.info('Render start');
|
||||
logger.info('initialPromptDone', initialPromptDone);
|
||||
logger.info('display', display);
|
||||
logger.info('tryBiometricsCheck', tryBiometricsCheck);
|
||||
logger.info('props.sensorInfo', props.sensorInfo);
|
||||
|
||||
useEffect(() => {
|
||||
if (!display || !tryBiometricsCheck) return;
|
||||
|
||||
const biometricsCheck = async () => {
|
||||
logger.info('biometricsCheck: start');
|
||||
|
||||
try {
|
||||
await FingerprintScanner.authenticate({ description: _('Verify your identity') });
|
||||
setTryBiometricsCheck(false);
|
||||
await biometricAuthenticate();
|
||||
setDisplay(false);
|
||||
} catch (error) {
|
||||
Alert.alert(_('Could not verify your identify'), error.message);
|
||||
setTryBiometricsCheck(false);
|
||||
} finally {
|
||||
FingerprintScanner.release();
|
||||
Alert.alert(error.message);
|
||||
}
|
||||
|
||||
setTryBiometricsCheck(false);
|
||||
|
||||
logger.info('biometricsCheck: end');
|
||||
};
|
||||
|
||||
void biometricsCheck();
|
||||
@@ -41,6 +56,9 @@ export default (props: Props) => {
|
||||
if (!display) return;
|
||||
|
||||
const complete = (enableBiometrics: boolean) => {
|
||||
logger.info('complete: start');
|
||||
logger.info('complete: enableBiometrics:', enableBiometrics);
|
||||
|
||||
setInitialPromptDone(true);
|
||||
Setting.setValue('security.biometricsInitialPromptDone', true);
|
||||
Setting.setValue('security.biometricsEnabled', enableBiometrics);
|
||||
@@ -55,6 +73,8 @@ export default (props: Props) => {
|
||||
type: 'BIOMETRICS_DONE_SET',
|
||||
value: true,
|
||||
});
|
||||
|
||||
logger.info('complete: end');
|
||||
};
|
||||
|
||||
Alert.alert(
|
||||
@@ -73,7 +93,7 @@ export default (props: Props) => {
|
||||
},
|
||||
]
|
||||
);
|
||||
}, [initialPromptDone, props.sensorInfo.supportedSensors, display, props.dispatch]);
|
||||
}, [initialPromptDone, display, props.dispatch]);
|
||||
|
||||
const windowSize = useMemo(() => {
|
||||
return {
|
||||
@@ -83,12 +103,18 @@ export default (props: Props) => {
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
logger.info('effect 1: start');
|
||||
|
||||
if (!display) {
|
||||
logger.info('effect 1: display', display);
|
||||
|
||||
props.dispatch({
|
||||
type: 'BIOMETRICS_DONE_SET',
|
||||
value: true,
|
||||
});
|
||||
}
|
||||
|
||||
logger.info('effect 1: end');
|
||||
}, [display, props.dispatch]);
|
||||
|
||||
const renderTryAgainButton = () => {
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import Logger from '@joplin/lib/Logger';
|
||||
import FingerprintScanner, { Errors } from 'react-native-fingerprint-scanner';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
|
||||
const logger = Logger.create('biometricAuthenticate');
|
||||
|
||||
export default async () => {
|
||||
try {
|
||||
logger.info('Authenticate...');
|
||||
await FingerprintScanner.authenticate({ description: _('Verify your identity') });
|
||||
logger.info('Authenticate done');
|
||||
} catch (error) {
|
||||
const errorName = (error as Errors).name;
|
||||
|
||||
let errorMessage = error.message;
|
||||
if (errorName === 'FingerprintScannerNotEnrolled' || errorName === 'FingerprintScannerNotAvailable') {
|
||||
errorMessage = _('Biometric unlock is not setup on the device. Please set it up in order to unlock Joplin. If the device is on lockout, consider switching it off and on to reset biometrics scanning.');
|
||||
}
|
||||
|
||||
error.message = _('Could not verify your identify: %s', errorMessage);
|
||||
|
||||
logger.warn(error);
|
||||
|
||||
throw error;
|
||||
} finally {
|
||||
FingerprintScanner.release();
|
||||
}
|
||||
};
|
||||
@@ -1,5 +1,7 @@
|
||||
import Logger from '@joplin/lib/Logger';
|
||||
import Setting from '@joplin/lib/models/Setting';
|
||||
import FingerprintScanner from 'react-native-fingerprint-scanner';
|
||||
const logger = Logger.create('sensorInfo');
|
||||
|
||||
export interface SensorInfo {
|
||||
enabled: boolean;
|
||||
@@ -8,11 +10,40 @@ export interface SensorInfo {
|
||||
}
|
||||
|
||||
export default async (): Promise<SensorInfo> => {
|
||||
// Early exit if the feature is disabled, so that we don't make any
|
||||
// FingerprintScanner scanner calls, since it seems they can fail and freeze
|
||||
// the app.
|
||||
|
||||
logger.info('Start');
|
||||
logger.info('security.biometricsEnabled', Setting.value('security.biometricsEnabled'));
|
||||
|
||||
if (!Setting.value('security.biometricsEnabled')) {
|
||||
return {
|
||||
enabled: false,
|
||||
sensorsHaveChanged: false,
|
||||
supportedSensors: '',
|
||||
};
|
||||
}
|
||||
|
||||
let hasChanged = false;
|
||||
let supportedSensors = '';
|
||||
|
||||
try {
|
||||
logger.info('Getting isSensorAvailable...');
|
||||
|
||||
// Note: If `isSensorAvailable()` doesn't return anything, it seems we
|
||||
// could assume that biometrics are not setup on the device, and thus we
|
||||
// can unlock the app. However that's not always correct - on some
|
||||
// devices (eg Galaxy S22), `isSensorAvailable()` will return nothing if
|
||||
// the device is on lockout - i.e. if the user gave the wrong
|
||||
// fingerprint multiple times.
|
||||
//
|
||||
// So we definitely can't unlock the app in that case, and it means
|
||||
// `isSensorAvailable()` is pretty much useless. Instead we ask for
|
||||
// fingerprint when the user turns on the feature and at that point we
|
||||
// know if the device supports biometrics or not.
|
||||
const result = await FingerprintScanner.isSensorAvailable();
|
||||
logger.info('isSensorAvailable result', result);
|
||||
supportedSensors = result;
|
||||
|
||||
if (result) {
|
||||
@@ -22,7 +53,7 @@ export default async (): Promise<SensorInfo> => {
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Could not check for biometrics sensor:', error);
|
||||
logger.warn('Could not check for biometrics sensor:', error);
|
||||
Setting.setValue('security.biometricsSupportedSensors', '');
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ const { themeStyle } = require('../global-style.js');
|
||||
const shared = require('@joplin/lib/components/shared/config-shared.js');
|
||||
import SyncTargetRegistry from '@joplin/lib/SyncTargetRegistry';
|
||||
import { openDocumentTree } from '@joplin/react-native-saf-x';
|
||||
import biometricAuthenticate from '../biometrics/biometricAuthenticate';
|
||||
|
||||
class ConfigScreenComponent extends BaseScreenComponent {
|
||||
public static navigationOptions(): any {
|
||||
@@ -463,7 +464,7 @@ class ConfigScreenComponent extends BaseScreenComponent {
|
||||
<Text key="label" style={this.styles().switchSettingText}>
|
||||
{label}
|
||||
</Text>
|
||||
<Switch key="control" style={this.styles().switchSettingControl} trackColor={{ false: theme.dividerColor }} value={value} onValueChange={(value: any) => updateSettingValue(key, value)} />
|
||||
<Switch key="control" style={this.styles().switchSettingControl} trackColor={{ false: theme.dividerColor }} value={value} onValueChange={(value: any) => void updateSettingValue(key, value)} />
|
||||
</View>
|
||||
{descriptionComp}
|
||||
</View>
|
||||
@@ -474,13 +475,39 @@ class ConfigScreenComponent extends BaseScreenComponent {
|
||||
return !hasDescription ? this.styles().settingContainer : this.styles().settingContainerNoBottomBorder;
|
||||
}
|
||||
|
||||
private async handleSetting(key: string, value: any): Promise<boolean> {
|
||||
// When the user tries to enable biometrics unlock, we ask for the
|
||||
// fingerprint or Face ID, and if it's correct we save immediately. If
|
||||
// it's not, we don't turn on the setting.
|
||||
if (key === 'security.biometricsEnabled' && !!value) {
|
||||
try {
|
||||
await biometricAuthenticate();
|
||||
shared.updateSettingValue(this, key, value);
|
||||
await this.saveButton_press();
|
||||
} catch (error) {
|
||||
shared.updateSettingValue(this, key, false);
|
||||
Alert.alert(error.message);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (key === 'security.biometricsEnabled' && !value) {
|
||||
shared.updateSettingValue(this, key, value);
|
||||
await this.saveButton_press();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public settingToComponent(key: string, value: any) {
|
||||
const themeId = this.props.themeId;
|
||||
const theme = themeStyle(themeId);
|
||||
const output: any = null;
|
||||
|
||||
const updateSettingValue = (key: string, value: any) => {
|
||||
return shared.updateSettingValue(this, key, value);
|
||||
const updateSettingValue = async (key: string, value: any) => {
|
||||
const handled = await this.handleSetting(key, value);
|
||||
if (!handled) shared.updateSettingValue(this, key, value);
|
||||
};
|
||||
|
||||
const md = Setting.settingMetadata(key);
|
||||
@@ -517,7 +544,7 @@ class ConfigScreenComponent extends BaseScreenComponent {
|
||||
fontSize: theme.fontSize,
|
||||
}}
|
||||
onValueChange={(itemValue: string) => {
|
||||
updateSettingValue(key, itemValue);
|
||||
void updateSettingValue(key, itemValue);
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
@@ -553,7 +580,7 @@ class ConfigScreenComponent extends BaseScreenComponent {
|
||||
</Text>
|
||||
<View style={{ display: 'flex', flexDirection: 'row', alignItems: 'center', flex: 1 }}>
|
||||
<Text style={this.styles().sliderUnits}>{unitLabel}</Text>
|
||||
<Slider key="control" style={{ flex: 1 }} step={md.step} minimumValue={minimum} maximumValue={maximum} value={value} onValueChange={value => updateSettingValue(key, value)} />
|
||||
<Slider key="control" style={{ flex: 1 }} step={md.step} minimumValue={minimum} maximumValue={maximum} value={value} onValueChange={value => void updateSettingValue(key, value)} />
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
@@ -577,7 +604,7 @@ class ConfigScreenComponent extends BaseScreenComponent {
|
||||
<Text key="label" style={this.styles().settingText}>
|
||||
{md.label()}
|
||||
</Text>
|
||||
<TextInput autoCorrect={false} autoComplete="off" selectionColor={theme.textSelectionColor} keyboardAppearance={theme.keyboardAppearance} autoCapitalize="none" key="control" style={this.styles().settingControl} value={value} onChangeText={(value: any) => updateSettingValue(key, value)} secureTextEntry={!!md.secure} />
|
||||
<TextInput autoCorrect={false} autoComplete="off" selectionColor={theme.textSelectionColor} keyboardAppearance={theme.keyboardAppearance} autoCapitalize="none" key="control" style={this.styles().settingControl} value={value} onChangeText={(value: any) => void updateSettingValue(key, value)} secureTextEntry={!!md.secure} />
|
||||
</View>
|
||||
);
|
||||
} else {
|
||||
|
||||
@@ -1118,6 +1118,7 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
|
||||
bodyComponent = <NoteEditor
|
||||
ref={this.editorRef}
|
||||
toolbarEnabled={this.props.toolbarEnabled}
|
||||
themeId={this.props.themeId}
|
||||
initialText={note.body}
|
||||
initialSelection={this.selection}
|
||||
@@ -1231,6 +1232,7 @@ const NoteScreen = connect((state: any) => {
|
||||
themeId: state.settings.theme,
|
||||
editorFont: [state.settings['style.editor.fontFamily']],
|
||||
editorFontSize: state.settings['style.editor.fontSize'],
|
||||
toolbarEnabled: state.settings['editor.mobile.toolbarEnabled'],
|
||||
ftsEnabled: state.settings['db.ftsEnabled'],
|
||||
sharedData: state.sharedData,
|
||||
showSideMenu: state.showSideMenu,
|
||||
|
||||
@@ -523,7 +523,7 @@
|
||||
INFOPLIST_FILE = Joplin/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
MARKETING_VERSION = 12.10.5;
|
||||
MARKETING_VERSION = 12.11.0;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
@@ -551,7 +551,7 @@
|
||||
INFOPLIST_FILE = Joplin/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
MARKETING_VERSION = 12.10.5;
|
||||
MARKETING_VERSION = 12.11.0;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
@@ -705,7 +705,7 @@
|
||||
INFOPLIST_FILE = ShareExtension/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
MARKETING_VERSION = 12.10.5;
|
||||
MARKETING_VERSION = 12.11.0;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = net.cozic.joplin.ShareExtension;
|
||||
@@ -736,7 +736,7 @@
|
||||
INFOPLIST_FILE = ShareExtension/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
|
||||
MARKETING_VERSION = 12.10.5;
|
||||
MARKETING_VERSION = 12.11.0;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = net.cozic.joplin.ShareExtension;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
||||
@@ -306,7 +306,7 @@ PODS:
|
||||
- React-jsinspector (0.70.6)
|
||||
- React-logger (0.70.6):
|
||||
- glog
|
||||
- react-native-alarm-notification (2.10.0):
|
||||
- react-native-alarm-notification (2.11.0):
|
||||
- React
|
||||
- react-native-camera (4.2.1):
|
||||
- React-Core
|
||||
@@ -316,7 +316,7 @@ PODS:
|
||||
- React-Core
|
||||
- react-native-camera/RN (4.2.1):
|
||||
- React-Core
|
||||
- react-native-document-picker (8.1.3):
|
||||
- react-native-document-picker (8.1.4):
|
||||
- React-Core
|
||||
- react-native-fingerprint-scanner (6.0.0):
|
||||
- React
|
||||
@@ -324,15 +324,15 @@ PODS:
|
||||
- React-Core
|
||||
- react-native-get-random-values (1.8.0):
|
||||
- React-Core
|
||||
- react-native-image-picker (5.0.2):
|
||||
- react-native-image-picker (5.3.1):
|
||||
- React-Core
|
||||
- react-native-image-resizer (1.4.5):
|
||||
- React-Core
|
||||
- react-native-netinfo (9.3.7):
|
||||
- react-native-netinfo (9.3.8):
|
||||
- React-Core
|
||||
- react-native-rsa-native (2.0.5):
|
||||
- React
|
||||
- react-native-saf-x (2.10.2):
|
||||
- react-native-saf-x (2.11.0):
|
||||
- React-Core
|
||||
- react-native-safe-area-context (4.5.0):
|
||||
- RCT-Folly
|
||||
@@ -432,7 +432,7 @@ PODS:
|
||||
- React
|
||||
- RNSecureRandom (1.0.1):
|
||||
- React
|
||||
- RNShare (8.2.0):
|
||||
- RNShare (8.2.1):
|
||||
- React-Core
|
||||
- RNVectorIcons (9.2.0):
|
||||
- React-Core
|
||||
@@ -714,17 +714,17 @@ SPEC CHECKSUMS:
|
||||
React-jsiexecutor: b4a65947391c658450151275aa406f2b8263178f
|
||||
React-jsinspector: 60769e5a0a6d4b32294a2456077f59d0266f9a8b
|
||||
React-logger: 1623c216abaa88974afce404dc8f479406bbc3a0
|
||||
react-native-alarm-notification: 0f58eaa37a4188480536fd7ab62db9b1dfba392f
|
||||
react-native-alarm-notification: 26527410a6162d07a9dc57f4bbc62e94ff48e65d
|
||||
react-native-camera: 3eae183c1d111103963f3dd913b65d01aef8110f
|
||||
react-native-document-picker: 958e2bc82e128be69055be261aeac8d872c8d34c
|
||||
react-native-document-picker: a9bd26996d1b2e4f412dd186041714c79af381d0
|
||||
react-native-fingerprint-scanner: ac6656f18c8e45a7459302b84da41a44ad96dbbe
|
||||
react-native-geolocation: 69f4fd37650b8e7fee91816d395e62dd16f5ab8d
|
||||
react-native-get-random-values: a6ea6a8a65dc93e96e24a11105b1a9c8cfe1d72a
|
||||
react-native-image-picker: a5dddebb4d2955ac4712a4ed66b00a85f62a63ac
|
||||
react-native-image-picker: ec9b713e248760bfa0f879f0715391de4651a7cb
|
||||
react-native-image-resizer: d9fb629a867335bdc13230ac2a58702bb8c8828f
|
||||
react-native-netinfo: 2517ad504b3d303e90d7a431b0fcaef76d207983
|
||||
react-native-netinfo: fbc23bc2fe217155d85f2f7e0644b1654df8029b
|
||||
react-native-rsa-native: 12132eb627797529fdb1f0d22fd0f8f9678df64a
|
||||
react-native-saf-x: db5a33862e7aec0f9f2d4cccfe7264b09b234e2e
|
||||
react-native-saf-x: 9bd5238d3b43d76bbec64aa82c173ac20a4bce9f
|
||||
react-native-safe-area-context: 39c2d8be3328df5d437ac1700f4f3a4f75716acc
|
||||
react-native-slider: 33b8d190b59d4f67a541061bb91775d53d617d9d
|
||||
react-native-sqlite-storage: f6d515e1c446d1e6d026aa5352908a25d4de3261
|
||||
@@ -751,7 +751,7 @@ SPEC CHECKSUMS:
|
||||
RNFS: 4ac0f0ea233904cb798630b3c077808c06931688
|
||||
RNQuickAction: 6d404a869dc872cde841ad3147416a670d13fa93
|
||||
RNSecureRandom: 07efbdf2cd99efe13497433668e54acd7df49fef
|
||||
RNShare: b089c33619bbfb0a32bc4069c858b9274e694187
|
||||
RNShare: eaee3dd5a06dad397c7d3b14762007035c5de405
|
||||
RNVectorIcons: fcc2f6cb32f5735b586e66d14103a74ce6ad61f8
|
||||
SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608
|
||||
Yoga: 99caf8d5ab45e9d637ee6e0174ec16fbbb01bcfc
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@joplin/app-mobile",
|
||||
"description": "Joplin for Mobile",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"version": "2.10.0",
|
||||
"version": "2.11.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "react-native start --reset-cache",
|
||||
@@ -18,14 +18,14 @@
|
||||
"postinstall": "jetify && yarn run build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@joplin/lib": "~2.10",
|
||||
"@joplin/react-native-alarm-notification": "~2.10",
|
||||
"@joplin/react-native-saf-x": "~2.10",
|
||||
"@joplin/renderer": "~2.10",
|
||||
"@joplin/lib": "~2.11",
|
||||
"@joplin/react-native-alarm-notification": "~2.11",
|
||||
"@joplin/react-native-saf-x": "~2.11",
|
||||
"@joplin/renderer": "~2.11",
|
||||
"@react-native-community/clipboard": "1.5.1",
|
||||
"@react-native-community/datetimepicker": "6.7.5",
|
||||
"@react-native-community/geolocation": "2.1.0",
|
||||
"@react-native-community/netinfo": "9.3.7",
|
||||
"@react-native-community/netinfo": "9.3.8",
|
||||
"@react-native-community/push-notification-ios": "1.10.1",
|
||||
"@react-native-community/slider": "4.4.2",
|
||||
"assert-browserify": "2.0.0",
|
||||
@@ -44,17 +44,17 @@
|
||||
"react-native-action-button": "2.8.5",
|
||||
"react-native-camera": "4.2.1",
|
||||
"react-native-dialogbox": "0.6.10",
|
||||
"react-native-document-picker": "8.1.3",
|
||||
"react-native-document-picker": "8.1.4",
|
||||
"react-native-dropdownalert": "4.5.1",
|
||||
"react-native-exit-app": "1.1.0",
|
||||
"react-native-file-viewer": "2.1.5",
|
||||
"react-native-fingerprint-scanner": "6.0.0",
|
||||
"react-native-fs": "2.20.0",
|
||||
"react-native-get-random-values": "1.8.0",
|
||||
"react-native-image-picker": "5.1.0",
|
||||
"react-native-image-picker": "5.3.1",
|
||||
"react-native-image-resizer": "1.4.5",
|
||||
"react-native-modal-datetime-picker": "14.0.1",
|
||||
"react-native-paper": "5.2.0",
|
||||
"react-native-paper": "5.4.1",
|
||||
"react-native-popup-menu": "0.16.1",
|
||||
"react-native-quick-actions": "0.3.13",
|
||||
"react-native-rsa-native": "2.0.5",
|
||||
@@ -79,36 +79,36 @@
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.16.0",
|
||||
"@babel/runtime": "7.16.3",
|
||||
"@codemirror/commands": "6.1.2",
|
||||
"@codemirror/commands": "6.2.2",
|
||||
"@codemirror/lang-cpp": "6.0.2",
|
||||
"@codemirror/lang-html": "6.4.0",
|
||||
"@codemirror/lang-html": "6.4.3",
|
||||
"@codemirror/lang-java": "6.0.1",
|
||||
"@codemirror/lang-javascript": "6.1.1",
|
||||
"@codemirror/lang-markdown": "6.0.5",
|
||||
"@codemirror/lang-javascript": "6.1.5",
|
||||
"@codemirror/lang-markdown": "6.1.0",
|
||||
"@codemirror/lang-php": "6.0.1",
|
||||
"@codemirror/lang-rust": "6.0.1",
|
||||
"@codemirror/language": "6.3.2",
|
||||
"@codemirror/legacy-modes": "6.3.1",
|
||||
"@codemirror/search": "6.2.3",
|
||||
"@codemirror/state": "6.1.4",
|
||||
"@codemirror/view": "6.7.1",
|
||||
"@joplin/tools": "~2.10",
|
||||
"@lezer/highlight": "1.1.3",
|
||||
"@codemirror/language": "6.6.0",
|
||||
"@codemirror/legacy-modes": "6.3.2",
|
||||
"@codemirror/search": "6.3.0",
|
||||
"@codemirror/state": "6.2.0",
|
||||
"@codemirror/view": "6.9.3",
|
||||
"@joplin/tools": "~2.11",
|
||||
"@lezer/highlight": "1.1.4",
|
||||
"@types/fs-extra": "9.0.13",
|
||||
"@types/jest": "29.2.6",
|
||||
"@types/react-native": "0.70.6",
|
||||
"@types/react-redux": "7.1.25",
|
||||
"babel-plugin-module-resolver": "4.1.0",
|
||||
"execa": "4.1.0",
|
||||
"fs-extra": "11.1.0",
|
||||
"fs-extra": "11.1.1",
|
||||
"gulp": "4.0.2",
|
||||
"jest": "29.4.3",
|
||||
"jest-environment-jsdom": "29.4.3",
|
||||
"jetifier": "2.0.0",
|
||||
"jsdom": "21.0.0",
|
||||
"jsdom": "21.1.1",
|
||||
"md5-file": "5.0.0",
|
||||
"metro-react-native-babel-preset": "0.72.3",
|
||||
"nodemon": "2.0.21",
|
||||
"nodemon": "2.0.22",
|
||||
"ts-jest": "29.0.5",
|
||||
"ts-loader": "9.4.2",
|
||||
"ts-node": "10.9.1",
|
||||
|
||||
@@ -501,7 +501,7 @@ async function initialize(dispatch: Function) {
|
||||
if (Setting.value('env') === 'prod') {
|
||||
await db.open({ name: getDatabaseName(currentProfile, isSubProfile) });
|
||||
} else {
|
||||
await db.open({ name: getDatabaseName(currentProfile, isSubProfile) });
|
||||
await db.open({ name: getDatabaseName(currentProfile, isSubProfile, '-3') });
|
||||
|
||||
// await db.clearForTesting();
|
||||
}
|
||||
@@ -984,6 +984,10 @@ class AppComponent extends React.Component {
|
||||
const biometricIsEnabled = !!this.state.sensorInfo && this.state.sensorInfo.enabled;
|
||||
const shouldShowMainContent = !biometricIsEnabled || this.props.biometricsDone;
|
||||
|
||||
logger.info('root.biometrics: biometricIsEnabled', biometricIsEnabled);
|
||||
logger.info('root.biometrics: shouldShowMainContent', shouldShowMainContent);
|
||||
logger.info('root.biometrics: this.state.sensorInfo', this.state.sensorInfo);
|
||||
|
||||
const mainContent = (
|
||||
<View style={{ flex: 1, backgroundColor: theme.backgroundColor }}>
|
||||
<SideMenu
|
||||
|
||||
@@ -24,9 +24,10 @@ export const getResourceDir = (profile: Profile, isSubProfile: boolean) => {
|
||||
return `${getProfilesRootDir()}/resources-${profile.id}`;
|
||||
};
|
||||
|
||||
export const getDatabaseName = (profile: Profile, isSubProfile: boolean) => {
|
||||
if (!isSubProfile) return 'joplin.sqlite';
|
||||
return `joplin-${profile.id}.sqlite`;
|
||||
// The suffix is for debugging only
|
||||
export const getDatabaseName = (profile: Profile, isSubProfile: boolean, suffix: string = '') => {
|
||||
if (!isSubProfile) return `joplin${suffix}.sqlite`;
|
||||
return `joplin-${profile.id}${suffix}.sqlite`;
|
||||
};
|
||||
|
||||
export const loadProfileConfig = async () => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"manifest_version": 1,
|
||||
"id": "<%= pluginId %>",
|
||||
"app_min_version": "2.10",
|
||||
"app_min_version": "2.11",
|
||||
"version": "1.0.0",
|
||||
"name": "<%= pluginName %>",
|
||||
"description": "<%= pluginDescription %>",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "generator-joplin",
|
||||
"version": "2.10.0",
|
||||
"version": "2.11.0",
|
||||
"description": "Scaffolds out a new Joplin plugin",
|
||||
"homepage": "https://github.com/laurent22/joplin/tree/dev/packages/generator-joplin",
|
||||
"author": {
|
||||
@@ -24,7 +24,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"chalk": "2.4.2",
|
||||
"slugify": "1.6.5",
|
||||
"slugify": "1.6.6",
|
||||
"yeoman-generator": "5.8.0",
|
||||
"yosay": "2.0.2"
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/htmlpack",
|
||||
"version": "2.10.2",
|
||||
"version": "2.11.0",
|
||||
"description": "Pack an HTML file and all its linked resources into a single HTML file",
|
||||
"main": "dist/index.js",
|
||||
"types": "src/index.ts",
|
||||
@@ -17,7 +17,7 @@
|
||||
"@joplin/fork-htmlparser2": "^4.1.43",
|
||||
"css": "3.0.0",
|
||||
"datauri": "4.1.0",
|
||||
"fs-extra": "11.1.0",
|
||||
"fs-extra": "11.1.1",
|
||||
"html-entities": "1.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -20,7 +20,7 @@ import Folder from './models/Folder';
|
||||
import BaseItem from './models/BaseItem';
|
||||
import Note from './models/Note';
|
||||
import Tag from './models/Tag';
|
||||
const { splitCommandString } = require('./string-utils.js');
|
||||
import { splitCommandString } from '@joplin/utils';
|
||||
import { reg } from './registry';
|
||||
import time from './time';
|
||||
import BaseSyncTarget from './BaseSyncTarget';
|
||||
@@ -192,6 +192,12 @@ export default class BaseApplication {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg === '--safe-mode') {
|
||||
matched.isSafeMode = true;
|
||||
argv.splice(0, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg === '--open-dev-tools') {
|
||||
Setting.setConstant('flagOpenDevTools', true);
|
||||
argv.splice(0, 1);
|
||||
@@ -700,7 +706,7 @@ export default class BaseApplication {
|
||||
|
||||
flagContent = flagContent.trim();
|
||||
|
||||
let flags = splitCommandString(flagContent);
|
||||
let flags: any = splitCommandString(flagContent);
|
||||
flags.splice(0, 0, 'cmd');
|
||||
flags.splice(0, 0, 'node');
|
||||
|
||||
@@ -829,6 +835,10 @@ export default class BaseApplication {
|
||||
|
||||
appLogger.info(`Client ID: ${Setting.value('clientId')}`);
|
||||
|
||||
if (initArgs?.isSafeMode) {
|
||||
Setting.setValue('isSafeMode', true);
|
||||
}
|
||||
|
||||
if (Setting.value('firstStart')) {
|
||||
// If it's a sub-profile, the locale must come from the root
|
||||
// profile.
|
||||
|
||||
@@ -96,12 +96,14 @@ export default class SyncTargetOneDrive extends BaseSyncTarget {
|
||||
let context = Setting.value(`sync.${this.syncTargetId()}.context`);
|
||||
context = context === '' ? null : JSON.parse(context);
|
||||
let accountProperties = context ? context.accountProperties : null;
|
||||
const api = this.api();
|
||||
|
||||
if (!accountProperties) {
|
||||
accountProperties = await this.api_.execAccountPropertiesRequest();
|
||||
accountProperties = await api.execAccountPropertiesRequest();
|
||||
context ? context.accountProperties = accountProperties : context = { accountProperties: accountProperties };
|
||||
Setting.setValue(`sync.${this.syncTargetId()}.context`, JSON.stringify(context));
|
||||
}
|
||||
this.api_.setAccountProperties(accountProperties);
|
||||
api.setAccountProperties(accountProperties);
|
||||
const appDir = await this.api().appDirectory();
|
||||
// the appDir might contain non-ASCII characters
|
||||
// /[^\u0021-\u00ff]/ is used in Node.js to detect the unescaped characters.
|
||||
|
||||
@@ -1,5 +1,18 @@
|
||||
const markJsUtils = {};
|
||||
|
||||
const isInsideContainer = (node, tagName) => {
|
||||
if (!node) return false;
|
||||
|
||||
tagName = tagName.toLowerCase();
|
||||
|
||||
while (node) {
|
||||
if (node.tagName && node.tagName.toLowerCase() === tagName) return true;
|
||||
node = node.parentNode;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
markJsUtils.markKeyword = (mark, keyword, stringUtils, extraOptions = null) => {
|
||||
if (typeof keyword === 'string') {
|
||||
keyword = {
|
||||
@@ -15,12 +28,13 @@ markJsUtils.markKeyword = (mark, keyword, stringUtils, extraOptions = null) => {
|
||||
if (isBasicSearch) accuracy = 'partially';
|
||||
if (keyword.type === 'regex') {
|
||||
accuracy = 'complementary';
|
||||
// Remove the trailing wildcard and "accuracy = complementary" will take care of
|
||||
// highlighting the relevant keywords.
|
||||
// Remove the trailing wildcard and "accuracy = complementary" will take
|
||||
// care of highlighting the relevant keywords.
|
||||
|
||||
// Known bug: it will also highlight word that contain the term as a suffix for example for "ent*", it will highlight "present"
|
||||
// which is incorrect (it should only highlight what starts with "ent") but for now will do. Mark.js doesn't have an option
|
||||
// to tweak this behaviour.
|
||||
// Known bug: it will also highlight word that contain the term as a
|
||||
// suffix for example for "ent*", it will highlight "present" which is
|
||||
// incorrect (it should only highlight what starts with "ent") but for
|
||||
// now will do. Mark.js doesn't have an option to tweak this behaviour.
|
||||
value = keyword.value.substr(0, keyword.value.length - 1);
|
||||
}
|
||||
|
||||
@@ -30,6 +44,18 @@ markJsUtils.markKeyword = (mark, keyword, stringUtils, extraOptions = null) => {
|
||||
{},
|
||||
{
|
||||
accuracy: accuracy,
|
||||
filter: (node, _term, _totalCounter, _counter) => {
|
||||
// We exclude SVG because it creates a "<mark>" tag inside
|
||||
// the document, which is not a valid SVG tag. As a result
|
||||
// the content within that tag disappears.
|
||||
//
|
||||
// mark.js has an "exclude" parameter, but it doesn't work
|
||||
// so we use "filter" instead.
|
||||
//
|
||||
// https://github.com/joplin/plugin-abc-sheet-music
|
||||
if (isInsideContainer(node, 'SVG')) return false;
|
||||
return true;
|
||||
},
|
||||
},
|
||||
extraOptions
|
||||
)
|
||||
|
||||
@@ -1050,6 +1050,17 @@ class Setting extends BaseModel {
|
||||
isGlobal: true,
|
||||
},
|
||||
|
||||
'editor.mobile.toolbarEnabled': {
|
||||
value: true,
|
||||
type: SettingItemType.Bool,
|
||||
section: 'note',
|
||||
public: true,
|
||||
appTypes: [AppType.Mobile],
|
||||
label: () => _('Enable the Markdown toolbar'),
|
||||
storage: SettingStorage.File,
|
||||
isGlobal: true,
|
||||
},
|
||||
|
||||
// Works around a bug in which additional space is visible beneath the toolbar on some devices.
|
||||
// See https://github.com/laurent22/joplin/pull/6823
|
||||
'editor.mobile.removeSpaceBelowToolbar': {
|
||||
@@ -1634,10 +1645,17 @@ class Setting extends BaseModel {
|
||||
storage: SettingStorage.Database,
|
||||
},
|
||||
|
||||
// The biometrics feature is disabled by default and marked as beta
|
||||
// because it seems to cause a freeze or slow down startup on
|
||||
// certain devices. May be the reason for:
|
||||
//
|
||||
// - https://discourse.joplinapp.org/t/on-android-when-joplin-gets-started-offline/29951/1
|
||||
// - https://github.com/laurent22/joplin/issues/7956
|
||||
'security.biometricsEnabled': {
|
||||
value: false,
|
||||
type: SettingItemType.Bool,
|
||||
label: () => _('Use biometrics to secure access to the app'),
|
||||
label: () => `${_('Use biometrics to secure access to the app')} (Beta)`,
|
||||
description: () => 'Important: This is a beta feature and it is not compatible with certain devices. If the app no longer starts after enabling this or is very slow to start, please uninstall and reinstall the app.',
|
||||
public: true,
|
||||
appTypes: [AppType.Mobile],
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/lib",
|
||||
"version": "2.10.2",
|
||||
"version": "2.11.0",
|
||||
"description": "Joplin Core library",
|
||||
"author": "Laurent Cozic",
|
||||
"homepage": "",
|
||||
@@ -34,10 +34,11 @@
|
||||
"@joplin/fork-htmlparser2": "^4.1.43",
|
||||
"@joplin/fork-sax": "^1.2.47",
|
||||
"@joplin/fork-uslug": "^1.0.8",
|
||||
"@joplin/htmlpack": "^2.10.2",
|
||||
"@joplin/renderer": "^2.10.2",
|
||||
"@joplin/htmlpack": "~2.11",
|
||||
"@joplin/renderer": "~2.11",
|
||||
"@joplin/turndown": "^4.0.65",
|
||||
"@joplin/turndown-plugin-gfm": "^1.0.47",
|
||||
"@joplin/utils": "~2.11",
|
||||
"@types/nanoid": "3.0.0",
|
||||
"async-mutex": "0.4.0",
|
||||
"base-64": "1.0.0",
|
||||
@@ -53,7 +54,7 @@
|
||||
"fast-xml-parser": "3.21.1",
|
||||
"follow-redirects": "1.15.2",
|
||||
"form-data": "4.0.0",
|
||||
"fs-extra": "11.1.0",
|
||||
"fs-extra": "11.1.1",
|
||||
"hpagent": "1.2.0",
|
||||
"html-entities": "1.4.0",
|
||||
"html-minifier": "4.0.0",
|
||||
@@ -68,7 +69,7 @@
|
||||
"moment": "2.29.4",
|
||||
"multiparty": "4.2.3",
|
||||
"mustache": "4.2.0",
|
||||
"nanoid": "3.3.4",
|
||||
"nanoid": "3.3.6",
|
||||
"node-fetch": "2.6.7",
|
||||
"node-notifier": "10.0.1",
|
||||
"node-persist": "3.1.3",
|
||||
@@ -82,7 +83,7 @@
|
||||
"reselect": "4.1.7",
|
||||
"server-destroy": "1.0.1",
|
||||
"sprintf-js": "1.1.2",
|
||||
"sqlite3": "5.1.4",
|
||||
"sqlite3": "5.1.6",
|
||||
"string-padding": "1.0.2",
|
||||
"string-to-stream": "3.0.1",
|
||||
"tar": "6.1.13",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable import/prefer-default-export */
|
||||
|
||||
const { splitCommandString } = require('../../string-utils');
|
||||
import { splitCommandString } from '@joplin/utils';
|
||||
import { spawn } from 'child_process';
|
||||
import Logger from '../../Logger';
|
||||
import Setting from '../../models/Setting';
|
||||
|
||||
@@ -110,6 +110,8 @@ export default class ReportService {
|
||||
let syncedCount = 0;
|
||||
for (let i = 0; i < BaseItem.syncItemDefinitions_.length; i++) {
|
||||
const d = BaseItem.syncItemDefinitions_[i];
|
||||
// ref: https://github.com/laurent22/joplin/issues/7940#issuecomment-1473709148
|
||||
if (d.className === 'MasterKey') continue;
|
||||
const ItemClass = BaseItem.getClass(d.className);
|
||||
const o = {
|
||||
total: await ItemClass.count(),
|
||||
|
||||
@@ -100,6 +100,11 @@ export default class PluginService extends BaseService {
|
||||
return this.plugins_;
|
||||
}
|
||||
|
||||
public enabledPlugins(pluginSettings: PluginSettings): Plugins {
|
||||
const enabledPlugins = Object.fromEntries(Object.entries(this.plugins_).filter((p) => this.pluginEnabled(pluginSettings, p[0])));
|
||||
return enabledPlugins;
|
||||
}
|
||||
|
||||
public get pluginIds(): string[] {
|
||||
return Object.keys(this.plugins_);
|
||||
}
|
||||
@@ -108,6 +113,10 @@ export default class PluginService extends BaseService {
|
||||
return this.isSafeMode_;
|
||||
}
|
||||
|
||||
public get appVersion(): string {
|
||||
return this.appVersion_;
|
||||
}
|
||||
|
||||
public set isSafeMode(v: boolean) {
|
||||
this.isSafeMode_ = v;
|
||||
}
|
||||
|
||||
@@ -215,21 +215,21 @@ export default class RepositoryApi {
|
||||
return this.manifests_;
|
||||
}
|
||||
|
||||
public async canBeUpdatedPlugins(installedManifests: PluginManifest[]): Promise<string[]> {
|
||||
public async canBeUpdatedPlugins(installedManifests: PluginManifest[], appVersion: string): Promise<string[]> {
|
||||
const output = [];
|
||||
|
||||
for (const manifest of installedManifests) {
|
||||
const canBe = await this.pluginCanBeUpdated(manifest.id, manifest.version);
|
||||
const canBe = await this.pluginCanBeUpdated(manifest.id, manifest.version, appVersion);
|
||||
if (canBe) output.push(manifest.id);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
public async pluginCanBeUpdated(pluginId: string, installedVersion: string): Promise<boolean> {
|
||||
public async pluginCanBeUpdated(pluginId: string, installedVersion: string, appVersion: string): Promise<boolean> {
|
||||
const manifest = (await this.manifests()).find(m => m.id === pluginId);
|
||||
if (!manifest) return false;
|
||||
return compareVersions(installedVersion, manifest.version) < 0;
|
||||
return compareVersions(installedVersion, manifest.version) < 0 && compareVersions(appVersion, manifest.app_min_version) >= 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -138,80 +138,6 @@ function commandArgumentsToString(args) {
|
||||
return output.join(' ');
|
||||
}
|
||||
|
||||
function splitCommandString(command, options = null) {
|
||||
options = options || {};
|
||||
if (!('handleEscape' in options)) {
|
||||
options.handleEscape = true;
|
||||
}
|
||||
|
||||
const args = [];
|
||||
let state = 'start';
|
||||
let current = '';
|
||||
let quote = '"';
|
||||
let escapeNext = false;
|
||||
for (let i = 0; i < command.length; i++) {
|
||||
const c = command[i];
|
||||
|
||||
if (state === 'quotes') {
|
||||
if (c !== quote) {
|
||||
current += c;
|
||||
} else {
|
||||
args.push(current);
|
||||
current = '';
|
||||
state = 'start';
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (escapeNext) {
|
||||
current += c;
|
||||
escapeNext = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c === '\\' && options.handleEscape) {
|
||||
escapeNext = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c === '"' || c === '\'') {
|
||||
state = 'quotes';
|
||||
quote = c;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (state === 'arg') {
|
||||
if (c === ' ' || c === '\t') {
|
||||
args.push(current);
|
||||
current = '';
|
||||
state = 'start';
|
||||
} else {
|
||||
current += c;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c !== ' ' && c !== '\t') {
|
||||
state = 'arg';
|
||||
current += c;
|
||||
}
|
||||
}
|
||||
|
||||
if (state === 'quotes') {
|
||||
throw new Error(`Unclosed quote in command line: ${command}`);
|
||||
}
|
||||
|
||||
if (current !== '') {
|
||||
args.push(current);
|
||||
}
|
||||
|
||||
if (args.length <= 0) {
|
||||
throw new Error('Empty command line');
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
function splitCommandBatch(commandBatch) {
|
||||
const commandLines = [];
|
||||
const eol = '\n';
|
||||
@@ -368,4 +294,4 @@ function scriptType(s) {
|
||||
return 'en';
|
||||
}
|
||||
|
||||
module.exports = Object.assign({ formatCssSize, camelCaseToDash, removeDiacritics, substrWithEllipsis, nextWhitespaceIndex, escapeFilename, wrap, splitCommandString, splitCommandBatch, padLeft, toTitleCase, urlDecode, escapeHtml, surroundKeywords, scriptType, commandArgumentsToString }, stringUtilsCommon);
|
||||
module.exports = Object.assign({ formatCssSize, camelCaseToDash, removeDiacritics, substrWithEllipsis, nextWhitespaceIndex, escapeFilename, wrap, splitCommandBatch, padLeft, toTitleCase, urlDecode, escapeHtml, surroundKeywords, scriptType, commandArgumentsToString }, stringUtilsCommon);
|
||||
|
||||
@@ -21,6 +21,17 @@ export function credentialDir() {
|
||||
throw new Error(`Could not find credential directory in any of these paths: ${JSON.stringify(toTry)}`);
|
||||
}
|
||||
|
||||
export const hasCredentialFile = (filename: string) => {
|
||||
let d = '';
|
||||
try {
|
||||
d = credentialDir();
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return pathExistsSync(`${d}/${filename}`);
|
||||
};
|
||||
|
||||
export function credentialFile(filename: string) {
|
||||
const rootDir = credentialDir();
|
||||
const output = `${rootDir}/${filename}`;
|
||||
|
||||
@@ -86,6 +86,7 @@ describe('getPluginLists', () => {
|
||||
);
|
||||
plugins[plugin.manifest.id] = plugin;
|
||||
}
|
||||
|
||||
const v = versionInfo(packageInfo, plugins);
|
||||
|
||||
expect(v.body).toMatch(/\n\nPlugin1: 1\nPlugin2: 1\nPlugin3: 1/);
|
||||
@@ -110,6 +111,7 @@ describe('getPluginLists', () => {
|
||||
|
||||
plugins[plugin.manifest.id] = plugin;
|
||||
}
|
||||
|
||||
const v = versionInfo(packageInfo, plugins);
|
||||
|
||||
const body = '\n';
|
||||
|
||||
@@ -16,6 +16,8 @@ function getPluginLists(plugins: Plugins): PluginList {
|
||||
}
|
||||
}
|
||||
|
||||
pluginList.sort(Intl.Collator().compare);
|
||||
|
||||
let completeList = '';
|
||||
let summary = '';
|
||||
if (pluginList.length > 0) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/pdf-viewer",
|
||||
"version": "2.10.0",
|
||||
"version": "2.11.0",
|
||||
"description": "Provides embedded PDF viewers for Joplin",
|
||||
"main": "dist/main.js",
|
||||
"types": "src/main.ts",
|
||||
@@ -28,7 +28,7 @@
|
||||
"css-loader": "6.7.3",
|
||||
"jest": "29.4.3",
|
||||
"jest-environment-jsdom": "29.4.3",
|
||||
"style-loader": "3.3.1",
|
||||
"style-loader": "3.3.2",
|
||||
"ts-jest": "29.0.5",
|
||||
"ts-loader": "9.4.2",
|
||||
"typescript": "4.9.4",
|
||||
@@ -39,11 +39,11 @@
|
||||
"@fortawesome/fontawesome-svg-core": "6.1.2",
|
||||
"@fortawesome/free-solid-svg-icons": "6.1.2",
|
||||
"@fortawesome/react-fontawesome": "0.2.0",
|
||||
"@joplin/lib": "~2.10",
|
||||
"@joplin/lib": "~2.11",
|
||||
"async-mutex": "0.4.0",
|
||||
"pdfjs-dist": "2.16.105",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"styled-components": "5.3.8"
|
||||
"styled-components": "5.3.9"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import * as path from 'path';
|
||||
import * as process from 'process';
|
||||
import validatePluginId from '@joplin/lib/services/plugins/utils/validatePluginId';
|
||||
import validatePluginVersion from '@joplin/lib/services/plugins/utils/validatePluginVersion';
|
||||
import { execCommand2, resolveRelativePathWithinDir, gitPullTry, gitRepoCleanTry, gitRepoClean } from '@joplin/tools/tool-utils.js';
|
||||
import { resolveRelativePathWithinDir, gitPullTry, gitRepoCleanTry, gitRepoClean } from '@joplin/tools/tool-utils.js';
|
||||
import checkIfPluginCanBeAdded from './lib/checkIfPluginCanBeAdded';
|
||||
import updateReadme from './lib/updateReadme';
|
||||
import { NpmPackage } from './lib/types';
|
||||
@@ -17,6 +17,7 @@ import gitCompareUrl from './lib/gitCompareUrl';
|
||||
import commandUpdateRelease from './commands/updateRelease';
|
||||
import { isJoplinPluginPackage, readJsonFile } from './lib/utils';
|
||||
import { applyManifestOverrides, getObsoleteManifests, readManifestOverrides } from './lib/overrideUtils';
|
||||
import { execCommand } from '@joplin/utils';
|
||||
|
||||
function pluginInfoFromSearchResults(results: any[]): NpmPackage[] {
|
||||
const output: NpmPackage[] = [];
|
||||
@@ -49,7 +50,7 @@ async function checkPluginRepository(dirPath: string, dryRun: boolean) {
|
||||
async function extractPluginFilesFromPackage(existingManifests: any, workDir: string, packageName: string, destDir: string): Promise<any> {
|
||||
const previousDir = chdir(workDir);
|
||||
|
||||
await execCommand2(`npm install ${packageName} --save --ignore-scripts`, { showStderr: false, showStdout: false });
|
||||
await execCommand(`npm install ${packageName} --save --ignore-scripts`, { showStderr: false, showStdout: false });
|
||||
|
||||
const pluginDir = resolveRelativePathWithinDir(workDir, 'node_modules', packageName, 'publish');
|
||||
|
||||
@@ -154,7 +155,7 @@ async function processNpmPackage(npmPackage: NpmPackage, repoDir: string, dryRun
|
||||
|
||||
await fs.mkdirp(packageTempDir);
|
||||
chdir(packageTempDir);
|
||||
await execCommand2('npm init --yes --loglevel silent', { quiet: true });
|
||||
await execCommand('npm init --yes --loglevel silent', { quiet: true });
|
||||
|
||||
let actionType: ProcessingActionType = ProcessingActionType.Update;
|
||||
let manifests: any = {};
|
||||
@@ -200,8 +201,8 @@ async function processNpmPackage(npmPackage: NpmPackage, repoDir: string, dryRun
|
||||
|
||||
if (!dryRun) {
|
||||
if (!(await gitRepoClean())) {
|
||||
await execCommand2('git add -A', { showStdout: false });
|
||||
await execCommand2(['git', 'commit', '-m', commitMessage(actionType, manifest, previousManifest, npmPackage, error)], { showStdout: false });
|
||||
await execCommand('git add -A', { showStdout: false });
|
||||
await execCommand(['git', 'commit', '-m', commitMessage(actionType, manifest, previousManifest, npmPackage, error)], { showStdout: false });
|
||||
} else {
|
||||
console.info('Nothing to commit');
|
||||
}
|
||||
@@ -227,14 +228,14 @@ async function commandBuild(args: CommandBuildArgs) {
|
||||
if (!dryRun) {
|
||||
if (!(await gitRepoClean())) {
|
||||
console.info('Updating README...');
|
||||
await execCommand2('git add -A');
|
||||
await execCommand2('git commit -m "Update README"');
|
||||
await execCommand('git add -A');
|
||||
await execCommand('git commit -m "Update README"');
|
||||
}
|
||||
}
|
||||
|
||||
chdir(previousDir);
|
||||
|
||||
const searchResults = (await execCommand2('npm search joplin-plugin --searchlimit 5000 --json', { showStdout: false, showStderr: false })).trim();
|
||||
const searchResults = (await execCommand('npm search joplin-plugin --searchlimit 5000 --json', { showStdout: false, showStderr: false })).trim();
|
||||
const npmPackages = pluginInfoFromSearchResults(JSON.parse(searchResults));
|
||||
|
||||
for (const npmPackage of npmPackages) {
|
||||
@@ -245,11 +246,11 @@ async function commandBuild(args: CommandBuildArgs) {
|
||||
await commandUpdateRelease(args);
|
||||
|
||||
if (!(await gitRepoClean())) {
|
||||
await execCommand2('git add -A');
|
||||
await execCommand2('git commit -m "Update stats"');
|
||||
await execCommand('git add -A');
|
||||
await execCommand('git commit -m "Update stats"');
|
||||
}
|
||||
|
||||
await execCommand2('git push');
|
||||
await execCommand('git push');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/plugin-repo-cli",
|
||||
"version": "2.10.2",
|
||||
"version": "2.11.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"bin": "./dist/index.js",
|
||||
@@ -18,9 +18,10 @@
|
||||
"author": "",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@joplin/lib": "^2.10.2",
|
||||
"@joplin/tools": "^2.10.2",
|
||||
"fs-extra": "11.1.0",
|
||||
"@joplin/lib": "~2.11",
|
||||
"@joplin/tools": "~2.11",
|
||||
"@joplin/utils": "~2.11",
|
||||
"fs-extra": "11.1.1",
|
||||
"gh-release-assets": "2.0.1",
|
||||
"node-fetch": "2.6.7",
|
||||
"source-map-support": "0.5.21",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@joplin/react-native-alarm-notification",
|
||||
"title": "React Native Alarm Notification for Joplin. Forked from https://github.com/emekalites/react-native-alarm-notification",
|
||||
"version": "2.10.0",
|
||||
"version": "2.11.0",
|
||||
"description": "schedule alarm with notification in react-native",
|
||||
"main": "index.js",
|
||||
"private": true,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/react-native-saf-x",
|
||||
"version": "2.10.2",
|
||||
"version": "2.11.0",
|
||||
"description": "a module to help work with scoped storages on android easily",
|
||||
"main": "src/index",
|
||||
"react-native": "src/index",
|
||||
|
||||
@@ -179,6 +179,8 @@ export interface RuleOptions {
|
||||
noteId?: string;
|
||||
vendorDir?: string;
|
||||
itemIdToUrl?: ItemIdToUrlHandler;
|
||||
|
||||
platformName?: string;
|
||||
}
|
||||
|
||||
export default class MdToHtml {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { RuleOptions } from '../../MdToHtml';
|
||||
|
||||
export default {
|
||||
|
||||
assets: function() {
|
||||
assets: function(theme: any) {
|
||||
return [
|
||||
{ name: 'mermaid.min.js' },
|
||||
{ name: 'mermaid_render.js' },
|
||||
@@ -12,14 +14,27 @@ export default {
|
||||
text: '.mermaid { background-color: white; width: 640px; }',
|
||||
mime: 'text/css',
|
||||
},
|
||||
{
|
||||
inline: true,
|
||||
// Export button in mermaid graph should be shown only on hovering the mermaid graph
|
||||
// ref: https://github.com/laurent22/joplin/issues/6101
|
||||
text: `
|
||||
.mermaid-export-graph { visibility: hidden; }
|
||||
.joplin-editable:hover .mermaid-export-graph { visibility: visible; }
|
||||
.mermaid-export-graph:hover { background-color: ${theme.backgroundColorHover3} !important; }
|
||||
`.trim(),
|
||||
mime: 'text/css',
|
||||
},
|
||||
];
|
||||
},
|
||||
|
||||
plugin: function(markdownIt: any) {
|
||||
plugin: function(markdownIt: any, ruleOptions: RuleOptions) {
|
||||
const defaultRender: Function = markdownIt.renderer.rules.fence || function(tokens: any[], idx: number, options: any, env: any, self: any) {
|
||||
return self.renderToken(tokens, idx, options, env, self);
|
||||
};
|
||||
|
||||
const exportButtonMarkup = isDesktop(ruleOptions.platformName) ? exportGraphButton(ruleOptions) : '';
|
||||
|
||||
markdownIt.renderer.rules.fence = function(tokens: any[], idx: number, options: {}, env: any, self: any) {
|
||||
const token = tokens[idx];
|
||||
if (token.info !== 'mermaid') return defaultRender(tokens, idx, options, env, self);
|
||||
@@ -31,9 +46,49 @@ export default {
|
||||
return `
|
||||
<div class="joplin-editable">
|
||||
<pre class="joplin-source" data-joplin-language="mermaid" data-joplin-source-open="\`\`\`mermaid " data-joplin-source-close=" \`\`\` ">${contentHtml}</pre>
|
||||
${exportButtonMarkup}
|
||||
<pre class="mermaid">${contentHtml}</pre>
|
||||
</div>
|
||||
`;
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
const exportGraphButton = (ruleOptions: RuleOptions) => {
|
||||
const theme = ruleOptions.theme;
|
||||
// Clicking on export button manually triggers a right click context menu event
|
||||
const onClickHandler = `
|
||||
const target = arguments[0].target;
|
||||
const button = target.closest("button.mermaid-export-graph");
|
||||
if (!button) return false;
|
||||
const $mermaid_elem = button.nextElementSibling;
|
||||
const rightClickEvent = new PointerEvent("contextmenu", {bubbles: true});
|
||||
rightClickEvent.target = $mermaid_elem;
|
||||
$mermaid_elem.dispatchEvent(rightClickEvent);
|
||||
return false;
|
||||
`.trim();
|
||||
const style = `
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
border-radius: ${theme.buttonStyle.borderRadius}px;
|
||||
font-size: ${theme.fontSize}px;
|
||||
color: ${theme.color};
|
||||
background: ${theme.buttonStyle.backgroundColor};
|
||||
border: ${theme.buttonStyle.border};
|
||||
`.trim();
|
||||
|
||||
return `<button class="mermaid-export-graph" onclick='${onClickHandler}' style="${style}" alt="Export mermaid graph">${downloadIcon()}</button>`;
|
||||
};
|
||||
|
||||
const downloadIcon = () => {
|
||||
// https://www.svgrepo.com/svg/505363/download
|
||||
return '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <path d="M20 15V18C20 19.1046 19.1046 20 18 20H6C4.89543 20 4 19.1046 4 18L4 15M8 11L12 15M12 15L16 11M12 15V3" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></g></svg>';
|
||||
};
|
||||
|
||||
const isDesktop = (platformName?: string) => {
|
||||
if (!platformName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ['darwin', 'linux', 'freebsd', 'win32'].includes(platformName);
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/renderer",
|
||||
"version": "2.10.2",
|
||||
"version": "2.11.0",
|
||||
"description": "The Joplin note renderer, used the mobile and desktop application",
|
||||
"repository": "https://github.com/laurent22/joplin/tree/dev/packages/renderer",
|
||||
"main": "index.js",
|
||||
@@ -29,7 +29,7 @@
|
||||
"@joplin/fork-htmlparser2": "^4.1.43",
|
||||
"@joplin/fork-uslug": "^1.0.8",
|
||||
"font-awesome-filetypes": "2.1.0",
|
||||
"fs-extra": "11.1.0",
|
||||
"fs-extra": "11.1.1",
|
||||
"highlight.js": "11.7.0",
|
||||
"html-entities": "1.4.0",
|
||||
"json-stringify-safe": "5.0.1",
|
||||
@@ -43,7 +43,7 @@
|
||||
"markdown-it-footnote": "3.0.3",
|
||||
"markdown-it-ins": "3.0.1",
|
||||
"markdown-it-mark": "3.0.1",
|
||||
"markdown-it-multimd-table": "4.2.0",
|
||||
"markdown-it-multimd-table": "4.2.1",
|
||||
"markdown-it-sub": "1.0.0",
|
||||
"markdown-it-sup": "1.0.0",
|
||||
"markdown-it-toc-done-right": "4.2.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/server",
|
||||
"version": "2.10.10",
|
||||
"version": "2.11.0",
|
||||
"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",
|
||||
@@ -23,8 +23,8 @@
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "3.241.0",
|
||||
"@fortawesome/fontawesome-free": "5.15.4",
|
||||
"@joplin/lib": "~2.10",
|
||||
"@joplin/renderer": "~2.10",
|
||||
"@joplin/lib": "~2.11",
|
||||
"@joplin/renderer": "~2.11",
|
||||
"@koa/cors": "3.1.0",
|
||||
"@types/uuid": "9.0.0",
|
||||
"bcryptjs": "2.4.3",
|
||||
@@ -33,9 +33,9 @@
|
||||
"compare-versions": "3.6.0",
|
||||
"dayjs": "1.11.7",
|
||||
"formidable": "2.1.1",
|
||||
"fs-extra": "11.1.0",
|
||||
"fs-extra": "11.1.1",
|
||||
"html-entities": "1.4.0",
|
||||
"jquery": "3.6.3",
|
||||
"jquery": "3.6.4",
|
||||
"knex": "2.4.2",
|
||||
"koa": "2.14.1",
|
||||
"markdown-it": "13.0.1",
|
||||
@@ -44,21 +44,21 @@
|
||||
"node-cron": "3.0.2",
|
||||
"node-env-file": "0.1.8",
|
||||
"nodemailer": "6.9.1",
|
||||
"nodemon": "2.0.21",
|
||||
"pg": "8.9.0",
|
||||
"nodemon": "2.0.22",
|
||||
"pg": "8.10.0",
|
||||
"pretty-bytes": "5.6.0",
|
||||
"prettycron": "0.10.0",
|
||||
"query-string": "7.1.3",
|
||||
"rate-limiter-flexible": "2.4.1",
|
||||
"raw-body": "2.5.2",
|
||||
"sqlite3": "5.1.4",
|
||||
"sqlite3": "5.1.6",
|
||||
"stripe": "8.222.0",
|
||||
"uuid": "9.0.0",
|
||||
"yargs": "17.7.1",
|
||||
"zxcvbn": "4.4.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@joplin/tools": "~2.10",
|
||||
"@joplin/tools": "~2.11",
|
||||
"@rmp135/sql-ts": "1.16.0",
|
||||
"@types/formidable": "2.0.5",
|
||||
"@types/fs-extra": "9.0.13",
|
||||
@@ -74,8 +74,8 @@
|
||||
"gulp": "4.0.2",
|
||||
"jest": "29.4.3",
|
||||
"jest-expect-message": "1.1.3",
|
||||
"jsdom": "21.0.0",
|
||||
"node-mocks-http": "1.12.1",
|
||||
"jsdom": "21.1.1",
|
||||
"node-mocks-http": "1.12.2",
|
||||
"source-map-support": "0.5.21",
|
||||
"typescript": "4.9.4"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { execCommand2, rootDir } from './tool-utils';
|
||||
import { rootDir } from './tool-utils';
|
||||
import * as moment from 'moment';
|
||||
import { execCommand } from '@joplin/utils';
|
||||
|
||||
interface Argv {
|
||||
dryRun?: boolean;
|
||||
@@ -35,7 +36,7 @@ async function main() {
|
||||
const buildDate = moment(new Date().getTime()).format('YYYY-MM-DDTHH:mm:ssZ');
|
||||
let revision = '';
|
||||
try {
|
||||
revision = await execCommand2('git rev-parse --short HEAD', { showStdout: false });
|
||||
revision = await execCommand('git rev-parse --short HEAD', { showStdout: false });
|
||||
} catch (error) {
|
||||
console.info('Could not get git commit: metadata revision field will be empty');
|
||||
}
|
||||
@@ -62,11 +63,11 @@ async function main() {
|
||||
return;
|
||||
}
|
||||
|
||||
await execCommand2(dockerCommand);
|
||||
await execCommand(dockerCommand);
|
||||
|
||||
for (const tag of dockerTags) {
|
||||
await execCommand2(`docker tag "${repository}:${imageVersion}" "${repository}:${tag}"`);
|
||||
if (pushImages) await execCommand2(`docker push ${repository}:${tag}`);
|
||||
await execCommand(`docker tag "${repository}:${imageVersion}" "${repository}:${tag}"`);
|
||||
if (pushImages) await execCommand(`docker push ${repository}:${tag}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { join } from 'path';
|
||||
import { execCommand2 } from './tool-utils';
|
||||
import { join, normalize } from 'path';
|
||||
import { pathExists, mkdir, readFile, move, remove, writeFile } from 'fs-extra';
|
||||
import { DefaultPluginsInfo } from '@joplin/lib/services/plugins/PluginService';
|
||||
import getDefaultPluginsInfo from '@joplin/lib/services/plugins/defaultPlugins/desktopDefaultPluginsInfo';
|
||||
import { execCommand } from '@joplin/utils';
|
||||
const fetch = require('node-fetch');
|
||||
|
||||
interface PluginAndVersion {
|
||||
@@ -41,7 +41,7 @@ async function downloadFile(url: string, outputPath: string) {
|
||||
|
||||
export async function extractPlugins(currentDir: string, defaultPluginDir: string, downloadedPluginsNames: PluginIdAndName): Promise<void> {
|
||||
for (const pluginId of Object.keys(downloadedPluginsNames)) {
|
||||
await execCommand2(`tar xzf ${currentDir}/${downloadedPluginsNames[pluginId]}`, { quiet: true });
|
||||
await execCommand(`tar xzf ${currentDir}/${downloadedPluginsNames[pluginId]}`, { quiet: true, splitCommandOptions: { handleEscape: false } });
|
||||
await move(`package/publish/${pluginId}.jpl`, `${defaultPluginDir}/${pluginId}/plugin.jpl`, { overwrite: true });
|
||||
await move(`package/publish/${pluginId}.json`, `${defaultPluginDir}/${pluginId}/manifest.json`, { overwrite: true });
|
||||
await remove(`${downloadedPluginsNames[pluginId]}`);
|
||||
@@ -74,7 +74,10 @@ export const downloadPlugins = async (localPluginsVersions: PluginAndVersion, de
|
||||
};
|
||||
|
||||
async function start(): Promise<void> {
|
||||
const defaultPluginDir = join(__dirname, '..', '..', 'packages', 'app-desktop', 'build', 'defaultPlugins');
|
||||
// windows CI fix: normalizing __dirname for windows
|
||||
const cwd = normalize(__dirname);
|
||||
process.chdir(cwd);
|
||||
const defaultPluginDir = join(cwd, '..', '..', 'packages', 'app-desktop', 'build', 'defaultPlugins');
|
||||
const defaultPluginsInfo = getDefaultPluginsInfo();
|
||||
|
||||
const manifestData = await fetch('https://raw.githubusercontent.com/joplin/plugins/master/manifests.json');
|
||||
@@ -83,7 +86,7 @@ async function start(): Promise<void> {
|
||||
|
||||
const localPluginsVersions = await localPluginsVersion(defaultPluginDir, defaultPluginsInfo);
|
||||
const downloadedPluginNames: PluginIdAndName = await downloadPlugins(localPluginsVersions, defaultPluginsInfo, manifests);
|
||||
await extractPlugins(__dirname, defaultPluginDir, downloadedPluginNames);
|
||||
await extractPlugins(cwd, defaultPluginDir, downloadedPluginNames);
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
@@ -94,3 +97,7 @@ if (require.main === module) {
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = async () => {
|
||||
await start();
|
||||
};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { execCommand2, rootDir } from './tool-utils';
|
||||
import { execCommand } from '@joplin/utils';
|
||||
import { rootDir } from './tool-utils';
|
||||
|
||||
const sqlts = require('@rmp135/sql-ts').default;
|
||||
const fs = require('fs-extra');
|
||||
@@ -6,7 +7,7 @@ const fs = require('fs-extra');
|
||||
async function main() {
|
||||
// Run the CLI app once so as to generate the database file
|
||||
process.chdir(`${rootDir}/packages/app-cli`);
|
||||
await execCommand2('yarn start version');
|
||||
await execCommand('yarn start version');
|
||||
|
||||
const sqlTsConfig = {
|
||||
'client': 'sqlite3',
|
||||
|
||||
12
packages/tools/gulp/tasks/buildCommandIndexRun.js
Normal file
12
packages/tools/gulp/tasks/buildCommandIndexRun.js
Normal file
@@ -0,0 +1,12 @@
|
||||
// Allow running that task "buildCommandIndex" without gulp
|
||||
|
||||
const task = require('./buildCommandIndex.js');
|
||||
|
||||
const main = async () => {
|
||||
await task.fn();
|
||||
};
|
||||
|
||||
main().catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -36,6 +36,7 @@ module.exports = {
|
||||
'packages/fork-sax/**',
|
||||
'packages/lib/plugin_types/**',
|
||||
'packages/server/**',
|
||||
'packages/utils/**',
|
||||
],
|
||||
}).filter(f => !f.endsWith('.d.ts'));
|
||||
|
||||
|
||||
12
packages/tools/gulp/tasks/updateIgnoredTypeScriptBuildRun.js
Normal file
12
packages/tools/gulp/tasks/updateIgnoredTypeScriptBuildRun.js
Normal file
@@ -0,0 +1,12 @@
|
||||
// Allow running that task "updateIgnoredTypeScriptBuild" without gulp
|
||||
|
||||
const task = require('./updateIgnoredTypeScriptBuild.js');
|
||||
|
||||
const main = async () => {
|
||||
await task.fn();
|
||||
};
|
||||
|
||||
main().catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -1,6 +1,7 @@
|
||||
import { readdir, stat, writeFile } from 'fs-extra';
|
||||
import { chdir, cwd } from 'process';
|
||||
import { execCommand2, rootDir } from './tool-utils';
|
||||
import { rootDir } from './tool-utils';
|
||||
import { execCommand } from '@joplin/utils';
|
||||
import yargs = require('yargs');
|
||||
import { rtrimSlashes } from '@joplin/lib/path-utils';
|
||||
|
||||
@@ -13,7 +14,7 @@ interface LicenseInfo {
|
||||
const getLicenses = async (directory: string): Promise<Record<string, LicenseInfo>> => {
|
||||
const previousDir = cwd();
|
||||
await chdir(directory);
|
||||
const result = await execCommand2(['license-checker-rseidelsohn', '--production', '--json'], { quiet: true });
|
||||
const result = await execCommand(['license-checker-rseidelsohn', '--production', '--json'], { quiet: true });
|
||||
const info: Record<string, LicenseInfo> = JSON.parse(result);
|
||||
if (!info) throw new Error(`Could not parse JSON: ${directory}`);
|
||||
await chdir(previousDir);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -91,12 +91,12 @@ msgstr "%d päivää"
|
||||
#: packages/lib/utils/joplinCloud.ts:136 packages/lib/utils/joplinCloud.ts:137
|
||||
#: packages/lib/utils/joplinCloud.ts:138
|
||||
msgid "%d GB"
|
||||
msgstr ""
|
||||
msgstr "%d Gt"
|
||||
|
||||
#: packages/lib/utils/joplinCloud.ts:133 packages/lib/utils/joplinCloud.ts:134
|
||||
#: packages/lib/utils/joplinCloud.ts:135
|
||||
msgid "%d GB storage space"
|
||||
msgstr ""
|
||||
msgstr "%d Gt tallennustila"
|
||||
|
||||
#: packages/lib/models/Setting.ts:1345
|
||||
msgid "%d hour"
|
||||
@@ -109,13 +109,12 @@ msgstr "%d tuntia"
|
||||
#: packages/lib/utils/joplinCloud.ts:124 packages/lib/utils/joplinCloud.ts:125
|
||||
#: packages/lib/utils/joplinCloud.ts:126
|
||||
msgid "%d MB"
|
||||
msgstr ""
|
||||
msgstr "%d Mt"
|
||||
|
||||
#: packages/lib/utils/joplinCloud.ts:121 packages/lib/utils/joplinCloud.ts:122
|
||||
#: packages/lib/utils/joplinCloud.ts:123
|
||||
#, fuzzy
|
||||
msgid "%d MB per note or attachment"
|
||||
msgstr "Muistiinpanon liitteet"
|
||||
msgstr "%d Mt muistiinpanoa tai liitettä kohti"
|
||||
|
||||
#: packages/lib/models/Setting.ts:1342 packages/lib/models/Setting.ts:1343
|
||||
#: packages/lib/models/Setting.ts:1344
|
||||
@@ -128,9 +127,8 @@ msgstr "%d muistiinpanot vastaavat tätä mallia. Poistetaanko ne?"
|
||||
|
||||
#: packages/app-desktop/gui/NoteListControls/NoteListControls.tsx:135
|
||||
#: packages/app-desktop/gui/NoteListControls/NoteListControls.tsx:144
|
||||
#, fuzzy
|
||||
msgid "%s"
|
||||
msgstr "(%s)"
|
||||
msgstr "%s"
|
||||
|
||||
#: packages/app-desktop/gui/utils/NoteListUtils.ts:61
|
||||
msgid "%s - Copy"
|
||||
@@ -323,6 +321,8 @@ msgstr "Lisätyökalut"
|
||||
msgid ""
|
||||
"All data, including notes, notebooks and tags will be permanently deleted."
|
||||
msgstr ""
|
||||
"Kaikki tiedot, mukaan lukien muistiinpanot, muistikirjat ja tunnisteet, "
|
||||
"poistetaan pysyvästi."
|
||||
|
||||
#: packages/app-desktop/gui/Sidebar/Sidebar.tsx:484
|
||||
#: packages/app-mobile/components/screens/Notes.tsx:203
|
||||
@@ -359,8 +359,8 @@ msgstr ""
|
||||
#: packages/app-cli/app/command-mkbook.ts:33
|
||||
#: packages/app-cli/app/command-mv.js:29
|
||||
msgid ""
|
||||
"Ambiguous notebook \"%s\". Please use short notebook id instead - press "
|
||||
"\"ti\" to see the short notebook id"
|
||||
"Ambiguous notebook \"%s\". Please use short notebook id instead - press \"ti"
|
||||
"\" to see the short notebook id"
|
||||
msgstr ""
|
||||
"Epäselvä muistikirja \"%s\". Käytä sen sijaan lyhyttä muistikirjan tunnusta "
|
||||
"- paina \"ti\" nähdäksesi lyhyen muistikirjan tunnuksen"
|
||||
@@ -390,6 +390,8 @@ msgid ""
|
||||
"Are you sure you want to return to the default layout? The current layout "
|
||||
"configuration will be lost."
|
||||
msgstr ""
|
||||
"Haluatko varmasti palata oletus ulkoasuun? Nykyinen ulkoasun määritys "
|
||||
"menetetään."
|
||||
|
||||
#: packages/app-desktop/gui/ConfigScreen/ConfigScreen.tsx:517
|
||||
msgid "Arguments:"
|
||||
@@ -494,7 +496,7 @@ msgstr "Takaisin"
|
||||
|
||||
#: packages/lib/utils/joplinCloud.ts:294
|
||||
msgid "Basic"
|
||||
msgstr ""
|
||||
msgstr "Perus"
|
||||
|
||||
#: packages/app-desktop/gui/NoteEditor/editorCommandDeclarations.ts:33
|
||||
#: packages/app-mobile/components/NoteEditor/MarkdownToolbar/MarkdownToolbar.tsx:132
|
||||
@@ -598,9 +600,8 @@ msgid "Cannot find \"%s\"."
|
||||
msgstr "Ei löydy \"%s\"."
|
||||
|
||||
#: packages/app-cli/app/command-mkbook.ts:28
|
||||
#, fuzzy
|
||||
msgid "Cannot find: \"%s\""
|
||||
msgstr "Ei löydy \"%s\"."
|
||||
msgstr "Ei löydy: \"%s\""
|
||||
|
||||
#: packages/app-cli/app/command-sync.ts:164
|
||||
msgid "Cannot initialise synchroniser."
|
||||
@@ -743,9 +744,8 @@ msgid "Close"
|
||||
msgstr "Sulkea"
|
||||
|
||||
#: packages/app-mobile/components/Dropdown.tsx:166
|
||||
#, fuzzy
|
||||
msgid "Close dropdown"
|
||||
msgstr "Sulje ikkuna"
|
||||
msgstr "Sulje pudotusvalikko"
|
||||
|
||||
#: packages/app-desktop/gui/KeymapConfig/utils/getLabel.ts:24
|
||||
#: packages/app-desktop/gui/MenuBar.tsx:596
|
||||
@@ -857,7 +857,7 @@ msgstr "Ristiriidat (liitteet)"
|
||||
|
||||
#: packages/lib/utils/joplinCloud.ts:171
|
||||
msgid "Consolidated billing"
|
||||
msgstr ""
|
||||
msgstr "Yhdistetty laskutus"
|
||||
|
||||
#: packages/app-desktop/gui/ConfigScreen/controls/plugins/SearchPlugins.tsx:110
|
||||
msgid "Content provided by %s"
|
||||
@@ -865,7 +865,7 @@ msgstr "Sisällön toimittaa %s"
|
||||
|
||||
#: packages/app-mobile/components/ProfileSwitcher/ProfileSwitcher.tsx:64
|
||||
msgid "Continue"
|
||||
msgstr ""
|
||||
msgstr "Jatkaa"
|
||||
|
||||
#: packages/app-mobile/components/screens/Note.tsx:930
|
||||
msgid "Convert to note"
|
||||
@@ -970,9 +970,8 @@ msgstr ""
|
||||
"Virhe oli: \"%s\""
|
||||
|
||||
#: packages/app-mobile/components/ProfileSwitcher/ProfileSwitcher.tsx:55
|
||||
#, fuzzy
|
||||
msgid "Could not switch profile: %s"
|
||||
msgstr "Laajennuksen asentaminen epäonnistui: %s"
|
||||
msgstr "Profiilia ei voitu vaihtaa: %s"
|
||||
|
||||
#: packages/lib/components/EncryptionConfigScreen/utils.ts:219
|
||||
msgid "Could not upgrade master key: %s"
|
||||
@@ -988,16 +987,15 @@ msgstr ""
|
||||
|
||||
#: packages/app-mobile/components/biometrics/BiometricPopup.tsx:29
|
||||
msgid "Could not verify your identify"
|
||||
msgstr ""
|
||||
msgstr "Henkilöllisyyttäsi ei voitu vahvistaa"
|
||||
|
||||
#: packages/app-desktop/gui/PromptDialog.tsx:260
|
||||
msgid "Create"
|
||||
msgstr "Luo"
|
||||
|
||||
#: packages/app-cli/app/command-mkbook.ts:19
|
||||
#, fuzzy
|
||||
msgid "Create a new notebook under a parent notebook."
|
||||
msgstr "Luo uuden muistikirjan."
|
||||
msgstr "Luo uusi muistikirja päämuistikirjan alle."
|
||||
|
||||
#: packages/app-mobile/components/note-list.js:101
|
||||
msgid "Create a notebook"
|
||||
@@ -1220,9 +1218,8 @@ msgid "Delete plugin \"%s\"?"
|
||||
msgstr "Poista laajennus \"%s\"?"
|
||||
|
||||
#: packages/app-mobile/components/ProfileSwitcher/ProfileSwitcher.tsx:101
|
||||
#, fuzzy
|
||||
msgid "Delete profile \"%s\""
|
||||
msgstr "Poista muistiinpano \"%s\"?"
|
||||
msgstr "Poista profiili \"%s\""
|
||||
|
||||
#: packages/app-mobile/components/ScreenHeader.tsx:420
|
||||
msgid "Delete selected notes"
|
||||
@@ -1241,9 +1238,8 @@ msgstr ""
|
||||
"muistikirjaa."
|
||||
|
||||
#: packages/app-mobile/components/ProfileSwitcher/ProfileSwitcher.tsx:97
|
||||
#, fuzzy
|
||||
msgid "Delete this profile?"
|
||||
msgstr "Poistetaanko nämä %d muistiinpanot?"
|
||||
msgstr "Poistetaanko tämä profiili?"
|
||||
|
||||
#: packages/lib/Synchronizer.ts:186
|
||||
msgid "Deleted local items: %d."
|
||||
@@ -1488,9 +1484,8 @@ msgid "Edit notebook"
|
||||
msgstr "Muokkaa muistikirjaa"
|
||||
|
||||
#: packages/app-mobile/components/ProfileSwitcher/ProfileEditor.tsx:87
|
||||
#, fuzzy
|
||||
msgid "Edit profile"
|
||||
msgstr "Vie profiili"
|
||||
msgstr "Muokkaa profiilia"
|
||||
|
||||
#: packages/app-desktop/commands/editProfileConfig.ts:9
|
||||
msgid "Edit profile configuration..."
|
||||
@@ -1582,7 +1577,7 @@ msgstr "Ota käyttöön audiosoitin"
|
||||
|
||||
#: packages/app-mobile/components/biometrics/BiometricPopup.tsx:61
|
||||
msgid "Enable biometrics authentication?"
|
||||
msgstr ""
|
||||
msgstr "Otetaanko biometrinen todennus käyttöön?"
|
||||
|
||||
#: packages/lib/models/Setting.ts:1146
|
||||
msgid "Enable deflist syntax"
|
||||
@@ -1635,7 +1630,7 @@ msgstr "Ota pehmeät tauot käyttöön"
|
||||
|
||||
#: packages/lib/models/Setting.ts:1048
|
||||
msgid "Enable spellcheck in the text editor"
|
||||
msgstr ""
|
||||
msgstr "Ota oikeinkirjoituksen tarkistus käyttöön tekstieditorissa"
|
||||
|
||||
#: packages/lib/models/Setting.ts:1143
|
||||
msgid "Enable table of contents extension"
|
||||
@@ -2298,7 +2293,7 @@ msgstr "Kohteet, joita ei voi synkronoida"
|
||||
|
||||
#: packages/app-desktop/gui/MenuBar.tsx:792
|
||||
msgid "Join us on Twitter"
|
||||
msgstr ""
|
||||
msgstr "Liity meihin Twitterissä"
|
||||
|
||||
#: packages/app-desktop/gui/SyncWizard/Dialog.tsx:330
|
||||
msgid ""
|
||||
@@ -2547,14 +2542,12 @@ msgid "Manage master password..."
|
||||
msgstr "Pääsalasanan hallinta..."
|
||||
|
||||
#: packages/lib/utils/joplinCloud.ts:165
|
||||
#, fuzzy
|
||||
msgid "Manage multiple users"
|
||||
msgstr "Pääsalasanan hallinta"
|
||||
msgstr "Hallitse useita käyttäjiä"
|
||||
|
||||
#: packages/app-mobile/components/screens/ConfigScreen.tsx:611
|
||||
#, fuzzy
|
||||
msgid "Manage profiles"
|
||||
msgstr "Päivitä profiili"
|
||||
msgstr "Hallitse profiileja"
|
||||
|
||||
#: packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginsStates.tsx:320
|
||||
msgid "Manage your plugins"
|
||||
@@ -2621,9 +2614,8 @@ msgid "Max Item Size"
|
||||
msgstr "Kohteen enimmäiskoko"
|
||||
|
||||
#: packages/lib/utils/joplinCloud.ts:117
|
||||
#, fuzzy
|
||||
msgid "Max note or attachment size"
|
||||
msgstr "Muistiinpanon liitteet"
|
||||
msgstr "Muistiinpanon tai liitteen enimmäiskoko"
|
||||
|
||||
#: packages/server/src/routes/admin/users.ts:150
|
||||
msgid "Max Total Size"
|
||||
@@ -2642,9 +2634,8 @@ msgid "Missing required argument: %s"
|
||||
msgstr "Vaadittu argumentti puuttuu: %s"
|
||||
|
||||
#: packages/app-cli/app/cli-utils.js:135
|
||||
#, fuzzy
|
||||
msgid "Missing required flag value: %s"
|
||||
msgstr "Vaadittu argumentti puuttuu: %s"
|
||||
msgstr "Pakollinen lipun arvo puuttuu: %s"
|
||||
|
||||
#: packages/app-mobile/components/side-menu-content.tsx:457
|
||||
msgid "Mobile data - auto-sync disabled"
|
||||
@@ -2819,9 +2810,8 @@ msgid "Not generated"
|
||||
msgstr "Ei luotu"
|
||||
|
||||
#: packages/app-mobile/components/biometrics/BiometricPopup.tsx:70
|
||||
#, fuzzy
|
||||
msgid "Not now"
|
||||
msgstr "Hae se nyt"
|
||||
msgstr "Ei nyt"
|
||||
|
||||
#: packages/app-desktop/gui/NoteEditor/NoteTitle/NoteTitleBar.tsx:110
|
||||
#: packages/server/src/models/UserModel.ts:215
|
||||
@@ -3084,7 +3074,7 @@ msgstr "Liitä"
|
||||
#: packages/app-desktop/gui/NoteEditor/commands/pasteAsText.ts:6
|
||||
#: packages/app-desktop/gui/NoteEditor/utils/contextMenu.ts:181
|
||||
msgid "Paste as text"
|
||||
msgstr ""
|
||||
msgstr "Liitä tekstinä"
|
||||
|
||||
#: packages/app-desktop/gui/ConfigScreen/ConfigScreen.tsx:541
|
||||
msgid "Path:"
|
||||
@@ -3097,7 +3087,7 @@ msgstr "PDF tiedosto"
|
||||
|
||||
#: packages/lib/utils/joplinCloud.ts:355
|
||||
msgid "Per user. Minimum of %d users."
|
||||
msgstr ""
|
||||
msgstr "Käyttäjää kohti. Vähintään %d käyttäjää."
|
||||
|
||||
#: packages/app-mobile/components/screens/Note.tsx:404
|
||||
msgid "Permission needed"
|
||||
@@ -3258,16 +3248,15 @@ msgstr "Tulosta"
|
||||
|
||||
#: packages/lib/utils/joplinCloud.ts:183
|
||||
msgid "Priority support"
|
||||
msgstr ""
|
||||
msgstr "Ensisijainen tuki"
|
||||
|
||||
#: packages/app-mobile/components/screens/ConfigScreen.tsx:703
|
||||
msgid "Privacy Policy"
|
||||
msgstr "Tietosuojakäytäntö"
|
||||
|
||||
#: packages/lib/utils/joplinCloud.ts:316
|
||||
#, fuzzy
|
||||
msgid "Pro"
|
||||
msgstr "Profiili"
|
||||
msgstr "Ammattilainen"
|
||||
|
||||
#: packages/server/src/services/TaskService.ts:24
|
||||
msgid "Process failed payment subscriptions"
|
||||
@@ -3286,9 +3275,8 @@ msgid "Profile"
|
||||
msgstr "Profiili"
|
||||
|
||||
#: packages/app-mobile/components/ProfileSwitcher/ProfileEditor.tsx:95
|
||||
#, fuzzy
|
||||
msgid "Profile name"
|
||||
msgstr "Profiilin nimi:"
|
||||
msgstr "Profiilin nimi"
|
||||
|
||||
#: packages/app-desktop/gui/MainScreen/commands/addProfile.ts:17
|
||||
msgid "Profile name:"
|
||||
@@ -3299,9 +3287,8 @@ msgid "Profile Version: %s"
|
||||
msgstr "Profiilin versio: %s"
|
||||
|
||||
#: packages/app-mobile/components/ProfileSwitcher/ProfileSwitcher.tsx:155
|
||||
#, fuzzy
|
||||
msgid "Profiles"
|
||||
msgstr "Profiili"
|
||||
msgstr "Profiilit"
|
||||
|
||||
#: packages/app-mobile/components/screens/Note.tsx:944
|
||||
msgid "Properties"
|
||||
@@ -3450,9 +3437,8 @@ msgid "Replace: "
|
||||
msgstr "Vaihda: "
|
||||
|
||||
#: packages/app-desktop/gui/MainScreen/commands/resetLayout.ts:7
|
||||
#, fuzzy
|
||||
msgid "Reset application layout"
|
||||
msgstr "Sovelluksen asettelun muuttaminen"
|
||||
msgstr "Palauta sovelluksen asettelu"
|
||||
|
||||
#: packages/app-desktop/gui/MasterPasswordDialog/Dialog.tsx:219
|
||||
#: packages/app-desktop/gui/MasterPasswordDialog/Dialog.tsx:220
|
||||
@@ -3692,9 +3678,8 @@ msgid "Share"
|
||||
msgstr "Jaa"
|
||||
|
||||
#: packages/lib/utils/joplinCloud.ts:159
|
||||
#, fuzzy
|
||||
msgid "Share and collaborate on a notebook"
|
||||
msgstr "Muistiinpanoja voi luoda vain muistikirjaan."
|
||||
msgstr "Muistikirjan jakaminen ja yhteiskäyttö"
|
||||
|
||||
#: packages/app-desktop/gui/ShareFolderDialog/ShareFolderDialog.tsx:339
|
||||
msgid "Share Notebook"
|
||||
@@ -3706,7 +3691,7 @@ msgstr "Muistikirjan jakaminen..."
|
||||
|
||||
#: packages/lib/utils/joplinCloud.ts:177
|
||||
msgid "Sharing access control"
|
||||
msgstr ""
|
||||
msgstr "Käyttöoikeuksien hallinnan jakaminen"
|
||||
|
||||
#: packages/app-desktop/gui/ShareFolderDialog/ShareFolderDialog.tsx:305
|
||||
msgid "Sharing notebook..."
|
||||
@@ -3932,7 +3917,7 @@ msgstr "Lopeta ulkoisen tekstieditorin muokkaus"
|
||||
|
||||
#: packages/lib/utils/joplinCloud.ts:129
|
||||
msgid "Storage space"
|
||||
msgstr ""
|
||||
msgstr "Tallennustila"
|
||||
|
||||
#: packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/setupToolbarButtons.ts:19
|
||||
msgid "Strikethrough"
|
||||
@@ -4000,7 +3985,7 @@ msgstr ""
|
||||
|
||||
#: packages/lib/utils/joplinCloud.ts:147
|
||||
msgid "Sync as many devices as you want"
|
||||
msgstr ""
|
||||
msgstr "Synkronoi niin monta laitetta kuin haluat"
|
||||
|
||||
#: packages/app-mobile/components/screens/ConfigScreen.tsx:612
|
||||
msgid "Sync Status"
|
||||
@@ -4115,7 +4100,7 @@ msgstr "Tehtävät"
|
||||
|
||||
#: packages/lib/utils/joplinCloud.ts:338
|
||||
msgid "Teams"
|
||||
msgstr ""
|
||||
msgstr "Tiimit"
|
||||
|
||||
#: packages/lib/models/Setting.ts:1366
|
||||
msgid "Text editor command"
|
||||
@@ -4130,6 +4115,8 @@ msgid ""
|
||||
"The active profile cannot be deleted. Switch to a different profile and try "
|
||||
"again."
|
||||
msgstr ""
|
||||
"Aktiivista profiilia ei voi poistaa. Vaihda toiseen profiiliin ja yritä "
|
||||
"uudelleen."
|
||||
|
||||
#: packages/app-desktop/bridge.ts:280
|
||||
msgid ""
|
||||
@@ -4195,7 +4182,7 @@ msgstr ""
|
||||
|
||||
#: packages/lib/services/profileConfig/index.ts:104
|
||||
msgid "The default profile cannot be deleted"
|
||||
msgstr ""
|
||||
msgstr "Oletusprofiilia ei voi poistaa"
|
||||
|
||||
#: packages/lib/models/Setting.ts:1366
|
||||
msgid ""
|
||||
@@ -4343,6 +4330,8 @@ msgid ""
|
||||
"The WebDAV implementation of %s is incompatible with Joplin, and as such is "
|
||||
"no longer supported. Please use a different sync method."
|
||||
msgstr ""
|
||||
"%s WebDAV toteutus ei ole yhteensopiva Joplinin kanssa, joten sitä ei enää "
|
||||
"tueta. Käytä toista synkronointitapaa."
|
||||
|
||||
#: packages/lib/models/Setting.ts:827
|
||||
msgid "Theme"
|
||||
@@ -4356,7 +4345,7 @@ msgstr ""
|
||||
|
||||
#: packages/app-mobile/components/screens/ConfigScreen.tsx:341
|
||||
msgid "There are unsaved changes."
|
||||
msgstr ""
|
||||
msgstr "On tallentamattomia muutoksia."
|
||||
|
||||
#: packages/app-desktop/gui/NoteList/NoteList.tsx:512
|
||||
msgid ""
|
||||
@@ -4580,6 +4569,8 @@ msgid ""
|
||||
"To switch the profile, the app is going to close and you will need to "
|
||||
"restart it."
|
||||
msgstr ""
|
||||
"Jos haluat vaihtaa profiilia, sovellus suljetaan ja sinun on käynnistettävä "
|
||||
"se uudelleen."
|
||||
|
||||
#: packages/app-mobile/components/screens/ConfigScreen.tsx:651
|
||||
msgid ""
|
||||
@@ -4661,9 +4652,8 @@ msgstr "Yritä uudestaan"
|
||||
|
||||
#: packages/lib/utils/joplinCloud.ts:309 packages/lib/utils/joplinCloud.ts:331
|
||||
#: packages/lib/utils/joplinCloud.ts:353
|
||||
#, fuzzy
|
||||
msgid "Try it now"
|
||||
msgstr "Hae se nyt"
|
||||
msgstr "Kokeile nyt"
|
||||
|
||||
#: packages/app-cli/app/command-help.js:71
|
||||
msgid ""
|
||||
@@ -4822,7 +4812,7 @@ msgstr "Käyttö: %s"
|
||||
|
||||
#: packages/lib/models/Setting.ts:1640
|
||||
msgid "Use biometrics to secure access to the app"
|
||||
msgstr ""
|
||||
msgstr "Käytä biometrisiä tunnisteita suojataksesi pääsyn sovellukseen"
|
||||
|
||||
#: packages/app-cli/app/command-ls.js:32 packages/app-cli/app/command-tag.js:18
|
||||
msgid ""
|
||||
@@ -4861,6 +4851,8 @@ msgid ""
|
||||
"Use your biometrics to secure access to your application. You can always set "
|
||||
"it up later in Settings."
|
||||
msgstr ""
|
||||
"Käytä biometrisiä tunnisteita suojataksesi pääsyn sovellukseen. Voit "
|
||||
"määrittää sen myöhemmin asetuksissa."
|
||||
|
||||
#: packages/lib/models/Setting.ts:1244
|
||||
msgid ""
|
||||
@@ -4896,7 +4888,7 @@ msgstr "Kelvollinen"
|
||||
|
||||
#: packages/app-mobile/components/biometrics/BiometricPopup.tsx:25
|
||||
msgid "Verify your identity"
|
||||
msgstr ""
|
||||
msgstr "Vahvista henkilöllisyytesi"
|
||||
|
||||
#: packages/app-desktop/gui/NoteList/NoteList.tsx:167
|
||||
msgid "View"
|
||||
|
||||
@@ -653,7 +653,7 @@ msgstr ""
|
||||
|
||||
#: packages/app-mobile/components/NoteEditor/SearchPanel.tsx:328
|
||||
msgid "Case sensitive"
|
||||
msgstr ""
|
||||
msgstr "Razlikuje velika i mala slova"
|
||||
|
||||
#: packages/app-desktop/gui/MainScreen/commands/toggleLayoutMoveMode.ts:7
|
||||
msgid "Change application layout"
|
||||
@@ -1072,7 +1072,7 @@ msgstr "Stvaranje izvještaja …"
|
||||
|
||||
#: packages/app-desktop/checkForUpdates.ts:180
|
||||
msgid "Current version is up-to-date."
|
||||
msgstr "Trenutačna verzija je najnovija verzija."
|
||||
msgstr "Trenutačna verzija je aktualna."
|
||||
|
||||
#: packages/lib/models/Note.ts:38
|
||||
msgid "custom order"
|
||||
@@ -1174,7 +1174,7 @@ msgstr "Izbriši istekle sesije"
|
||||
|
||||
#: packages/server/src/services/TaskService.ts:20
|
||||
msgid "Delete expired tokens"
|
||||
msgstr "Izbriši istekle tokene"
|
||||
msgstr "Izbriši istekle ključeve"
|
||||
|
||||
#: packages/app-desktop/gui/NoteEditor/editorCommandDeclarations.ts:88
|
||||
msgid "Delete line"
|
||||
@@ -1392,7 +1392,7 @@ msgstr ""
|
||||
|
||||
#: packages/app-mobile/components/NoteEditor/EditLinkDialog.tsx:149
|
||||
msgid "Done"
|
||||
msgstr ""
|
||||
msgstr "Gotovo"
|
||||
|
||||
#: packages/app-desktop/checkForUpdates.ts:199
|
||||
msgid "Download"
|
||||
@@ -1582,7 +1582,7 @@ msgstr "Aktiviraj audio-player"
|
||||
|
||||
#: packages/app-mobile/components/biometrics/BiometricPopup.tsx:61
|
||||
msgid "Enable biometrics authentication?"
|
||||
msgstr ""
|
||||
msgstr "Aktivirati biometrijsku autentifikaciju?"
|
||||
|
||||
#: packages/lib/models/Setting.ts:1146
|
||||
msgid "Enable deflist syntax"
|
||||
@@ -2228,7 +2228,7 @@ msgstr "Umetnuti kȏd"
|
||||
|
||||
#: packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/setupToolbarButtons.ts:24
|
||||
msgid "Insert"
|
||||
msgstr "Umetnuto"
|
||||
msgstr "Umetni"
|
||||
|
||||
#: packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/CodeMirror.tsx:199
|
||||
msgid "Insert Hyperlink"
|
||||
@@ -2394,7 +2394,7 @@ msgstr ""
|
||||
|
||||
#: packages/lib/models/Setting.ts:1530
|
||||
msgid "Keep note history for"
|
||||
msgstr "Čuvaj povijest bilješke"
|
||||
msgstr "Čuvaj povijest bilježaka"
|
||||
|
||||
#: packages/lib/models/Setting.ts:1403
|
||||
msgid "Keyboard Mode"
|
||||
@@ -2873,7 +2873,7 @@ msgstr "Bilješka ne postoji: „%s”. Želiš li je stvoriti?"
|
||||
#: packages/app-mobile/components/NoteEditor/NoteEditor.tsx:82
|
||||
#, fuzzy
|
||||
msgid "Note editor"
|
||||
msgstr "Povijest bilježaka"
|
||||
msgstr "Uređivač za bilješke"
|
||||
|
||||
#: packages/app-cli/app/command-edit.js:97
|
||||
msgid "Note has been saved."
|
||||
@@ -3058,7 +3058,7 @@ msgstr "Ili stvori novi račun."
|
||||
#: packages/app-mobile/components/NoteEditor/MarkdownToolbar/MarkdownToolbar.tsx:82
|
||||
#, fuzzy
|
||||
msgid "Ordered list"
|
||||
msgstr "Stvori korisnika"
|
||||
msgstr "Razvrstan popis"
|
||||
|
||||
#: packages/app-desktop/gui/MenuBar.tsx:409
|
||||
msgid "Other applications..."
|
||||
@@ -3150,8 +3150,8 @@ msgid ""
|
||||
"Please note that if it is a large notebook, it may take a few minutes for "
|
||||
"all the notes to show up on the recipient's device."
|
||||
msgstr ""
|
||||
"Imaj na umu, da ako je velika bilježnica, može potrajati nekoliko minuta dok "
|
||||
"se sve bilješke pojave na uređaju primatelja."
|
||||
"Imaj na umu, da ako je bilježnica velika, pojavljivanje svih bilježaka na "
|
||||
"uređaju primatelja može potrajati nekoliko minuta."
|
||||
|
||||
#: packages/lib/onedrive-api-node-utils.js:118
|
||||
msgid ""
|
||||
@@ -3162,9 +3162,9 @@ msgid ""
|
||||
"will be shared with any third party."
|
||||
msgstr ""
|
||||
"Otvori sljedeći URL u pregledniku za autentificiranje programa. Program će "
|
||||
"stvoriti mapu u „Aplikacije/Joplin” i koristit će je samo za čitanje i "
|
||||
"pisanje. Program neće moći pristupiti datotekama izvan ove mape niti bilo "
|
||||
"kojim drugim osobnim podacima. Nikoji podaci se neće dijeliti s drugima."
|
||||
"stvoriti mapu u „Aplikacije/Joplin” dozvolama za čitanje i pisanje. Program "
|
||||
"neće moći pristupiti datotekama izvan ove mape niti bilo kojim drugim "
|
||||
"osobnim podacima. Nikoji podaci se neće dijeliti s drugima."
|
||||
|
||||
#: packages/app-cli/app/command-ls.js:63
|
||||
msgid "Please select a notebook first."
|
||||
@@ -3262,7 +3262,7 @@ msgstr "Pritisni za postavljanje lozinke za dešifriranje."
|
||||
|
||||
#: packages/app-mobile/components/NoteEditor/SearchPanel.tsx:278
|
||||
msgid "Previous match"
|
||||
msgstr ""
|
||||
msgstr "Prethodno poklapanje"
|
||||
|
||||
#: packages/app-desktop/gui/NotePropertiesDialog.min.js:307
|
||||
#: packages/app-desktop/gui/NotePropertiesDialog.tsx:329
|
||||
@@ -3464,7 +3464,7 @@ msgstr "Označi sve"
|
||||
|
||||
#: packages/app-mobile/components/NoteEditor/SearchPanel.tsx:236
|
||||
msgid "Replace with..."
|
||||
msgstr ""
|
||||
msgstr "Zamijeni sa …"
|
||||
|
||||
#: packages/app-mobile/components/NoteEditor/SearchPanel.tsx:257
|
||||
msgid "Replace: "
|
||||
@@ -3473,7 +3473,7 @@ msgstr ""
|
||||
#: packages/app-desktop/gui/MainScreen/commands/resetLayout.ts:7
|
||||
#, fuzzy
|
||||
msgid "Reset application layout"
|
||||
msgstr "Promijeni raspored programa"
|
||||
msgstr "Obnovi raspored programa"
|
||||
|
||||
#: packages/app-desktop/gui/MasterPasswordDialog/Dialog.tsx:219
|
||||
#: packages/app-desktop/gui/MasterPasswordDialog/Dialog.tsx:220
|
||||
@@ -3729,7 +3729,7 @@ msgstr "Dijeli bilježnicu …"
|
||||
|
||||
#: packages/lib/utils/joplinCloud.ts:177
|
||||
msgid "Sharing access control"
|
||||
msgstr ""
|
||||
msgstr "Dijeljenje kontrole pristupa"
|
||||
|
||||
#: packages/app-desktop/gui/ShareFolderDialog/ShareFolderDialog.tsx:305
|
||||
msgid "Sharing notebook..."
|
||||
@@ -3737,7 +3737,7 @@ msgstr "Dijeljenje bilježnice …"
|
||||
|
||||
#: packages/app-cli/app/command-help.js:44
|
||||
msgid "Shortcuts are not available in CLI mode."
|
||||
msgstr "Prečaci nisu podržani u naredbenom retku."
|
||||
msgstr "Prečaci nisu dostupni u naredbenom retku."
|
||||
|
||||
#: packages/app-mobile/components/NoteEditor/SearchPanel.tsx:208
|
||||
#, fuzzy
|
||||
@@ -3776,7 +3776,7 @@ msgstr "Prikaži broj bilježaka"
|
||||
|
||||
#: packages/lib/models/Setting.ts:942
|
||||
msgid "Show sort order buttons"
|
||||
msgstr "Prikaži gumbe redoslijeda"
|
||||
msgstr "Prikaži gumbe za određivanje redoslijeda"
|
||||
|
||||
#: packages/lib/models/Setting.ts:1162
|
||||
msgid "Show tray icon"
|
||||
@@ -4021,12 +4021,12 @@ msgid ""
|
||||
"Switches to [notebook] - all further operations will happen within this "
|
||||
"notebook."
|
||||
msgstr ""
|
||||
"Mijenja se u bilježnicu [notebook] – sve daljnje operacije izvode se u toj "
|
||||
"bilježnici."
|
||||
"Prebacuje na bilježnicu [notebook] – sve daljnje operacije će se izvoditi u "
|
||||
"ovoj bilježnici."
|
||||
|
||||
#: packages/lib/utils/joplinCloud.ts:147
|
||||
msgid "Sync as many devices as you want"
|
||||
msgstr ""
|
||||
msgstr "Sinkroniziraj koliko god uređaja želiš"
|
||||
|
||||
#: packages/app-mobile/components/screens/ConfigScreen.tsx:612
|
||||
msgid "Sync Status"
|
||||
@@ -4212,7 +4212,7 @@ msgid ""
|
||||
"The default encryption method has been changed to a more secure one and it "
|
||||
"is recommended that you apply it to your data."
|
||||
msgstr ""
|
||||
"Standardna metoda šifriranja promijenjena je u sigurniju metodu. "
|
||||
"Standardna metoda šifriranja je promijenjena sa sigurnijom metodom. "
|
||||
"Preporučujemo da je primijeniš na tvoje podatke."
|
||||
|
||||
#: packages/app-desktop/gui/MainScreen/MainScreen.tsx:619
|
||||
@@ -4404,7 +4404,7 @@ msgid ""
|
||||
"\n"
|
||||
"%s"
|
||||
msgstr ""
|
||||
"Došlo je do [konflikta](%s) s dolje navedenim privitkom.\n"
|
||||
"Došlo je do konflikta [conflict](%s) s dolje navedenim privitkom.\n"
|
||||
"\n"
|
||||
"%s"
|
||||
|
||||
@@ -4467,7 +4467,7 @@ msgid ""
|
||||
"access Joplin."
|
||||
msgstr ""
|
||||
"Ovaj ključ za autorizaciju potreban je samo za dozvoljavanje drugim "
|
||||
"programima pristupiti Joplinu."
|
||||
"programima da pristupe Joplinu."
|
||||
|
||||
#: packages/app-desktop/gui/ResourceScreen.tsx:231
|
||||
msgid ""
|
||||
@@ -4747,7 +4747,7 @@ msgstr ""
|
||||
#: packages/app-mobile/components/NoteEditor/MarkdownToolbar/MarkdownToolbar.tsx:69
|
||||
#, fuzzy
|
||||
msgid "Unordered list"
|
||||
msgstr "Stvori korisnika"
|
||||
msgstr "Nerazvstan popis"
|
||||
|
||||
#: packages/app-desktop/gui/ShareNoteDialog.tsx:162
|
||||
msgid "Unpublish note"
|
||||
@@ -4853,7 +4853,7 @@ msgstr "Korištenje: %s"
|
||||
|
||||
#: packages/lib/models/Setting.ts:1640
|
||||
msgid "Use biometrics to secure access to the app"
|
||||
msgstr ""
|
||||
msgstr "Koristi biometrijske podatke za osiguravanje pristupa programu"
|
||||
|
||||
#: packages/app-cli/app/command-ls.js:32 packages/app-cli/app/command-tag.js:18
|
||||
msgid ""
|
||||
@@ -5437,6 +5437,9 @@ msgstr "Umanji prikaz"
|
||||
#~ msgid "Give focus to next pane"
|
||||
#~ msgstr "Fokusiraj sljedeće okno"
|
||||
|
||||
#~ msgid "Give focus to previous pane"
|
||||
#~ msgstr "Fokusiraj prethodno okno"
|
||||
|
||||
#~ msgid "Exit command line mode"
|
||||
#~ msgstr "Napusti naredbeni redak"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/tools",
|
||||
"version": "2.10.2",
|
||||
"version": "2.11.0",
|
||||
"description": "Various tools for Joplin",
|
||||
"main": "index.js",
|
||||
"author": "Laurent Cozic",
|
||||
@@ -20,13 +20,12 @@
|
||||
},
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@joplin/lib": "^2.10.2",
|
||||
"@joplin/renderer": "^2.10.2",
|
||||
"@types/node-fetch": "2.6.2",
|
||||
"@types/yargs": "17.0.20",
|
||||
"@joplin/lib": "~2.11",
|
||||
"@joplin/renderer": "~2.11",
|
||||
"@joplin/utils": "~2.11",
|
||||
"dayjs": "1.11.7",
|
||||
"execa": "4.1.0",
|
||||
"fs-extra": "11.1.0",
|
||||
"fs-extra": "11.1.1",
|
||||
"gettext-parser": "6.0.0",
|
||||
"glob": "8.1.0",
|
||||
"markdown-it": "13.0.1",
|
||||
@@ -48,13 +47,15 @@
|
||||
"@types/jest": "29.2.6",
|
||||
"@types/mustache": "4.2.2",
|
||||
"@types/node": "18.11.18",
|
||||
"gettext-extractor": "3.6.2",
|
||||
"@types/node-fetch": "2.6.2",
|
||||
"@types/yargs": "17.0.20",
|
||||
"gettext-extractor": "3.7.0",
|
||||
"gulp": "4.0.2",
|
||||
"html-entities": "1.4.0",
|
||||
"jest": "29.4.3",
|
||||
"rss": "1.2.2",
|
||||
"sass": "1.58.3",
|
||||
"sqlite3": "5.1.4",
|
||||
"sass": "1.59.3",
|
||||
"sqlite3": "5.1.6",
|
||||
"typescript": "4.9.4"
|
||||
},
|
||||
"gitHead": "eb4b0e64eab40a51b0895d3a40a9d8c3cb7b1b14"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { execCommand } from '@joplin/utils';
|
||||
import * as fs from 'fs-extra';
|
||||
import { execCommandVerbose, execCommandWithPipes, githubRelease, githubOauthToken, fileExists, gitPullTry, completeReleaseWithChangelog, execCommand2 } from './tool-utils';
|
||||
import { execCommandVerbose, execCommandWithPipes, githubRelease, githubOauthToken, fileExists, gitPullTry, completeReleaseWithChangelog } from './tool-utils';
|
||||
const path = require('path');
|
||||
const fetch = require('node-fetch');
|
||||
const uriTemplate = require('uri-template');
|
||||
@@ -150,7 +151,7 @@ async function main() {
|
||||
const isPreRelease = !('type' in argv) || argv.type === 'prerelease';
|
||||
|
||||
process.chdir(rnDir);
|
||||
await execCommand2('yarn run build', { showStdout: false });
|
||||
await execCommand('yarn run build', { showStdout: false });
|
||||
|
||||
if (isPreRelease) console.info('Creating pre-release');
|
||||
console.info('Updating version numbers in build.gradle...');
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { execCommand2, rootDir, completeReleaseWithChangelog } from './tool-utils';
|
||||
import { execCommand } from '@joplin/utils';
|
||||
import { rootDir, completeReleaseWithChangelog } from './tool-utils';
|
||||
|
||||
const appDir = `${rootDir}/packages/app-cli`;
|
||||
const changelogPath = `${rootDir}/readme/changelog_cli.md`;
|
||||
@@ -8,19 +9,19 @@ const changelogPath = `${rootDir}/readme/changelog_cli.md`;
|
||||
async function main() {
|
||||
process.chdir(appDir);
|
||||
|
||||
await execCommand2('git pull');
|
||||
await execCommand('git pull');
|
||||
|
||||
const newVersion = (await execCommand2('npm version patch')).trim();
|
||||
const newVersion = (await execCommand('npm version patch')).trim();
|
||||
console.info(`Building ${newVersion}...`);
|
||||
const newTag = `cli-${newVersion}`;
|
||||
|
||||
await execCommand2('touch app/main.js');
|
||||
await execCommand2('yarn run build');
|
||||
await execCommand2('cp ../../README.md build/');
|
||||
await execCommand('touch app/main.js');
|
||||
await execCommand('yarn run build');
|
||||
await execCommand('cp ../../README.md build/');
|
||||
|
||||
process.chdir(`${appDir}/build`);
|
||||
|
||||
await execCommand2('npm publish');
|
||||
await execCommand('npm publish');
|
||||
|
||||
await completeReleaseWithChangelog(changelogPath, newVersion, newTag, 'CLI', false);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { execCommand2, gitCurrentBranch, githubRelease, gitPullTry, rootDir } from './tool-utils';
|
||||
import { execCommand } from '@joplin/utils';
|
||||
import { gitCurrentBranch, githubRelease, gitPullTry, rootDir } from './tool-utils';
|
||||
|
||||
const appDir = `${rootDir}/packages/app-desktop`;
|
||||
|
||||
@@ -11,16 +12,16 @@ async function main() {
|
||||
|
||||
console.info(`Running from: ${process.cwd()}`);
|
||||
|
||||
const version = (await execCommand2('npm version patch')).trim();
|
||||
const version = (await execCommand('npm version patch')).trim();
|
||||
const tagName = version;
|
||||
|
||||
console.info(`New version number: ${version}`);
|
||||
|
||||
await execCommand2('git add -A');
|
||||
await execCommand2(`git commit -m "Desktop release ${version}"`);
|
||||
await execCommand2(`git tag ${tagName}`);
|
||||
await execCommand2('git push');
|
||||
await execCommand2('git push --tags');
|
||||
await execCommand('git add -A');
|
||||
await execCommand(`git commit -m "Desktop release ${version}"`);
|
||||
await execCommand(`git tag ${tagName}`);
|
||||
await execCommand('git push');
|
||||
await execCommand('git push --tags');
|
||||
|
||||
const releaseOptions = { isDraft: true, isPreRelease: !!argv.beta };
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { execCommand } from '@joplin/utils';
|
||||
import { chdir } from 'process';
|
||||
import { rootDir, gitPullTry, execCommand2, releaseFinalGitCommands } from './tool-utils';
|
||||
import { rootDir, gitPullTry, releaseFinalGitCommands } from './tool-utils';
|
||||
|
||||
const workDir = `${rootDir}/packages/plugin-repo-cli`;
|
||||
|
||||
@@ -7,18 +8,18 @@ async function main() {
|
||||
await gitPullTry();
|
||||
|
||||
chdir(rootDir);
|
||||
await execCommand2('yarn run tsc');
|
||||
await execCommand('yarn run tsc');
|
||||
|
||||
chdir(workDir);
|
||||
await execCommand2('yarn run dist');
|
||||
await execCommand('yarn run dist');
|
||||
|
||||
const newVersion = (await execCommand2('npm version patch')).trim();
|
||||
const newVersion = (await execCommand('npm version patch')).trim();
|
||||
|
||||
console.info(`New version: ${newVersion}`);
|
||||
const tagName = `plugin-repo-cli-${newVersion}`;
|
||||
console.info(`Tag name: ${tagName}`);
|
||||
|
||||
await execCommand2('npm publish');
|
||||
await execCommand('npm publish');
|
||||
|
||||
console.info(releaseFinalGitCommands('Plugin Repo CLI', newVersion, tagName));
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { execCommand2, rootDir, gitPullTry, completeReleaseWithChangelog } from './tool-utils';
|
||||
import { execCommand } from '@joplin/utils';
|
||||
import { rootDir, gitPullTry, completeReleaseWithChangelog } from './tool-utils';
|
||||
|
||||
const serverDir = `${rootDir}/packages/server`;
|
||||
|
||||
@@ -12,7 +13,7 @@ async function main() {
|
||||
await gitPullTry();
|
||||
|
||||
process.chdir(serverDir);
|
||||
const version = (await execCommand2('npm version patch')).trim();
|
||||
const version = (await execCommand('npm version patch')).trim();
|
||||
const versionSuffix = ''; // isPreRelease ? '-beta' : '';
|
||||
const tagName = `server-${version}${versionSuffix}`;
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ yarn install
|
||||
# to change after installation.
|
||||
git reset --hard
|
||||
|
||||
yarn run updateMarkdownDoc
|
||||
JOPLIN_GITHUB_OAUTH_TOKEN=$JOPLIN_GITHUB_OAUTH_TOKEN yarn run updateMarkdownDoc
|
||||
yarn run updateNews $DISCOURSE_API_KEY $DISCOURSE_USERNAME
|
||||
|
||||
# We commit and push the change. It will be a noop if nothing was actually
|
||||
|
||||
@@ -139,6 +139,7 @@ async function main() {
|
||||
await updatePackageVersion(`${rootDir}/packages/renderer/package.json`, majorMinorVersion, options);
|
||||
await updatePackageVersion(`${rootDir}/packages/server/package.json`, majorMinorVersion, options);
|
||||
await updatePackageVersion(`${rootDir}/packages/tools/package.json`, majorMinorVersion, options);
|
||||
await updatePackageVersion(`${rootDir}/packages/utils/package.json`, majorMinorVersion, options);
|
||||
|
||||
if (options.updateVersion) {
|
||||
await updateGradleVersion(`${rootDir}/packages/app-mobile/android/app/build.gradle`, majorMinorVersion);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import yargs = require('yargs');
|
||||
import { chdir } from 'process';
|
||||
import { execCommand2, rootDir } from './tool-utils';
|
||||
import { rootDir } from './tool-utils';
|
||||
import { execCommand } from '@joplin/utils';
|
||||
|
||||
const main = async () => {
|
||||
const argv = await yargs.argv;
|
||||
@@ -10,7 +11,7 @@ const main = async () => {
|
||||
chdir(rootDir);
|
||||
|
||||
try {
|
||||
await execCommand2(['yarn', 'run', 'cspell'].concat(filePaths), { showStderr: false, showStdout: false });
|
||||
await execCommand(['yarn', 'run', 'cspell'].concat(filePaths), { showStderr: false, showStdout: false });
|
||||
} catch (error) {
|
||||
if (!error.stdout.trim()) return;
|
||||
|
||||
|
||||
@@ -64,11 +64,6 @@
|
||||
"title": "Serei Network",
|
||||
"imageName": "SeireiNetwork.png"
|
||||
},
|
||||
{
|
||||
"url": "https://usrigging.com/",
|
||||
"title": "U.S. Ringing Supply",
|
||||
"imageName": "RingingSupply.svg"
|
||||
},
|
||||
{
|
||||
"url": "https://www.hosting.de/nextcloud/?mtm_campaign=managed-nextcloud&mtm_kwd=joplinapp&mtm_source=joplinapp-github&mtm_medium=banner",
|
||||
"urlWebsite": "https://www.hosting.de/nextcloud/?mtm_campaign=managed-nextcloud&mtm_kwd=joplinapp&mtm_source=joplinapp-webseite&mtm_medium=banner",
|
||||
@@ -86,5 +81,11 @@
|
||||
"imageName": "Grundstueckspreise.png"
|
||||
}
|
||||
],
|
||||
"orgsOld": []
|
||||
"orgsOld": [
|
||||
{
|
||||
"url": "https://usrigging.com/",
|
||||
"title": "U.S. Ringing Supply",
|
||||
"imageName": "RingingSupply.svg"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { execCommand2 } from './tool-utils';
|
||||
import { execCommand } from '@joplin/utils';
|
||||
|
||||
async function main() {
|
||||
const argv = require('yargs').argv;
|
||||
@@ -6,9 +6,9 @@ async function main() {
|
||||
|
||||
const version = argv._[0];
|
||||
|
||||
await execCommand2(`docker pull "joplin/server:${version}"`);
|
||||
await execCommand2(`docker tag "joplin/server:${version}" "joplin/server:latest"`);
|
||||
await execCommand2('docker push joplin/server:latest');
|
||||
await execCommand(`docker pull "joplin/server:${version}"`);
|
||||
await execCommand(`docker tag "joplin/server:${version}" "joplin/server:latest"`);
|
||||
await execCommand('docker push joplin/server:latest');
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import * as fs from 'fs-extra';
|
||||
import { readCredentialFile } from '@joplin/lib/utils/credentialFiles';
|
||||
import { pathExists, readFile, writeFile, unlink, stat, createWriteStream } from 'fs-extra';
|
||||
import { hasCredentialFile, readCredentialFile } from '@joplin/lib/utils/credentialFiles';
|
||||
import { execCommand as execCommand2, commandToString } from '@joplin/utils';
|
||||
|
||||
const fetch = require('node-fetch');
|
||||
const execa = require('execa');
|
||||
const { splitCommandString } = require('@joplin/lib/string-utils');
|
||||
const moment = require('moment');
|
||||
|
||||
export interface GitHubReleaseAsset {
|
||||
@@ -20,27 +20,10 @@ export interface GitHubRelease {
|
||||
draft: boolean;
|
||||
}
|
||||
|
||||
function quotePath(path: string) {
|
||||
if (!path) return '';
|
||||
if (path.indexOf('"') < 0 && path.indexOf(' ') < 0) return path;
|
||||
path = path.replace(/"/, '\\"');
|
||||
return `"${path}"`;
|
||||
}
|
||||
|
||||
function commandToString(commandName: string, args: string[] = []) {
|
||||
const output = [quotePath(commandName)];
|
||||
|
||||
for (const arg of args) {
|
||||
output.push(quotePath(arg));
|
||||
}
|
||||
|
||||
return output.join(' ');
|
||||
}
|
||||
|
||||
async function insertChangelog(tag: string, changelogPath: string, changelog: string, isPrerelease: boolean, repoTagUrl: string = '') {
|
||||
repoTagUrl = repoTagUrl || 'https://github.com/laurent22/joplin/releases/tag';
|
||||
|
||||
const currentText = await fs.readFile(changelogPath, 'UTF-8');
|
||||
const currentText = await readFile(changelogPath, 'UTF-8');
|
||||
const lines = currentText.split('\n');
|
||||
|
||||
const beforeLines = [];
|
||||
@@ -97,7 +80,7 @@ export async function completeReleaseWithChangelog(changelogPath: string, newVer
|
||||
|
||||
const newChangelog = await insertChangelog(newTag, changelogPath, changelog, isPreRelease, repoTagUrl);
|
||||
|
||||
await fs.writeFile(changelogPath, newChangelog);
|
||||
await writeFile(changelogPath, newChangelog);
|
||||
|
||||
console.info('');
|
||||
console.info('Verify that the changelog is correct:');
|
||||
@@ -112,8 +95,8 @@ export async function completeReleaseWithChangelog(changelogPath: string, newVer
|
||||
async function loadGitHubUsernameCache() {
|
||||
const path = `${__dirname}/github_username_cache.json`;
|
||||
|
||||
if (await fs.pathExists(path)) {
|
||||
const jsonString = await fs.readFile(path, 'utf8');
|
||||
if (await pathExists(path)) {
|
||||
const jsonString = await readFile(path, 'utf8');
|
||||
return JSON.parse(jsonString);
|
||||
}
|
||||
|
||||
@@ -122,7 +105,7 @@ async function loadGitHubUsernameCache() {
|
||||
|
||||
async function saveGitHubUsernameCache(cache: any) {
|
||||
const path = `${__dirname}/github_username_cache.json`;
|
||||
await fs.writeFile(path, JSON.stringify(cache));
|
||||
await writeFile(path, JSON.stringify(cache));
|
||||
}
|
||||
|
||||
// Returns the project root dir
|
||||
@@ -163,52 +146,6 @@ export function execCommandVerbose(commandName: string, args: string[] = []) {
|
||||
return promise;
|
||||
}
|
||||
|
||||
interface ExecCommandOptions {
|
||||
showInput?: boolean;
|
||||
showStdout?: boolean;
|
||||
showStderr?: boolean;
|
||||
quiet?: boolean;
|
||||
}
|
||||
|
||||
// There's lot of execCommandXXX functions, but eventually all scripts should
|
||||
// use the one below, which supports:
|
||||
//
|
||||
// - Printing the command being executed
|
||||
// - Printing the output in real time (piping to stdout)
|
||||
// - Returning the command result as string
|
||||
export async function execCommand2(command: string | string[], options: ExecCommandOptions = null): Promise<string> {
|
||||
options = {
|
||||
showInput: true,
|
||||
showStdout: true,
|
||||
showStderr: true,
|
||||
quiet: false,
|
||||
...options,
|
||||
};
|
||||
|
||||
if (options.quiet) {
|
||||
options.showInput = false;
|
||||
options.showStdout = false;
|
||||
options.showStderr = false;
|
||||
}
|
||||
|
||||
if (options.showInput) {
|
||||
if (typeof command === 'string') {
|
||||
console.info(`> ${command}`);
|
||||
} else {
|
||||
console.info(`> ${commandToString(command[0], command.slice(1))}`);
|
||||
}
|
||||
}
|
||||
|
||||
const args: string[] = typeof command === 'string' ? splitCommandString(command) : command as string[];
|
||||
const executableName = args[0];
|
||||
args.splice(0, 1);
|
||||
const promise = execa(executableName, args);
|
||||
if (options.showStdout) promise.stdout.pipe(process.stdout);
|
||||
if (options.showStderr) promise.stdout.pipe(process.stderr);
|
||||
const result = await promise;
|
||||
return result.stdout.trim();
|
||||
}
|
||||
|
||||
export function execCommandWithPipes(executable: string, args: string[]) {
|
||||
const spawn = require('child_process').spawn;
|
||||
|
||||
@@ -236,22 +173,21 @@ export function toSystemSlashes(path: string) {
|
||||
}
|
||||
|
||||
export async function setPackagePrivateField(filePath: string, value: any) {
|
||||
const text = await fs.readFile(filePath, 'utf8');
|
||||
const text = await readFile(filePath, 'utf8');
|
||||
const obj = JSON.parse(text);
|
||||
if (!value) {
|
||||
delete obj.private;
|
||||
} else {
|
||||
obj.private = true;
|
||||
}
|
||||
await fs.writeFile(filePath, JSON.stringify(obj, null, 2), 'utf8');
|
||||
await writeFile(filePath, JSON.stringify(obj, null, 2), 'utf8');
|
||||
}
|
||||
|
||||
export async function downloadFile(url: string, targetPath: string) {
|
||||
const https = require('https');
|
||||
const fs = require('fs');
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const file = fs.createWriteStream(targetPath);
|
||||
const file = createWriteStream(targetPath);
|
||||
https.get(url, (response: any) => {
|
||||
if (response.statusCode !== 200) reject(new Error(`HTTP error ${response.statusCode}`));
|
||||
response.pipe(file);
|
||||
@@ -285,10 +221,8 @@ export function fileSha256(filePath: string) {
|
||||
}
|
||||
|
||||
export async function unlinkForce(filePath: string) {
|
||||
const fs = require('fs-extra');
|
||||
|
||||
try {
|
||||
await fs.unlink(filePath);
|
||||
await unlink(filePath);
|
||||
} catch (error) {
|
||||
if (error.code === 'ENOENT') return;
|
||||
throw error;
|
||||
@@ -296,10 +230,8 @@ export async function unlinkForce(filePath: string) {
|
||||
}
|
||||
|
||||
export function fileExists(filePath: string) {
|
||||
const fs = require('fs-extra');
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.stat(filePath, (error: any) => {
|
||||
stat(filePath, (error: any) => {
|
||||
if (!error) {
|
||||
resolve(true);
|
||||
} else if (error.code === 'ENOENT') {
|
||||
@@ -389,7 +321,10 @@ export function patreonOauthToken() {
|
||||
}
|
||||
|
||||
export function githubOauthToken() {
|
||||
return readCredentialFile('github_oauth_token.txt');
|
||||
const filename = 'github_oauth_token.txt';
|
||||
if (hasCredentialFile(filename)) return readCredentialFile(filename);
|
||||
if (process.env.JOPLIN_GITHUB_OAUTH_TOKEN) return process.env.JOPLIN_GITHUB_OAUTH_TOKEN;
|
||||
throw new Error(`Cannot get Oauth token. Neither ${filename} nor the env variable JOPLIN_GITHUB_OAUTH_TOKEN are present`);
|
||||
}
|
||||
|
||||
// Note that the GitHub API releases/latest is broken on the joplin-android repo
|
||||
@@ -485,12 +420,11 @@ export function isMac() {
|
||||
}
|
||||
|
||||
export async function insertContentIntoFile(filePath: string, markerOpen: string, markerClose: string, contentToInsert: string) {
|
||||
const fs = require('fs-extra');
|
||||
let content = await fs.readFile(filePath, 'utf-8');
|
||||
let content = await readFile(filePath, 'utf-8');
|
||||
// [^]* matches any character including new lines
|
||||
const regex = new RegExp(`${markerOpen}[^]*?${markerClose}`);
|
||||
content = content.replace(regex, markerOpen + contentToInsert + markerClose);
|
||||
await fs.writeFile(filePath, content);
|
||||
await writeFile(filePath, content);
|
||||
}
|
||||
|
||||
export function dirname(path: string) {
|
||||
|
||||
@@ -1,43 +1,9 @@
|
||||
import { readFile } from 'fs-extra';
|
||||
import { insertContentIntoFile, rootDir } from './tool-utils';
|
||||
import markdownUtils, { MarkdownTableHeader, MarkdownTableJustify, MarkdownTableRow } from '@joplin/lib/markdownUtils';
|
||||
import { GithubSponsor, GithubUser, OrgSponsor, Sponsors } from './website/utils/types';
|
||||
import fetch from 'node-fetch';
|
||||
import { GithubSponsor, loadSponsors, OrgSponsor } from './utils/loadSponsors';
|
||||
const { escapeHtml } = require('@joplin/lib/string-utils');
|
||||
|
||||
const readmePath = `${rootDir}/README.md`;
|
||||
const sponsorsPath = `${rootDir}/packages/tools/sponsors.json`;
|
||||
|
||||
const sleep = (ms: number) => {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
};
|
||||
|
||||
const fetchWithRetry = async (url: string, opts: any = null) => {
|
||||
if (!opts) opts = {};
|
||||
let retry = opts && opts.retry || 3;
|
||||
|
||||
while (retry > 0) {
|
||||
try {
|
||||
return fetch(url, opts);
|
||||
} catch (e) {
|
||||
if (opts && opts.callback) {
|
||||
opts.callback(retry);
|
||||
}
|
||||
retry = retry - 1;
|
||||
if (retry === 0) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (opts && opts.pause) {
|
||||
if (opts && !opts.silent) console.log('pausing..');
|
||||
await sleep(opts.pause);
|
||||
if (opts && !opts.silent) console.log('done pausing...');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
async function createGitHubSponsorTable(sponsors: GithubSponsor[]): Promise<string> {
|
||||
sponsors = sponsors.slice();
|
||||
@@ -70,9 +36,7 @@ async function createGitHubSponsorTable(sponsors: GithubSponsor[]): Promise<stri
|
||||
sponsorIndex++;
|
||||
if (!sponsor) break;
|
||||
|
||||
const userResponse = await fetchWithRetry(`https://api.github.com/users/${sponsor.name}`);
|
||||
const user = await userResponse.json() as GithubUser;
|
||||
row[`col${colIndex}`] = `<img width="50" src="https://avatars2.githubusercontent.com/u/${user.id}?s=96&v=4"/></br>[${sponsor.name}](https://github.com/${sponsor.name})`;
|
||||
row[`col${colIndex}`] = `<img width="50" src="https://avatars2.githubusercontent.com/u/${sponsor.id}?s=96&v=4"/></br>[${sponsor.name}](https://github.com/${sponsor.name})`;
|
||||
}
|
||||
|
||||
if (Object.keys(row)) rows.push(row);
|
||||
@@ -94,7 +58,7 @@ async function createOrgSponsorTable(sponsors: OrgSponsor[]): Promise<string> {
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const sponsors: Sponsors = JSON.parse(await readFile(sponsorsPath, 'utf8'));
|
||||
const sponsors = await loadSponsors();
|
||||
|
||||
await insertContentIntoFile(
|
||||
readmePath,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { execCommand } from '@joplin/utils';
|
||||
import { chdir } from 'process';
|
||||
import { execCommand2, rootDir, gitRepoCleanTry } from './tool-utils';
|
||||
import { rootDir, gitRepoCleanTry } from './tool-utils';
|
||||
import updateDownloadPage from './website/updateDownloadPage';
|
||||
|
||||
async function main() {
|
||||
@@ -7,23 +8,23 @@ async function main() {
|
||||
|
||||
if (doGitOperations) {
|
||||
await gitRepoCleanTry();
|
||||
await execCommand2(['git', 'pull', '--rebase']);
|
||||
await execCommand(['git', 'pull', '--rebase']);
|
||||
}
|
||||
|
||||
await execCommand2(['node', `${rootDir}/packages/tools/update-readme-download.js`]);
|
||||
await execCommand2(['node', `${rootDir}/packages/tools/build-release-stats.js`, '--types=changelog']);
|
||||
await execCommand2(['node', `${rootDir}/packages/tools/build-release-stats.js`, '--types=stats', '--update-interval=30']);
|
||||
await execCommand2(['node', `${rootDir}/packages/tools/update-readme-sponsors.js`]);
|
||||
await execCommand2(['node', `${rootDir}/packages/tools/build-welcome.js`]);
|
||||
await execCommand(['node', `${rootDir}/packages/tools/update-readme-download.js`]);
|
||||
await execCommand(['node', `${rootDir}/packages/tools/build-release-stats.js`, '--types=changelog']);
|
||||
await execCommand(['node', `${rootDir}/packages/tools/build-release-stats.js`, '--types=stats', '--update-interval=30']);
|
||||
await execCommand(['node', `${rootDir}/packages/tools/update-readme-sponsors.js`]);
|
||||
await execCommand(['node', `${rootDir}/packages/tools/build-welcome.js`]);
|
||||
chdir(rootDir);
|
||||
await execCommand2(['yarn', 'run', 'buildApiDoc']);
|
||||
await execCommand(['yarn', 'run', 'buildApiDoc']);
|
||||
await updateDownloadPage();
|
||||
|
||||
if (doGitOperations) {
|
||||
await execCommand2(['git', 'add', '-A']);
|
||||
await execCommand2(['git', 'commit', '-m', 'Update Markdown doc']);
|
||||
await execCommand2(['git', 'pull', '--rebase']);
|
||||
await execCommand2(['git', 'push']);
|
||||
await execCommand(['git', 'add', '-A']);
|
||||
await execCommand(['git', 'commit', '-m', 'Update Markdown doc']);
|
||||
await execCommand(['git', 'pull', '--rebase']);
|
||||
await execCommand(['git', 'push']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
48
packages/tools/utils/loadSponsors.ts
Normal file
48
packages/tools/utils/loadSponsors.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { readFile } from 'fs-extra';
|
||||
import { getRootDir } from '@joplin/utils';
|
||||
import { fetchWithRetry } from '@joplin/utils/net';
|
||||
import { githubOauthToken } from '../tool-utils';
|
||||
|
||||
export interface GithubSponsor {
|
||||
name: string;
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface Sponsors {
|
||||
github: GithubSponsor[];
|
||||
orgs: OrgSponsor[];
|
||||
}
|
||||
|
||||
export interface OrgSponsor {
|
||||
url: string;
|
||||
urlWebsite?: string;
|
||||
title: string;
|
||||
imageName: string;
|
||||
}
|
||||
|
||||
export const loadSponsors = async (): Promise<Sponsors> => {
|
||||
const sponsorsPath = `${await getRootDir()}/packages/tools/sponsors.json`;
|
||||
const output: Sponsors = JSON.parse(await readFile(sponsorsPath, 'utf8'));
|
||||
|
||||
output.orgs = output.orgs.map(o => {
|
||||
if (o.urlWebsite) o.url = o.urlWebsite;
|
||||
return o;
|
||||
});
|
||||
|
||||
const oauthToken = await githubOauthToken();
|
||||
|
||||
for (const ghSponsor of output.github) {
|
||||
const userResponse = await fetchWithRetry(`https://api.github.com/users/${ghSponsor.name}`, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `token ${oauthToken}`,
|
||||
},
|
||||
});
|
||||
|
||||
if (!userResponse.ok) throw new Error(await userResponse.text());
|
||||
const user = await userResponse.json();
|
||||
ghSponsor.id = user.id;
|
||||
}
|
||||
|
||||
return output;
|
||||
};
|
||||
@@ -2,7 +2,7 @@ import { readFileSync, readFile, mkdirpSync, writeFileSync, remove, copy, pathEx
|
||||
import { rootDir } from '../tool-utils';
|
||||
import { pressCarouselItems } from './utils/pressCarousel';
|
||||
import { getMarkdownIt, loadMustachePartials, markdownToPageHtml, renderMustache } from './utils/render';
|
||||
import { AssetUrls, Env, Partials, PlanPageParams, Sponsors, TemplateParams } from './utils/types';
|
||||
import { AssetUrls, Env, Partials, PlanPageParams, TemplateParams } from './utils/types';
|
||||
import { createFeatureTableMd, getPlans, loadStripeConfig } from '@joplin/lib/utils/joplinCloud';
|
||||
import { stripOffFrontMatter } from './utils/frontMatter';
|
||||
import { dirname, basename } from 'path';
|
||||
@@ -13,6 +13,7 @@ import { getNewsDateString } from './utils/news';
|
||||
import { parsePoFile, parseTranslations, Translations } from '../utils/translation';
|
||||
import { countryCodeOnly, setLocale } from '@joplin/lib/locale';
|
||||
import applyTranslations from './utils/applyTranslations';
|
||||
import { loadSponsors } from '../utils/loadSponsors';
|
||||
|
||||
interface BuildConfig {
|
||||
env: Env;
|
||||
@@ -175,16 +176,6 @@ function makeHomePageMd() {
|
||||
return md;
|
||||
}
|
||||
|
||||
async function loadSponsors(): Promise<Sponsors> {
|
||||
const sponsorsPath = `${rootDir}/packages/tools/sponsors.json`;
|
||||
const output: Sponsors = JSON.parse(await readFile(sponsorsPath, 'utf8'));
|
||||
output.orgs = output.orgs.map(o => {
|
||||
if (o.urlWebsite) o.url = o.urlWebsite;
|
||||
return o;
|
||||
});
|
||||
return output;
|
||||
}
|
||||
|
||||
const processNewsMarkdown = (md: string, mdFilePath: string): string => {
|
||||
const info = stripOffFrontMatter(md);
|
||||
md = info.doc.trim();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Plan, StripePublicConfig } from '@joplin/lib/utils/joplinCloud';
|
||||
import { Sponsors } from '../../utils/loadSponsors';
|
||||
import { OpenGraphTags } from './openGraph';
|
||||
|
||||
export enum Env {
|
||||
@@ -6,26 +7,10 @@ export enum Env {
|
||||
Prod = 'prod',
|
||||
}
|
||||
|
||||
export interface GithubSponsor {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface GithubUser {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface OrgSponsor {
|
||||
url: string;
|
||||
urlWebsite?: string;
|
||||
title: string;
|
||||
imageName: string;
|
||||
}
|
||||
|
||||
export interface Sponsors {
|
||||
github: GithubSponsor[];
|
||||
orgs: OrgSponsor[];
|
||||
}
|
||||
|
||||
interface PressCarouselItem {
|
||||
active: string;
|
||||
body: string;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"browserify": "14.5.0",
|
||||
"rollup": "0.50.1",
|
||||
"standard": "17.0.0",
|
||||
"turndown": "7.1.1",
|
||||
"turndown": "7.1.2",
|
||||
"turndown-attendant": "0.0.3"
|
||||
},
|
||||
"files": [
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"dependencies": {
|
||||
"css": "3.0.0",
|
||||
"html-entities": "1.4.0",
|
||||
"jsdom": "21.0.0"
|
||||
"jsdom": "21.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"browserify": "14.5.0",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user