1
0
mirror of https://github.com/laurent22/joplin.git synced 2026-01-14 00:29:38 +02:00

Compare commits

..

4 Commits

Author SHA1 Message Date
Laurent Cozic
7e387c47f2 Update BaseApplication.ts 2023-03-14 11:45:30 +00:00
palerdot
7dae90698d refactor: fix comments 2023-03-14 15:27:14 +05:30
palerdot
0093dfc361 Merge remote-tracking branch 'origin/dev' into safe-mode-command-line-flag 2023-03-14 15:20:38 +05:30
palerdot
09e143f218 feat(desktop,cli): --safe-mode command line option 2023-03-14 15:18:52 +05:30
123 changed files with 1826 additions and 3348 deletions

View File

@@ -66,7 +66,6 @@ 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/
@@ -405,7 +404,6 @@ 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
@@ -864,7 +862,6 @@ 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

View File

@@ -180,6 +180,9 @@ 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..."

View File

@@ -6,7 +6,6 @@ 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 }}
@@ -17,7 +16,6 @@ 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

View File

@@ -7,7 +7,6 @@ on:
jobs:
CLAAssistant:
if: github.repository == 'laurent22/joplin'
runs-on: ubuntu-latest
steps:
- name: "CLA Assistant"

View File

@@ -6,7 +6,6 @@ permissions:
issues: write
jobs:
ProcessStaleIssues:
if: github.repository == 'laurent22/joplin'
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v4

View File

@@ -2,7 +2,6 @@ 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 }}
@@ -15,7 +14,7 @@ jobs:
Main:
needs: pre_job
# We always process server or desktop release tags, because they also publish the release
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'))
if: 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:
@@ -93,7 +92,6 @@ 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 }}
@@ -131,7 +129,7 @@ jobs:
ServerDockerImage:
needs: pre_job
if: github.repository == 'laurent22/joplin' && needs.pre_job.outputs.should_skip != 'true'
if: needs.pre_job.outputs.should_skip != 'true'
runs-on: ${{ matrix.os }}
strategy:
matrix:

2
.gitignore vendored
View File

@@ -392,7 +392,6 @@ 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
@@ -851,7 +850,6 @@ 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

View File

@@ -14,8 +14,7 @@
"@joplin/turndown-plugin-gfm",
"@joplin/tools",
"@joplin/react-native-saf-x",
"@joplin/react-native-alarm-notification",
"@joplin/utils"
"@joplin/react-native-alarm-notification"
]
}
]

View File

@@ -1,30 +0,0 @@
diff --git a/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java b/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java
index a8abd71833879201e3438b2fa51d712a311c4551..ffe9c2c6dfa5c703ba76b65d94d5dd6784102c19 100644
--- a/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java
+++ b/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java
@@ -591,7 +591,7 @@ public class RNFetchBlobReq extends BroadcastReceiver implements Runnable {
// ignored.printStackTrace();
}
- RNFetchBlobFileResp rnFetchBlobFileResp = (RNFetchBlobFileResp) responseBody;
+ RNFetchBlobFileResp rnFetchBlobFileResp = new RNFetchBlobFileResp(responseBody);
if(rnFetchBlobFileResp != null && !rnFetchBlobFileResp.isDownloadComplete()){
callback.invoke("Download interrupted.", null);
diff --git a/android/src/main/java/com/RNFetchBlob/Response/RNFetchBlobFileResp.java b/android/src/main/java/com/RNFetchBlob/Response/RNFetchBlobFileResp.java
index 2470eef612308c15a89dfea5a1f16937469be29f..965f8becc195965907699182c764ec9e51811450 100644
--- a/android/src/main/java/com/RNFetchBlob/Response/RNFetchBlobFileResp.java
+++ b/android/src/main/java/com/RNFetchBlob/Response/RNFetchBlobFileResp.java
@@ -35,6 +35,12 @@ public class RNFetchBlobFileResp extends ResponseBody {
FileOutputStream ofStream;
boolean isEndMarkerReceived;
+ // ref: https://github.com/joltup/rn-fetch-blob/issues/490#issuecomment-990899440
+ public RNFetchBlobFileResp(ResponseBody body) {
+ super();
+ this.originalBody = body;
+ }
+
public RNFetchBlobFileResp(ReactApplicationContext ctx, String taskId, ResponseBody body, String path, boolean overwrite) throws IOException {
super();
this.rctContext = ctx;

View File

@@ -30,7 +30,6 @@ 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

View File

@@ -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://www.hosting.de/nextcloud/?mtm_campaign=managed-nextcloud&amp;mtm_kwd=joplinapp&amp;mtm_source=joplinapp-webseite&amp;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://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&amp;mtm_kwd=joplinapp&amp;mtm_source=joplinapp-github&amp;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,7 +126,6 @@ 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)

View File

@@ -1,52 +1,26 @@
const gulp = require('gulp');
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 utils = require('./packages/tools/gulp/utils');
const tasks = {
updateIgnoredTypeScriptBuild: require('./packages/tools/gulp/tasks/updateIgnoredTypeScriptBuild'),
buildCommandIndex: require('./packages/tools/gulp/tasks/buildCommandIndex'),
completePublishAll: {
fn: async () => {
await execCommand('git', ['add', '-A']);
await execCommand('git', ['commit', '-m', 'Releasing sub-packages']);
await utils.execCommandVerbose('git', ['add', '-A']);
await utils.execCommandVerbose('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 execCommand('lerna', ['publish', 'from-package', '-y', '--no-verify-access']);
await utils.execCommandVerbose('lerna', ['publish', 'from-package', '-y', '--no-verify-access']);
await execCommand('yarn', ['install']);
await execCommand('git', ['add', '-A']);
await execCommand('git', ['commit', '-m', 'Lock file']);
await utils.execCommandVerbose('yarn', ['install']);
await utils.execCommandVerbose('git', ['add', '-A']);
await utils.execCommandVerbose('git', ['commit', '-m', 'Lock file']);
await execCommand('git', ['push']);
await utils.execCommandVerbose('git', ['push']);
},
},
build: {
@@ -59,14 +33,12 @@ const tasks = {
// faster, especially when having to rebuild after adding a
// dependency.
if (process.env.BUILD_SEQUENCIAL === '1') {
await execCommand('yarn', ['run', 'buildSequential']);
await utils.execCommandVerbose('yarn', ['run', 'buildSequential']);
} else {
await execCommand('yarn', ['run', 'buildParallel']);
await utils.execCommandVerbose('yarn', ['run', 'buildParallel']);
}
},
},
};
for (const taskName in tasks) {
gulp.task(taskName, tasks[taskName].fn);
}
utils.registerGulpTasks(gulp, tasks);

View File

@@ -329,7 +329,6 @@
"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,

View File

@@ -15,7 +15,7 @@
"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",
"buildApiDoc": "yarn workspace joplin start apidoc ../../readme/api/references/rest_api.md",
"buildCommandIndex": "node packages/tools/gulp/tasks/buildCommandIndexRun.js",
"buildCommandIndex": "gulp buildCommandIndex",
"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": "node packages/tools/gulp/tasks/updateIgnoredTypeScriptBuildRun.js",
"updateIgnored": "gulp updateIgnoredTypeScriptBuild",
"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,7 +64,6 @@
}
},
"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",
@@ -75,13 +74,12 @@
"eslint-plugin-jest": "27.2.1",
"eslint-plugin-promise": "6.1.1",
"eslint-plugin-react": "7.32.0",
"execa": "5.1.1",
"fs-extra": "11.1.1",
"fs-extra": "11.1.0",
"glob": "8.1.0",
"gulp": "4.0.2",
"husky": "3.1.0",
"lerna": "3.22.1",
"lint-staged": "13.2.0",
"lint-staged": "13.1.2",
"madge": "6.0.0",
"npm-package-json-lint": "6.4.0",
"typedoc": "0.17.8",
@@ -91,11 +89,10 @@
"@types/fs-extra": "9.0.13",
"http-server": "14.1.1",
"node-gyp": "9.3.1",
"nodemon": "2.0.22"
"nodemon": "2.0.21"
},
"packageManager": "yarn@3.3.1",
"resolutions": {
"react-native-camera@4.2.1": "patch:react-native-camera@npm%3A4.2.1#./.yarn/patches/react-native-camera-npm-4.2.1-24b2600a7e.patch",
"rn-fetch-blob@0.12.0": "patch:rn-fetch-blob@npm%3A0.12.0#./.yarn/patches/rn-fetch-blob-npm-0.12.0-cf02e3c544.patch"
"react-native-camera@4.2.1": "patch:react-native-camera@npm%3A4.2.1#./.yarn/patches/react-native-camera-npm-4.2.1-24b2600a7e.patch"
}
}

View File

@@ -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/utils');
const { splitCommandString } = require('@joplin/lib/string-utils.js');
const { reg } = require('@joplin/lib/registry.js');
const { _ } = require('@joplin/lib/locale');
const shim = require('@joplin/lib/shim').default;

View File

@@ -9,8 +9,7 @@ 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 } = require('@joplin/utils');
const { splitCommandBatch } = require('@joplin/lib/string-utils');
const { splitCommandString, splitCommandBatch } = require('@joplin/lib/string-utils');
const { _ } = require('@joplin/lib/locale');
const fs = require('fs-extra');
const { cliUtils } = require('./cli-utils.js');

View File

@@ -1,6 +1,6 @@
const fs = require('fs-extra');
const BaseCommand = require('./base-command').default;
const { splitCommandString } = require('@joplin/utils');
const { splitCommandString } = require('@joplin/lib/string-utils.js');
const uuid = require('@joplin/lib/uuid').default;
const { app } = require('./app.js');
const { _ } = require('@joplin/lib/locale');

View File

@@ -30,24 +30,22 @@
2019,
2020,
2021,
2022,
2023
2022
],
"owner": "Laurent Cozic"
},
"version": "2.11.0",
"version": "2.10.3",
"bin": "./main.js",
"engines": {
"node": ">=10.0.0"
},
"dependencies": {
"@joplin/lib": "~2.11",
"@joplin/renderer": "~2.11",
"@joplin/utils": "~2.11",
"@joplin/lib": "~2.10",
"@joplin/renderer": "~2.10",
"aws-sdk": "2.1290.0",
"chalk": "4.1.2",
"compare-version": "0.1.2",
"fs-extra": "11.1.1",
"fs-extra": "11.1.0",
"html-entities": "1.4.0",
"image-type": "3.1.0",
"keytar": "7.9.0",
@@ -59,7 +57,7 @@
"server-destroy": "1.0.1",
"sharp": "0.31.3",
"sprintf-js": "1.1.2",
"sqlite3": "5.1.6",
"sqlite3": "5.1.4",
"string-padding": "1.0.2",
"strip-ansi": "6.0.1",
"tcp-port-used": "1.0.2",
@@ -70,7 +68,7 @@
"yargs-parser": "21.1.1"
},
"devDependencies": {
"@joplin/tools": "~2.11",
"@joplin/tools": "~2.10",
"@types/fs-extra": "9.0.13",
"@types/jest": "29.2.6",
"@types/node": "18.11.18",

View File

@@ -47,11 +47,9 @@ 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', '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);
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);
}));
});

View File

@@ -19,7 +19,7 @@
import * as fs from 'fs-extra';
import { homedir } from 'os';
import { execCommand } from '@joplin/utils';
import { execCommand2 } from '@joplin/tools/tool-utils';
import { chdir } from 'process';
const minUserNum = 1;
@@ -66,7 +66,7 @@ const processUser = async (userNum: number) => {
await chdir(cliDir);
await execCommand(['yarn', 'run', 'start-no-build', '--', '--profile', profileDir, 'batch', commandFile]);
await execCommand2(['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 execCommand(['yarn', 'run', 'build']);
await execCommand2(['yarn', 'run', 'build']);
const focusUserNum = 0;

View File

@@ -1,7 +1,7 @@
{
"manifest_version": 2,
"name": "Joplin Web Clipper [DEV]",
"version": "2.11.2",
"version": "2.10.0",
"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'",

View File

@@ -126,4 +126,4 @@
"react-app"
]
}
}
}

View File

@@ -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), pluginService.appVersion);
const pluginIds = await repoApi().canBeUpdatedPlugins(pluginItems.map(p => p.manifest));
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, pluginService.appVersion]);
}, [manifestsLoaded, pluginItems]);
const onDelete = useCallback(async (event: ItemEvent) => {
const item = event.item;

View File

@@ -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, { PluginSettings } from '@joplin/lib/services/plugins/PluginService';
import PluginService from '@joplin/lib/services/plugins/PluginService';
const packageInfo = require('../packageInfo.js');
const { clipboard } = require('electron');
const Menu = bridge().Menu;
@@ -128,7 +128,6 @@ interface Props {
customCss: string;
locale: string;
profileConfig: ProfileConfig;
pluginSettings: PluginSettings;
}
const commandNames: string[] = menuCommandNames();
@@ -488,7 +487,8 @@ function useMenu(props: Props) {
}
function _showAbout() {
const v = versionInfo(packageInfo, PluginService.instance().enabledPlugins(props.pluginSettings));
const v = versionInfo(packageInfo, PluginService.instance().plugins);
const copyToClipboard = bridge().showMessageBox(v.message, {
icon: `${bridge().electronApp().buildDir()}/icons/128x128.png`,
@@ -931,7 +931,6 @@ 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,
@@ -987,7 +986,6 @@ 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,

View File

@@ -3,7 +3,6 @@ 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';
@@ -24,7 +23,6 @@ export interface MarkupToHtmlOptions {
useCustomPdfViewer?: boolean;
noteId?: string;
vendorDir?: string;
platformName?: string;
}
export default function useMarkupToHtml(deps: HookDependencies) {
@@ -42,7 +40,6 @@ export default function useMarkupToHtml(deps: HookDependencies) {
options = {
replaceResourceInternalToExternalLinks: false,
resourceInfos: {},
platformName: shim.platformName(),
...options,
};

View File

@@ -241,7 +241,6 @@ 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) => {

View File

@@ -12,9 +12,9 @@ const { connect } = require('react-redux');
const styled = require('styled-components').default;
enum BaseBreakpoint {
Sm = 75,
Md = 80,
Lg = 120,
Sm = 160,
Md = 190,
Lg = 40,
Xl = 474,
}
@@ -50,9 +50,7 @@ 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;

View File

@@ -48,15 +48,6 @@ 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;
@@ -747,9 +738,9 @@ const SidebarComponent = (props: Props) => {
tagItemsOrder_.current = result.order;
items.push(
<TagsHolder className="tags" key="tag_items" style={{ display: props.tagHeaderIsExpanded ? 'block' : 'none' }}>
<div className="tags" key="tag_items" style={{ display: props.tagHeaderIsExpanded ? 'block' : 'none' }}>
{tagItems}
</TagsHolder>
</div>
);
}

View File

@@ -56,19 +56,6 @@ 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 = {
@@ -84,13 +71,12 @@ 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);
}
@@ -100,18 +86,6 @@ 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
)

View File

@@ -1,12 +1,11 @@
{
"name": "@joplin/app-desktop",
"version": "2.11.1",
"version": "2.10.10",
"description": "Joplin for Desktop",
"main": "main.js",
"private": true,
"scripts": {
"dist": "yarn run bundleDefaultPlugins && yarn run electronRebuild && npx electron-builder",
"bundleDefaultPlugins": "cd ../tools && node bundleDefaultPlugins.js",
"dist": "yarn run electronRebuild && npx electron-builder",
"build": "gulp build",
"postinstall": "yarn run build",
"electronBuilder": "gulp electronBuilder",
@@ -91,11 +90,7 @@
"CFBundleURLName": "org.joplinapp.x-callback-url"
}
]
},
"binaries": [
"Contents/Resources/build/defaultPlugins/io.github.jackgruber.backup/7zip-bin/mac/arm64/7za",
"Contents/Resources/build/defaultPlugins/io.github.jackgruber.backup/7zip-bin/mac/x64/7za"
]
}
},
"linux": {
"icon": "../../Assets/LinuxIcons",
@@ -112,9 +107,7 @@
},
"homepage": "https://github.com/laurent22/joplin#readme",
"devDependencies": {
"@electron/notarize": "1.2.3",
"@electron/rebuild": "3.2.10",
"@joplin/tools": "~2.11",
"@joplin/tools": "~2.10",
"@testing-library/react-hooks": "8.0.1",
"@types/jest": "29.2.6",
"@types/node": "18.11.18",
@@ -122,7 +115,9 @@
"@types/react-redux": "7.1.25",
"@types/styled-components": "5.1.26",
"electron": "19.1.4",
"electron-builder": "24.1.2",
"electron-builder": "23.6.0",
"electron-notarize": "1.2.2",
"electron-rebuild": "3.2.9",
"glob": "8.1.0",
"gulp": "4.0.2",
"jest": "29.4.3",
@@ -141,9 +136,9 @@
"@electron/remote": "2.0.9",
"@fortawesome/fontawesome-free": "5.15.4",
"@joeattardi/emoji-button": "4.6.4",
"@joplin/lib": "~2.11",
"@joplin/pdf-viewer": "~2.11",
"@joplin/renderer": "~2.11",
"@joplin/lib": "~2.10",
"@joplin/pdf-viewer": "~2.10",
"@joplin/renderer": "~2.10",
"async-mutex": "0.4.0",
"codemirror": "5.65.9",
"color": "3.2.1",
@@ -152,7 +147,7 @@
"debounce": "1.2.1",
"electron-window-state": "5.0.3",
"formatcoords": "1.1.3",
"fs-extra": "11.1.1",
"fs-extra": "11.1.0",
"highlight.js": "11.7.0",
"immer": "7.0.15",
"keytar": "7.9.0",
@@ -168,17 +163,17 @@
"react-datetime": "3.2.0",
"react-dom": "18.2.0",
"react-redux": "8.0.5",
"react-select": "5.7.2",
"react-select": "5.7.0",
"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.6",
"styled-components": "5.3.9",
"sqlite3": "5.1.4",
"styled-components": "5.3.8",
"styled-system": "5.1.5",
"taboverride": "4.0.3",
"tinymce": "5.10.6"
}
}
}

View File

@@ -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) {

View File

@@ -0,0 +1,6 @@
module.exports = {
bracketSpacing: false,
jsxBracketSameLine: true,
singleQuote: true,
trailingComma: 'all',
};

View File

@@ -150,8 +150,8 @@ android {
applicationId "net.cozic.joplin"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 2097687
versionName "2.11.2"
versionCode 2097684
versionName "2.10.8"
// ndk {
// abiFilters "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
// }

View File

@@ -2,7 +2,6 @@
* @jest-environment jsdom
*/
import { EditorSettings } from '../types';
import { initCodeMirror } from './CodeMirror';
import { themeStyle } from '@joplin/lib/theme';
@@ -10,8 +9,6 @@ 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);
@@ -26,14 +23,6 @@ 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.`;

View File

@@ -30,7 +30,6 @@ interface Props {
initialSelection?: Selection;
style: ViewStyle;
contentStyle?: ViewStyle;
toolbarEnabled: boolean;
onChange: ChangeEventHandler;
onSelectionChange: SelectionChangeEventHandler;
@@ -365,19 +364,6 @@ 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 (
@@ -415,7 +401,18 @@ function NoteEditor(props: Props, ref: any) {
searchState={searchState}
/>
{props.toolbarEnabled ? toolbar : null}
<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}
/>
</View>
);
}

View File

@@ -2,12 +2,9 @@ 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;
@@ -16,36 +13,24 @@ interface Props {
}
export default (props: Props) => {
// 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 [initialPromptDone, setInitialPromptDone] = useState(Setting.value('security.biometricsInitialPromptDone'));
const [display, setDisplay] = useState(!!props.sensorInfo.supportedSensors && (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 biometricAuthenticate();
await FingerprintScanner.authenticate({ description: _('Verify your identity') });
setTryBiometricsCheck(false);
setDisplay(false);
} catch (error) {
Alert.alert(error.message);
Alert.alert(_('Could not verify your identify'), error.message);
setTryBiometricsCheck(false);
} finally {
FingerprintScanner.release();
}
setTryBiometricsCheck(false);
logger.info('biometricsCheck: end');
};
void biometricsCheck();
@@ -56,9 +41,6 @@ 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);
@@ -73,8 +55,6 @@ export default (props: Props) => {
type: 'BIOMETRICS_DONE_SET',
value: true,
});
logger.info('complete: end');
};
Alert.alert(
@@ -93,7 +73,7 @@ export default (props: Props) => {
},
]
);
}, [initialPromptDone, display, props.dispatch]);
}, [initialPromptDone, props.sensorInfo.supportedSensors, display, props.dispatch]);
const windowSize = useMemo(() => {
return {
@@ -103,18 +83,12 @@ 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 = () => {

View File

@@ -1,28 +0,0 @@
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();
}
};

View File

@@ -1,7 +1,5 @@
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;
@@ -10,40 +8,11 @@ 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) {
@@ -53,7 +22,7 @@ export default async (): Promise<SensorInfo> => {
}
}
} catch (error) {
logger.warn('Could not check for biometrics sensor:', error);
console.warn('Could not check for biometrics sensor:', error);
Setting.setValue('security.biometricsSupportedSensors', '');
}

View File

@@ -23,7 +23,6 @@ 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 {
@@ -464,7 +463,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) => void updateSettingValue(key, value)} />
<Switch key="control" style={this.styles().switchSettingControl} trackColor={{ false: theme.dividerColor }} value={value} onValueChange={(value: any) => updateSettingValue(key, value)} />
</View>
{descriptionComp}
</View>
@@ -475,39 +474,13 @@ 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 = async (key: string, value: any) => {
const handled = await this.handleSetting(key, value);
if (!handled) shared.updateSettingValue(this, key, value);
const updateSettingValue = (key: string, value: any) => {
return shared.updateSettingValue(this, key, value);
};
const md = Setting.settingMetadata(key);
@@ -544,7 +517,7 @@ class ConfigScreenComponent extends BaseScreenComponent {
fontSize: theme.fontSize,
}}
onValueChange={(itemValue: string) => {
void updateSettingValue(key, itemValue);
updateSettingValue(key, itemValue);
}}
/>
</View>
@@ -580,7 +553,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 => void updateSettingValue(key, value)} />
<Slider key="control" style={{ flex: 1 }} step={md.step} minimumValue={minimum} maximumValue={maximum} value={value} onValueChange={value => updateSettingValue(key, value)} />
</View>
</View>
);
@@ -604,7 +577,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) => void 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) => updateSettingValue(key, value)} secureTextEntry={!!md.secure} />
</View>
);
} else {

View File

@@ -1118,7 +1118,6 @@ class NoteScreenComponent extends BaseScreenComponent {
bodyComponent = <NoteEditor
ref={this.editorRef}
toolbarEnabled={this.props.toolbarEnabled}
themeId={this.props.themeId}
initialText={note.body}
initialSelection={this.selection}
@@ -1232,7 +1231,6 @@ 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,

View File

@@ -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.11.0;
MARKETING_VERSION = 12.10.5;
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.11.0;
MARKETING_VERSION = 12.10.5;
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.11.0;
MARKETING_VERSION = 12.10.5;
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.11.0;
MARKETING_VERSION = 12.10.5;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = net.cozic.joplin.ShareExtension;
PRODUCT_NAME = "$(TARGET_NAME)";

View File

@@ -306,7 +306,7 @@ PODS:
- React-jsinspector (0.70.6)
- React-logger (0.70.6):
- glog
- react-native-alarm-notification (2.11.0):
- react-native-alarm-notification (2.10.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.4):
- react-native-document-picker (8.1.3):
- 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.3.1):
- react-native-image-picker (5.0.2):
- React-Core
- react-native-image-resizer (1.4.5):
- React-Core
- react-native-netinfo (9.3.8):
- react-native-netinfo (9.3.7):
- React-Core
- react-native-rsa-native (2.0.5):
- React
- react-native-saf-x (2.11.0):
- react-native-saf-x (2.10.2):
- 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.1):
- RNShare (8.2.0):
- 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: 26527410a6162d07a9dc57f4bbc62e94ff48e65d
react-native-alarm-notification: 0f58eaa37a4188480536fd7ab62db9b1dfba392f
react-native-camera: 3eae183c1d111103963f3dd913b65d01aef8110f
react-native-document-picker: a9bd26996d1b2e4f412dd186041714c79af381d0
react-native-document-picker: 958e2bc82e128be69055be261aeac8d872c8d34c
react-native-fingerprint-scanner: ac6656f18c8e45a7459302b84da41a44ad96dbbe
react-native-geolocation: 69f4fd37650b8e7fee91816d395e62dd16f5ab8d
react-native-get-random-values: a6ea6a8a65dc93e96e24a11105b1a9c8cfe1d72a
react-native-image-picker: ec9b713e248760bfa0f879f0715391de4651a7cb
react-native-image-picker: a5dddebb4d2955ac4712a4ed66b00a85f62a63ac
react-native-image-resizer: d9fb629a867335bdc13230ac2a58702bb8c8828f
react-native-netinfo: fbc23bc2fe217155d85f2f7e0644b1654df8029b
react-native-netinfo: 2517ad504b3d303e90d7a431b0fcaef76d207983
react-native-rsa-native: 12132eb627797529fdb1f0d22fd0f8f9678df64a
react-native-saf-x: 9bd5238d3b43d76bbec64aa82c173ac20a4bce9f
react-native-saf-x: db5a33862e7aec0f9f2d4cccfe7264b09b234e2e
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: eaee3dd5a06dad397c7d3b14762007035c5de405
RNShare: b089c33619bbfb0a32bc4069c858b9274e694187
RNVectorIcons: fcc2f6cb32f5735b586e66d14103a74ce6ad61f8
SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608
Yoga: 99caf8d5ab45e9d637ee6e0174ec16fbbb01bcfc

View File

@@ -2,7 +2,7 @@
"name": "@joplin/app-mobile",
"description": "Joplin for Mobile",
"license": "AGPL-3.0-or-later",
"version": "2.11.0",
"version": "2.10.0",
"private": true,
"scripts": {
"start": "react-native start --reset-cache",
@@ -18,14 +18,14 @@
"postinstall": "jetify && yarn run build"
},
"dependencies": {
"@joplin/lib": "~2.11",
"@joplin/react-native-alarm-notification": "~2.11",
"@joplin/react-native-saf-x": "~2.11",
"@joplin/renderer": "~2.11",
"@joplin/lib": "~2.10",
"@joplin/react-native-alarm-notification": "~2.10",
"@joplin/react-native-saf-x": "~2.10",
"@joplin/renderer": "~2.10",
"@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.8",
"@react-native-community/netinfo": "9.3.7",
"@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.4",
"react-native-document-picker": "8.1.3",
"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.3.1",
"react-native-image-picker": "5.1.0",
"react-native-image-resizer": "1.4.5",
"react-native-modal-datetime-picker": "14.0.1",
"react-native-paper": "5.5.2",
"react-native-paper": "5.2.0",
"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.2.2",
"@codemirror/commands": "6.1.2",
"@codemirror/lang-cpp": "6.0.2",
"@codemirror/lang-html": "6.4.3",
"@codemirror/lang-html": "6.4.0",
"@codemirror/lang-java": "6.0.1",
"@codemirror/lang-javascript": "6.1.5",
"@codemirror/lang-markdown": "6.1.0",
"@codemirror/lang-javascript": "6.1.1",
"@codemirror/lang-markdown": "6.0.5",
"@codemirror/lang-php": "6.0.1",
"@codemirror/lang-rust": "6.0.1",
"@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",
"@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",
"@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.1",
"fs-extra": "11.1.0",
"gulp": "4.0.2",
"jest": "29.4.3",
"jest-environment-jsdom": "29.4.3",
"jetifier": "2.0.0",
"jsdom": "21.1.1",
"jsdom": "21.0.0",
"md5-file": "5.0.0",
"metro-react-native-babel-preset": "0.72.3",
"nodemon": "2.0.22",
"nodemon": "2.0.21",
"ts-jest": "29.0.5",
"ts-loader": "9.4.2",
"ts-node": "10.9.1",

View File

@@ -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, '-3') });
await db.open({ name: getDatabaseName(currentProfile, isSubProfile) });
// await db.clearForTesting();
}
@@ -984,10 +984,6 @@ 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

View File

@@ -24,10 +24,9 @@ export const getResourceDir = (profile: Profile, isSubProfile: boolean) => {
return `${getProfilesRootDir()}/resources-${profile.id}`;
};
// 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 getDatabaseName = (profile: Profile, isSubProfile: boolean) => {
if (!isSubProfile) return 'joplin.sqlite';
return `joplin-${profile.id}.sqlite`;
};
export const loadProfileConfig = async () => {

View File

@@ -1,7 +1,7 @@
{
"manifest_version": 1,
"id": "<%= pluginId %>",
"app_min_version": "2.11",
"app_min_version": "2.10",
"version": "1.0.0",
"name": "<%= pluginName %>",
"description": "<%= pluginDescription %>",

View File

@@ -1,6 +1,6 @@
{
"name": "generator-joplin",
"version": "2.11.0",
"version": "2.10.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.6",
"slugify": "1.6.5",
"yeoman-generator": "5.8.0",
"yosay": "2.0.2"
},

View File

@@ -1,6 +1,6 @@
{
"name": "@joplin/htmlpack",
"version": "2.11.0",
"version": "2.10.2",
"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.1",
"fs-extra": "11.1.0",
"html-entities": "1.4.0"
},
"devDependencies": {

View File

@@ -20,7 +20,7 @@ import Folder from './models/Folder';
import BaseItem from './models/BaseItem';
import Note from './models/Note';
import Tag from './models/Tag';
import { splitCommandString } from '@joplin/utils';
const { splitCommandString } = require('./string-utils.js');
import { reg } from './registry';
import time from './time';
import BaseSyncTarget from './BaseSyncTarget';
@@ -706,7 +706,7 @@ export default class BaseApplication {
flagContent = flagContent.trim();
let flags: any = splitCommandString(flagContent);
let flags = splitCommandString(flagContent);
flags.splice(0, 0, 'cmd');
flags.splice(0, 0, 'node');

View File

@@ -96,14 +96,12 @@ 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 api.execAccountPropertiesRequest();
accountProperties = await this.api_.execAccountPropertiesRequest();
context ? context.accountProperties = accountProperties : context = { accountProperties: accountProperties };
Setting.setValue(`sync.${this.syncTargetId()}.context`, JSON.stringify(context));
}
api.setAccountProperties(accountProperties);
this.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.

View File

@@ -1,18 +1,5 @@
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 = {
@@ -28,13 +15,12 @@ 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);
}
@@ -44,18 +30,6 @@ 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
)

View File

@@ -1050,17 +1050,6 @@ 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': {
@@ -1645,17 +1634,10 @@ 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')} (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.',
label: () => _('Use biometrics to secure access to the app'),
public: true,
appTypes: [AppType.Mobile],
},

View File

@@ -1,6 +1,6 @@
{
"name": "@joplin/lib",
"version": "2.11.0",
"version": "2.10.2",
"description": "Joplin Core library",
"author": "Laurent Cozic",
"homepage": "",
@@ -34,11 +34,10 @@
"@joplin/fork-htmlparser2": "^4.1.43",
"@joplin/fork-sax": "^1.2.47",
"@joplin/fork-uslug": "^1.0.8",
"@joplin/htmlpack": "~2.11",
"@joplin/renderer": "~2.11",
"@joplin/htmlpack": "^2.10.2",
"@joplin/renderer": "^2.10.2",
"@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",
@@ -54,7 +53,7 @@
"fast-xml-parser": "3.21.1",
"follow-redirects": "1.15.2",
"form-data": "4.0.0",
"fs-extra": "11.1.1",
"fs-extra": "11.1.0",
"hpagent": "1.2.0",
"html-entities": "1.4.0",
"html-minifier": "4.0.0",
@@ -69,7 +68,7 @@
"moment": "2.29.4",
"multiparty": "4.2.3",
"mustache": "4.2.0",
"nanoid": "3.3.6",
"nanoid": "3.3.4",
"node-fetch": "2.6.7",
"node-notifier": "10.0.1",
"node-persist": "3.1.3",
@@ -83,7 +82,7 @@
"reselect": "4.1.7",
"server-destroy": "1.0.1",
"sprintf-js": "1.1.2",
"sqlite3": "5.1.6",
"sqlite3": "5.1.4",
"string-padding": "1.0.2",
"string-to-stream": "3.0.1",
"tar": "6.1.13",

View File

@@ -1,6 +1,6 @@
/* eslint-disable import/prefer-default-export */
import { splitCommandString } from '@joplin/utils';
const { splitCommandString } = require('../../string-utils');
import { spawn } from 'child_process';
import Logger from '../../Logger';
import Setting from '../../models/Setting';

View File

@@ -110,8 +110,6 @@ 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(),

View File

@@ -100,11 +100,6 @@ 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_);
}
@@ -113,10 +108,6 @@ export default class PluginService extends BaseService {
return this.isSafeMode_;
}
public get appVersion(): string {
return this.appVersion_;
}
public set isSafeMode(v: boolean) {
this.isSafeMode_ = v;
}

View File

@@ -215,21 +215,21 @@ export default class RepositoryApi {
return this.manifests_;
}
public async canBeUpdatedPlugins(installedManifests: PluginManifest[], appVersion: string): Promise<string[]> {
public async canBeUpdatedPlugins(installedManifests: PluginManifest[]): Promise<string[]> {
const output = [];
for (const manifest of installedManifests) {
const canBe = await this.pluginCanBeUpdated(manifest.id, manifest.version, appVersion);
const canBe = await this.pluginCanBeUpdated(manifest.id, manifest.version);
if (canBe) output.push(manifest.id);
}
return output;
}
public async pluginCanBeUpdated(pluginId: string, installedVersion: string, appVersion: string): Promise<boolean> {
public async pluginCanBeUpdated(pluginId: string, installedVersion: string): Promise<boolean> {
const manifest = (await this.manifests()).find(m => m.id === pluginId);
if (!manifest) return false;
return compareVersions(installedVersion, manifest.version) < 0 && compareVersions(appVersion, manifest.app_min_version) >= 0;
return compareVersions(installedVersion, manifest.version) < 0;
}
}

View File

@@ -138,6 +138,80 @@ 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';
@@ -294,4 +368,4 @@ function scriptType(s) {
return 'en';
}
module.exports = Object.assign({ formatCssSize, camelCaseToDash, removeDiacritics, substrWithEllipsis, nextWhitespaceIndex, escapeFilename, wrap, splitCommandBatch, padLeft, toTitleCase, urlDecode, escapeHtml, surroundKeywords, scriptType, commandArgumentsToString }, stringUtilsCommon);
module.exports = Object.assign({ formatCssSize, camelCaseToDash, removeDiacritics, substrWithEllipsis, nextWhitespaceIndex, escapeFilename, wrap, splitCommandString, splitCommandBatch, padLeft, toTitleCase, urlDecode, escapeHtml, surroundKeywords, scriptType, commandArgumentsToString }, stringUtilsCommon);

View File

@@ -21,17 +21,6 @@ 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}`;

View File

@@ -86,7 +86,6 @@ describe('getPluginLists', () => {
);
plugins[plugin.manifest.id] = plugin;
}
const v = versionInfo(packageInfo, plugins);
expect(v.body).toMatch(/\n\nPlugin1: 1\nPlugin2: 1\nPlugin3: 1/);
@@ -111,7 +110,6 @@ describe('getPluginLists', () => {
plugins[plugin.manifest.id] = plugin;
}
const v = versionInfo(packageInfo, plugins);
const body = '\n';

View File

@@ -16,8 +16,6 @@ function getPluginLists(plugins: Plugins): PluginList {
}
}
pluginList.sort(Intl.Collator().compare);
let completeList = '';
let summary = '';
if (pluginList.length > 0) {

View File

@@ -1,6 +1,6 @@
{
"name": "@joplin/pdf-viewer",
"version": "2.11.0",
"version": "2.10.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.2",
"style-loader": "3.3.1",
"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.11",
"@joplin/lib": "~2.10",
"async-mutex": "0.4.0",
"pdfjs-dist": "2.16.105",
"react": "18.2.0",
"react-dom": "18.2.0",
"styled-components": "5.3.9"
"styled-components": "5.3.8"
}
}

View File

@@ -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 { resolveRelativePathWithinDir, gitPullTry, gitRepoCleanTry, gitRepoClean } from '@joplin/tools/tool-utils.js';
import { execCommand2, 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,7 +17,6 @@ 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[] = [];
@@ -50,7 +49,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 execCommand(`npm install ${packageName} --save --ignore-scripts`, { showStderr: false, showStdout: false });
await execCommand2(`npm install ${packageName} --save --ignore-scripts`, { showStderr: false, showStdout: false });
const pluginDir = resolveRelativePathWithinDir(workDir, 'node_modules', packageName, 'publish');
@@ -155,7 +154,7 @@ async function processNpmPackage(npmPackage: NpmPackage, repoDir: string, dryRun
await fs.mkdirp(packageTempDir);
chdir(packageTempDir);
await execCommand('npm init --yes --loglevel silent', { quiet: true });
await execCommand2('npm init --yes --loglevel silent', { quiet: true });
let actionType: ProcessingActionType = ProcessingActionType.Update;
let manifests: any = {};
@@ -201,8 +200,8 @@ async function processNpmPackage(npmPackage: NpmPackage, repoDir: string, dryRun
if (!dryRun) {
if (!(await gitRepoClean())) {
await execCommand('git add -A', { showStdout: false });
await execCommand(['git', 'commit', '-m', commitMessage(actionType, manifest, previousManifest, npmPackage, error)], { showStdout: false });
await execCommand2('git add -A', { showStdout: false });
await execCommand2(['git', 'commit', '-m', commitMessage(actionType, manifest, previousManifest, npmPackage, error)], { showStdout: false });
} else {
console.info('Nothing to commit');
}
@@ -228,14 +227,14 @@ async function commandBuild(args: CommandBuildArgs) {
if (!dryRun) {
if (!(await gitRepoClean())) {
console.info('Updating README...');
await execCommand('git add -A');
await execCommand('git commit -m "Update README"');
await execCommand2('git add -A');
await execCommand2('git commit -m "Update README"');
}
}
chdir(previousDir);
const searchResults = (await execCommand('npm search joplin-plugin --searchlimit 5000 --json', { showStdout: false, showStderr: false })).trim();
const searchResults = (await execCommand2('npm search joplin-plugin --searchlimit 5000 --json', { showStdout: false, showStderr: false })).trim();
const npmPackages = pluginInfoFromSearchResults(JSON.parse(searchResults));
for (const npmPackage of npmPackages) {
@@ -246,11 +245,11 @@ async function commandBuild(args: CommandBuildArgs) {
await commandUpdateRelease(args);
if (!(await gitRepoClean())) {
await execCommand('git add -A');
await execCommand('git commit -m "Update stats"');
await execCommand2('git add -A');
await execCommand2('git commit -m "Update stats"');
}
await execCommand('git push');
await execCommand2('git push');
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@joplin/plugin-repo-cli",
"version": "2.11.0",
"version": "2.10.2",
"description": "",
"main": "index.js",
"bin": "./dist/index.js",
@@ -18,10 +18,9 @@
"author": "",
"license": "AGPL-3.0-or-later",
"dependencies": {
"@joplin/lib": "~2.11",
"@joplin/tools": "~2.11",
"@joplin/utils": "~2.11",
"fs-extra": "11.1.1",
"@joplin/lib": "^2.10.2",
"@joplin/tools": "^2.10.2",
"fs-extra": "11.1.0",
"gh-release-assets": "2.0.1",
"node-fetch": "2.6.7",
"source-map-support": "0.5.21",

View File

@@ -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.11.0",
"version": "2.10.0",
"description": "schedule alarm with notification in react-native",
"main": "index.js",
"private": true,

View File

@@ -1,6 +1,6 @@
{
"name": "@joplin/react-native-saf-x",
"version": "2.11.0",
"version": "2.10.2",
"description": "a module to help work with scoped storages on android easily",
"main": "src/index",
"react-native": "src/index",

View File

@@ -179,8 +179,6 @@ export interface RuleOptions {
noteId?: string;
vendorDir?: string;
itemIdToUrl?: ItemIdToUrlHandler;
platformName?: string;
}
export default class MdToHtml {

View File

@@ -1,8 +1,6 @@
import { RuleOptions } from '../../MdToHtml';
export default {
assets: function(theme: any) {
assets: function() {
return [
{ name: 'mermaid.min.js' },
{ name: 'mermaid_render.js' },
@@ -14,27 +12,14 @@ 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, ruleOptions: RuleOptions) {
plugin: function(markdownIt: any) {
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);
@@ -46,49 +31,9 @@ export default {
return `
<div class="joplin-editable">
<pre class="joplin-source" data-joplin-language="mermaid" data-joplin-source-open="\`\`\`mermaid&#10;" data-joplin-source-close="&#10;\`\`\`&#10;">${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);
};

View File

@@ -1,6 +1,6 @@
{
"name": "@joplin/renderer",
"version": "2.11.0",
"version": "2.10.2",
"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.1",
"fs-extra": "11.1.0",
"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.1",
"markdown-it-multimd-table": "4.2.0",
"markdown-it-sub": "1.0.0",
"markdown-it-sup": "1.0.0",
"markdown-it-toc-done-right": "4.2.0",

View File

@@ -1,6 +1,6 @@
{
"name": "@joplin/server",
"version": "2.11.0",
"version": "2.10.10",
"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.11",
"@joplin/renderer": "~2.11",
"@joplin/lib": "~2.10",
"@joplin/renderer": "~2.10",
"@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.1",
"fs-extra": "11.1.0",
"html-entities": "1.4.0",
"jquery": "3.6.4",
"jquery": "3.6.3",
"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.22",
"pg": "8.10.0",
"nodemon": "2.0.21",
"pg": "8.9.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.6",
"sqlite3": "5.1.4",
"stripe": "8.222.0",
"uuid": "9.0.0",
"yargs": "17.7.1",
"zxcvbn": "4.4.2"
},
"devDependencies": {
"@joplin/tools": "~2.11",
"@joplin/tools": "~2.10",
"@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.1.1",
"node-mocks-http": "1.12.2",
"jsdom": "21.0.0",
"node-mocks-http": "1.12.1",
"source-map-support": "0.5.21",
"typescript": "4.9.4"
}

View File

@@ -1,6 +1,5 @@
import { rootDir } from './tool-utils';
import { execCommand2, rootDir } from './tool-utils';
import * as moment from 'moment';
import { execCommand } from '@joplin/utils';
interface Argv {
dryRun?: boolean;
@@ -36,7 +35,7 @@ async function main() {
const buildDate = moment(new Date().getTime()).format('YYYY-MM-DDTHH:mm:ssZ');
let revision = '';
try {
revision = await execCommand('git rev-parse --short HEAD', { showStdout: false });
revision = await execCommand2('git rev-parse --short HEAD', { showStdout: false });
} catch (error) {
console.info('Could not get git commit: metadata revision field will be empty');
}
@@ -63,11 +62,11 @@ async function main() {
return;
}
await execCommand(dockerCommand);
await execCommand2(dockerCommand);
for (const tag of dockerTags) {
await execCommand(`docker tag "${repository}:${imageVersion}" "${repository}:${tag}"`);
if (pushImages) await execCommand(`docker push ${repository}:${tag}`);
await execCommand2(`docker tag "${repository}:${imageVersion}" "${repository}:${tag}"`);
if (pushImages) await execCommand2(`docker push ${repository}:${tag}`);
}
}

View File

@@ -1,8 +1,8 @@
import { join } from 'path';
import { execCommand2 } from './tool-utils';
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 execCommand(`tar xzf ${currentDir}/${downloadedPluginsNames[pluginId]}`, { quiet: true, splitCommandOptions: { handleEscape: false } });
await execCommand2(`tar xzf ${currentDir}/${downloadedPluginsNames[pluginId]}`, { quiet: true });
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]}`);
@@ -73,20 +73,6 @@ export const downloadPlugins = async (localPluginsVersions: PluginAndVersion, de
return downloadedPluginsNames;
};
// Mac app signing/notarizing fails if the binaries are inside an archive (plugin.jpl)
// Contents of plugin.jpl are unzipped just for Mac so that binary signing passes through
// ref: https://github.com/laurent22/joplin/pull/8048, https://github.com/laurent22/joplin/pull/8040
const extractMacPlugins = async (defaultPluginDir: string, downloadedPluginsNames: PluginIdAndName) => {
if (process.platform !== 'darwin') return;
for (const pluginId in downloadedPluginsNames) {
const pluginDirectory = `${defaultPluginDir}/${pluginId}`;
const archivePath = `${pluginDirectory}/plugin.jpl`;
await execCommand(`tar xzf ${archivePath} --directory ${pluginDirectory}`, { quiet: true, splitCommandOptions: { handleEscape: false } });
await remove(archivePath);
}
};
async function start(): Promise<void> {
const defaultPluginDir = join(__dirname, '..', '..', 'packages', 'app-desktop', 'build', 'defaultPlugins');
const defaultPluginsInfo = getDefaultPluginsInfo();
@@ -98,7 +84,6 @@ 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 extractMacPlugins(defaultPluginDir, downloadedPluginNames);
}
if (require.main === module) {

View File

@@ -1,5 +1,4 @@
import { execCommand } from '@joplin/utils';
import { rootDir } from './tool-utils';
import { execCommand2, rootDir } from './tool-utils';
const sqlts = require('@rmp135/sql-ts').default;
const fs = require('fs-extra');
@@ -7,7 +6,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 execCommand('yarn start version');
await execCommand2('yarn start version');
const sqlTsConfig = {
'client': 'sqlite3',

View File

@@ -1,12 +0,0 @@
// 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);
});

View File

@@ -36,7 +36,6 @@ module.exports = {
'packages/fork-sax/**',
'packages/lib/plugin_types/**',
'packages/server/**',
'packages/utils/**',
],
}).filter(f => !f.endsWith('.d.ts'));

View File

@@ -1,12 +0,0 @@
// 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);
});

View File

@@ -1,7 +1,6 @@
import { readdir, stat, writeFile } from 'fs-extra';
import { chdir, cwd } from 'process';
import { rootDir } from './tool-utils';
import { execCommand } from '@joplin/utils';
import { execCommand2, rootDir } from './tool-utils';
import yargs = require('yargs');
import { rtrimSlashes } from '@joplin/lib/path-utils';
@@ -14,7 +13,7 @@ interface LicenseInfo {
const getLicenses = async (directory: string): Promise<Record<string, LicenseInfo>> => {
const previousDir = cwd();
await chdir(directory);
const result = await execCommand(['license-checker-rseidelsohn', '--production', '--json'], { quiet: true });
const result = await execCommand2(['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

View File

@@ -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 "%d Gt"
msgstr ""
#: packages/lib/utils/joplinCloud.ts:133 packages/lib/utils/joplinCloud.ts:134
#: packages/lib/utils/joplinCloud.ts:135
msgid "%d GB storage space"
msgstr "%d Gt tallennustila"
msgstr ""
#: packages/lib/models/Setting.ts:1345
msgid "%d hour"
@@ -109,12 +109,13 @@ 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 "%d Mt"
msgstr ""
#: 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 "%d Mt muistiinpanoa tai liitettä kohti"
msgstr "Muistiinpanon liitteet"
#: packages/lib/models/Setting.ts:1342 packages/lib/models/Setting.ts:1343
#: packages/lib/models/Setting.ts:1344
@@ -127,8 +128,9 @@ 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"
@@ -321,8 +323,6 @@ 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,8 +390,6 @@ 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:"
@@ -496,7 +494,7 @@ msgstr "Takaisin"
#: packages/lib/utils/joplinCloud.ts:294
msgid "Basic"
msgstr "Perus"
msgstr ""
#: packages/app-desktop/gui/NoteEditor/editorCommandDeclarations.ts:33
#: packages/app-mobile/components/NoteEditor/MarkdownToolbar/MarkdownToolbar.tsx:132
@@ -600,8 +598,9 @@ 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."
@@ -744,8 +743,9 @@ msgid "Close"
msgstr "Sulkea"
#: packages/app-mobile/components/Dropdown.tsx:166
#, fuzzy
msgid "Close dropdown"
msgstr "Sulje pudotusvalikko"
msgstr "Sulje ikkuna"
#: 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 "Yhdistetty laskutus"
msgstr ""
#: 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 "Jatkaa"
msgstr ""
#: packages/app-mobile/components/screens/Note.tsx:930
msgid "Convert to note"
@@ -970,8 +970,9 @@ msgstr ""
"Virhe oli: \"%s\""
#: packages/app-mobile/components/ProfileSwitcher/ProfileSwitcher.tsx:55
#, fuzzy
msgid "Could not switch profile: %s"
msgstr "Profiilia ei voitu vaihtaa: %s"
msgstr "Laajennuksen asentaminen epäonnistui: %s"
#: packages/lib/components/EncryptionConfigScreen/utils.ts:219
msgid "Could not upgrade master key: %s"
@@ -987,15 +988,16 @@ msgstr ""
#: packages/app-mobile/components/biometrics/BiometricPopup.tsx:29
msgid "Could not verify your identify"
msgstr "Henkilöllisyyttäsi ei voitu vahvistaa"
msgstr ""
#: 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 uusi muistikirja päämuistikirjan alle."
msgstr "Luo uuden muistikirjan."
#: packages/app-mobile/components/note-list.js:101
msgid "Create a notebook"
@@ -1218,8 +1220,9 @@ msgid "Delete plugin \"%s\"?"
msgstr "Poista laajennus \"%s\"?"
#: packages/app-mobile/components/ProfileSwitcher/ProfileSwitcher.tsx:101
#, fuzzy
msgid "Delete profile \"%s\""
msgstr "Poista profiili \"%s\""
msgstr "Poista muistiinpano \"%s\"?"
#: packages/app-mobile/components/ScreenHeader.tsx:420
msgid "Delete selected notes"
@@ -1238,8 +1241,9 @@ msgstr ""
"muistikirjaa."
#: packages/app-mobile/components/ProfileSwitcher/ProfileSwitcher.tsx:97
#, fuzzy
msgid "Delete this profile?"
msgstr "Poistetaanko tämä profiili?"
msgstr "Poistetaanko nämä %d muistiinpanot?"
#: packages/lib/Synchronizer.ts:186
msgid "Deleted local items: %d."
@@ -1484,8 +1488,9 @@ msgid "Edit notebook"
msgstr "Muokkaa muistikirjaa"
#: packages/app-mobile/components/ProfileSwitcher/ProfileEditor.tsx:87
#, fuzzy
msgid "Edit profile"
msgstr "Muokkaa profiilia"
msgstr "Vie profiili"
#: packages/app-desktop/commands/editProfileConfig.ts:9
msgid "Edit profile configuration..."
@@ -1577,7 +1582,7 @@ msgstr "Ota käyttöön audiosoitin"
#: packages/app-mobile/components/biometrics/BiometricPopup.tsx:61
msgid "Enable biometrics authentication?"
msgstr "Otetaanko biometrinen todennus käyttöön?"
msgstr ""
#: packages/lib/models/Setting.ts:1146
msgid "Enable deflist syntax"
@@ -1630,7 +1635,7 @@ msgstr "Ota pehmeät tauot käyttöön"
#: packages/lib/models/Setting.ts:1048
msgid "Enable spellcheck in the text editor"
msgstr "Ota oikeinkirjoituksen tarkistus käyttöön tekstieditorissa"
msgstr ""
#: packages/lib/models/Setting.ts:1143
msgid "Enable table of contents extension"
@@ -2293,7 +2298,7 @@ msgstr "Kohteet, joita ei voi synkronoida"
#: packages/app-desktop/gui/MenuBar.tsx:792
msgid "Join us on Twitter"
msgstr "Liity meihin Twitterissä"
msgstr ""
#: packages/app-desktop/gui/SyncWizard/Dialog.tsx:330
msgid ""
@@ -2542,12 +2547,14 @@ msgid "Manage master password..."
msgstr "Pääsalasanan hallinta..."
#: packages/lib/utils/joplinCloud.ts:165
#, fuzzy
msgid "Manage multiple users"
msgstr "Hallitse useita käyttäjiä"
msgstr "Pääsalasanan hallinta"
#: packages/app-mobile/components/screens/ConfigScreen.tsx:611
#, fuzzy
msgid "Manage profiles"
msgstr "Hallitse profiileja"
msgstr "Päivitä profiili"
#: packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginsStates.tsx:320
msgid "Manage your plugins"
@@ -2614,8 +2621,9 @@ msgid "Max Item Size"
msgstr "Kohteen enimmäiskoko"
#: packages/lib/utils/joplinCloud.ts:117
#, fuzzy
msgid "Max note or attachment size"
msgstr "Muistiinpanon tai liitteen enimmäiskoko"
msgstr "Muistiinpanon liitteet"
#: packages/server/src/routes/admin/users.ts:150
msgid "Max Total Size"
@@ -2634,8 +2642,9 @@ 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 "Pakollinen lipun arvo puuttuu: %s"
msgstr "Vaadittu argumentti puuttuu: %s"
#: packages/app-mobile/components/side-menu-content.tsx:457
msgid "Mobile data - auto-sync disabled"
@@ -2810,8 +2819,9 @@ msgid "Not generated"
msgstr "Ei luotu"
#: packages/app-mobile/components/biometrics/BiometricPopup.tsx:70
#, fuzzy
msgid "Not now"
msgstr "Ei nyt"
msgstr "Hae se nyt"
#: packages/app-desktop/gui/NoteEditor/NoteTitle/NoteTitleBar.tsx:110
#: packages/server/src/models/UserModel.ts:215
@@ -3074,7 +3084,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 "Liitä tekstinä"
msgstr ""
#: packages/app-desktop/gui/ConfigScreen/ConfigScreen.tsx:541
msgid "Path:"
@@ -3087,7 +3097,7 @@ msgstr "PDF tiedosto"
#: packages/lib/utils/joplinCloud.ts:355
msgid "Per user. Minimum of %d users."
msgstr "Käyttäjää kohti. Vähintään %d käyttäjää."
msgstr ""
#: packages/app-mobile/components/screens/Note.tsx:404
msgid "Permission needed"
@@ -3248,15 +3258,16 @@ msgstr "Tulosta"
#: packages/lib/utils/joplinCloud.ts:183
msgid "Priority support"
msgstr "Ensisijainen tuki"
msgstr ""
#: 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 "Ammattilainen"
msgstr "Profiili"
#: packages/server/src/services/TaskService.ts:24
msgid "Process failed payment subscriptions"
@@ -3275,8 +3286,9 @@ 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:"
@@ -3287,8 +3299,9 @@ msgid "Profile Version: %s"
msgstr "Profiilin versio: %s"
#: packages/app-mobile/components/ProfileSwitcher/ProfileSwitcher.tsx:155
#, fuzzy
msgid "Profiles"
msgstr "Profiilit"
msgstr "Profiili"
#: packages/app-mobile/components/screens/Note.tsx:944
msgid "Properties"
@@ -3437,8 +3450,9 @@ msgid "Replace: "
msgstr "Vaihda: "
#: packages/app-desktop/gui/MainScreen/commands/resetLayout.ts:7
#, fuzzy
msgid "Reset application layout"
msgstr "Palauta sovelluksen asettelu"
msgstr "Sovelluksen asettelun muuttaminen"
#: packages/app-desktop/gui/MasterPasswordDialog/Dialog.tsx:219
#: packages/app-desktop/gui/MasterPasswordDialog/Dialog.tsx:220
@@ -3678,8 +3692,9 @@ msgid "Share"
msgstr "Jaa"
#: packages/lib/utils/joplinCloud.ts:159
#, fuzzy
msgid "Share and collaborate on a notebook"
msgstr "Muistikirjan jakaminen ja yhteiskäyttö"
msgstr "Muistiinpanoja voi luoda vain muistikirjaan."
#: packages/app-desktop/gui/ShareFolderDialog/ShareFolderDialog.tsx:339
msgid "Share Notebook"
@@ -3691,7 +3706,7 @@ msgstr "Muistikirjan jakaminen..."
#: packages/lib/utils/joplinCloud.ts:177
msgid "Sharing access control"
msgstr "Käyttöoikeuksien hallinnan jakaminen"
msgstr ""
#: packages/app-desktop/gui/ShareFolderDialog/ShareFolderDialog.tsx:305
msgid "Sharing notebook..."
@@ -3917,7 +3932,7 @@ msgstr "Lopeta ulkoisen tekstieditorin muokkaus"
#: packages/lib/utils/joplinCloud.ts:129
msgid "Storage space"
msgstr "Tallennustila"
msgstr ""
#: packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/setupToolbarButtons.ts:19
msgid "Strikethrough"
@@ -3985,7 +4000,7 @@ msgstr ""
#: packages/lib/utils/joplinCloud.ts:147
msgid "Sync as many devices as you want"
msgstr "Synkronoi niin monta laitetta kuin haluat"
msgstr ""
#: packages/app-mobile/components/screens/ConfigScreen.tsx:612
msgid "Sync Status"
@@ -4100,7 +4115,7 @@ msgstr "Tehtävät"
#: packages/lib/utils/joplinCloud.ts:338
msgid "Teams"
msgstr "Tiimit"
msgstr ""
#: packages/lib/models/Setting.ts:1366
msgid "Text editor command"
@@ -4115,8 +4130,6 @@ 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 ""
@@ -4182,7 +4195,7 @@ msgstr ""
#: packages/lib/services/profileConfig/index.ts:104
msgid "The default profile cannot be deleted"
msgstr "Oletusprofiilia ei voi poistaa"
msgstr ""
#: packages/lib/models/Setting.ts:1366
msgid ""
@@ -4330,8 +4343,6 @@ 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"
@@ -4345,7 +4356,7 @@ msgstr ""
#: packages/app-mobile/components/screens/ConfigScreen.tsx:341
msgid "There are unsaved changes."
msgstr "On tallentamattomia muutoksia."
msgstr ""
#: packages/app-desktop/gui/NoteList/NoteList.tsx:512
msgid ""
@@ -4569,8 +4580,6 @@ 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 ""
@@ -4652,8 +4661,9 @@ 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 "Kokeile nyt"
msgstr "Hae se nyt"
#: packages/app-cli/app/command-help.js:71
msgid ""
@@ -4812,7 +4822,7 @@ msgstr "Käyttö: %s"
#: packages/lib/models/Setting.ts:1640
msgid "Use biometrics to secure access to the app"
msgstr "Käytä biometrisiä tunnisteita suojataksesi pääsyn sovellukseen"
msgstr ""
#: packages/app-cli/app/command-ls.js:32 packages/app-cli/app/command-tag.js:18
msgid ""
@@ -4851,8 +4861,6 @@ 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 ""
@@ -4888,7 +4896,7 @@ msgstr "Kelvollinen"
#: packages/app-mobile/components/biometrics/BiometricPopup.tsx:25
msgid "Verify your identity"
msgstr "Vahvista henkilöllisyytesi"
msgstr ""
#: packages/app-desktop/gui/NoteList/NoteList.tsx:167
msgid "View"

View File

@@ -653,7 +653,7 @@ msgstr ""
#: packages/app-mobile/components/NoteEditor/SearchPanel.tsx:328
msgid "Case sensitive"
msgstr "Razlikuje velika i mala slova"
msgstr ""
#: 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 aktualna."
msgstr "Trenutačna verzija je najnovija verzija."
#: 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 ključeve"
msgstr "Izbriši istekle tokene"
#: 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 "Gotovo"
msgstr ""
#: 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 "Aktivirati biometrijsku autentifikaciju?"
msgstr ""
#: 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 "Umetni"
msgstr "Umetnuto"
#: 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žaka"
msgstr "Čuvaj povijest bilješke"
#: 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 "Uređivač za bilješke"
msgstr "Povijest bilježaka"
#: 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 "Razvrstan popis"
msgstr "Stvori korisnika"
#: 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 bilježnica velika, pojavljivanje svih bilježaka na "
"uređaju primatelja može potrajati nekoliko minuta."
"Imaj na umu, da ako je velika bilježnica, može potrajati nekoliko minuta dok "
"se sve bilješke pojave na uređaju primatelja."
#: 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” 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."
"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."
#: 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 "Prethodno poklapanje"
msgstr ""
#: 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 "Zamijeni sa …"
msgstr ""
#: 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 "Obnovi raspored programa"
msgstr "Promijeni 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 "Dijeljenje kontrole pristupa"
msgstr ""
#: 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 dostupni u naredbenom retku."
msgstr "Prečaci nisu podržani 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 za određivanje redoslijeda"
msgstr "Prikaži gumbe 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 ""
"Prebacuje na bilježnicu [notebook] – sve daljnje operacije će se izvoditi u "
"ovoj bilježnici."
"Mijenja se u bilježnicu [notebook] – sve daljnje operacije izvode se u toj "
"bilježnici."
#: packages/lib/utils/joplinCloud.ts:147
msgid "Sync as many devices as you want"
msgstr "Sinkroniziraj koliko god uređaja želiš"
msgstr ""
#: 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 je promijenjena sa sigurnijom metodom. "
"Standardna metoda šifriranja promijenjena je u sigurniju metodu. "
"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 [conflict](%s) s dolje navedenim privitkom.\n"
"Došlo je do [konflikta](%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 da pristupe Joplinu."
"programima pristupiti 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 "Nerazvstan popis"
msgstr "Stvori korisnika"
#: 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 "Koristi biometrijske podatke za osiguravanje pristupa programu"
msgstr ""
#: packages/app-cli/app/command-ls.js:32 packages/app-cli/app/command-tag.js:18
msgid ""
@@ -5437,9 +5437,6 @@ 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"

View File

@@ -1,6 +1,6 @@
{
"name": "@joplin/tools",
"version": "2.11.0",
"version": "2.10.2",
"description": "Various tools for Joplin",
"main": "index.js",
"author": "Laurent Cozic",
@@ -20,12 +20,13 @@
},
"license": "AGPL-3.0-or-later",
"dependencies": {
"@joplin/lib": "~2.11",
"@joplin/renderer": "~2.11",
"@joplin/utils": "~2.11",
"@joplin/lib": "^2.10.2",
"@joplin/renderer": "^2.10.2",
"@types/node-fetch": "2.6.2",
"@types/yargs": "17.0.20",
"dayjs": "1.11.7",
"execa": "4.1.0",
"fs-extra": "11.1.1",
"fs-extra": "11.1.0",
"gettext-parser": "6.0.0",
"glob": "8.1.0",
"markdown-it": "13.0.1",
@@ -47,15 +48,13 @@
"@types/jest": "29.2.6",
"@types/mustache": "4.2.2",
"@types/node": "18.11.18",
"@types/node-fetch": "2.6.2",
"@types/yargs": "17.0.20",
"gettext-extractor": "3.7.0",
"gettext-extractor": "3.6.2",
"gulp": "4.0.2",
"html-entities": "1.4.0",
"jest": "29.4.3",
"rss": "1.2.2",
"sass": "1.59.3",
"sqlite3": "5.1.6",
"sass": "1.58.3",
"sqlite3": "5.1.4",
"typescript": "4.9.4"
},
"gitHead": "eb4b0e64eab40a51b0895d3a40a9d8c3cb7b1b14"

View File

@@ -1,6 +1,5 @@
import { execCommand } from '@joplin/utils';
import * as fs from 'fs-extra';
import { execCommandVerbose, execCommandWithPipes, githubRelease, githubOauthToken, fileExists, gitPullTry, completeReleaseWithChangelog } from './tool-utils';
import { execCommandVerbose, execCommandWithPipes, githubRelease, githubOauthToken, fileExists, gitPullTry, completeReleaseWithChangelog, execCommand2 } from './tool-utils';
const path = require('path');
const fetch = require('node-fetch');
const uriTemplate = require('uri-template');
@@ -151,7 +150,7 @@ async function main() {
const isPreRelease = !('type' in argv) || argv.type === 'prerelease';
process.chdir(rnDir);
await execCommand('yarn run build', { showStdout: false });
await execCommand2('yarn run build', { showStdout: false });
if (isPreRelease) console.info('Creating pre-release');
console.info('Updating version numbers in build.gradle...');

View File

@@ -1,5 +1,4 @@
import { execCommand } from '@joplin/utils';
import { rootDir, completeReleaseWithChangelog } from './tool-utils';
import { execCommand2, rootDir, completeReleaseWithChangelog } from './tool-utils';
const appDir = `${rootDir}/packages/app-cli`;
const changelogPath = `${rootDir}/readme/changelog_cli.md`;
@@ -9,19 +8,19 @@ const changelogPath = `${rootDir}/readme/changelog_cli.md`;
async function main() {
process.chdir(appDir);
await execCommand('git pull');
await execCommand2('git pull');
const newVersion = (await execCommand('npm version patch')).trim();
const newVersion = (await execCommand2('npm version patch')).trim();
console.info(`Building ${newVersion}...`);
const newTag = `cli-${newVersion}`;
await execCommand('touch app/main.js');
await execCommand('yarn run build');
await execCommand('cp ../../README.md build/');
await execCommand2('touch app/main.js');
await execCommand2('yarn run build');
await execCommand2('cp ../../README.md build/');
process.chdir(`${appDir}/build`);
await execCommand('npm publish');
await execCommand2('npm publish');
await completeReleaseWithChangelog(changelogPath, newVersion, newTag, 'CLI', false);
}

View File

@@ -1,5 +1,4 @@
import { execCommand } from '@joplin/utils';
import { gitCurrentBranch, githubRelease, gitPullTry, rootDir } from './tool-utils';
import { execCommand2, gitCurrentBranch, githubRelease, gitPullTry, rootDir } from './tool-utils';
const appDir = `${rootDir}/packages/app-desktop`;
@@ -12,16 +11,16 @@ async function main() {
console.info(`Running from: ${process.cwd()}`);
const version = (await execCommand('npm version patch')).trim();
const version = (await execCommand2('npm version patch')).trim();
const tagName = version;
console.info(`New version number: ${version}`);
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');
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');
const releaseOptions = { isDraft: true, isPreRelease: !!argv.beta };

View File

@@ -1,6 +1,5 @@
import { execCommand } from '@joplin/utils';
import { chdir } from 'process';
import { rootDir, gitPullTry, releaseFinalGitCommands } from './tool-utils';
import { rootDir, gitPullTry, execCommand2, releaseFinalGitCommands } from './tool-utils';
const workDir = `${rootDir}/packages/plugin-repo-cli`;
@@ -8,18 +7,18 @@ async function main() {
await gitPullTry();
chdir(rootDir);
await execCommand('yarn run tsc');
await execCommand2('yarn run tsc');
chdir(workDir);
await execCommand('yarn run dist');
await execCommand2('yarn run dist');
const newVersion = (await execCommand('npm version patch')).trim();
const newVersion = (await execCommand2('npm version patch')).trim();
console.info(`New version: ${newVersion}`);
const tagName = `plugin-repo-cli-${newVersion}`;
console.info(`Tag name: ${tagName}`);
await execCommand('npm publish');
await execCommand2('npm publish');
console.info(releaseFinalGitCommands('Plugin Repo CLI', newVersion, tagName));
}

View File

@@ -1,5 +1,4 @@
import { execCommand } from '@joplin/utils';
import { rootDir, gitPullTry, completeReleaseWithChangelog } from './tool-utils';
import { execCommand2, rootDir, gitPullTry, completeReleaseWithChangelog } from './tool-utils';
const serverDir = `${rootDir}/packages/server`;
@@ -13,7 +12,7 @@ async function main() {
await gitPullTry();
process.chdir(serverDir);
const version = (await execCommand('npm version patch')).trim();
const version = (await execCommand2('npm version patch')).trim();
const versionSuffix = ''; // isPreRelease ? '-beta' : '';
const tagName = `server-${version}${versionSuffix}`;

View File

@@ -40,7 +40,7 @@ yarn install
# to change after installation.
git reset --hard
JOPLIN_GITHUB_OAUTH_TOKEN=$JOPLIN_GITHUB_OAUTH_TOKEN yarn run updateMarkdownDoc
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

View File

@@ -139,7 +139,6 @@ 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);

View File

@@ -1,7 +1,6 @@
import yargs = require('yargs');
import { chdir } from 'process';
import { rootDir } from './tool-utils';
import { execCommand } from '@joplin/utils';
import { execCommand2, rootDir } from './tool-utils';
const main = async () => {
const argv = await yargs.argv;
@@ -11,7 +10,7 @@ const main = async () => {
chdir(rootDir);
try {
await execCommand(['yarn', 'run', 'cspell'].concat(filePaths), { showStderr: false, showStdout: false });
await execCommand2(['yarn', 'run', 'cspell'].concat(filePaths), { showStderr: false, showStdout: false });
} catch (error) {
if (!error.stdout.trim()) return;

View File

@@ -64,6 +64,11 @@
"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",
@@ -81,11 +86,5 @@
"imageName": "Grundstueckspreise.png"
}
],
"orgsOld": [
{
"url": "https://usrigging.com/",
"title": "U.S. Ringing Supply",
"imageName": "RingingSupply.svg"
}
]
"orgsOld": []
}

View File

@@ -1,4 +1,4 @@
import { execCommand } from '@joplin/utils';
import { execCommand2 } from './tool-utils';
async function main() {
const argv = require('yargs').argv;
@@ -6,9 +6,9 @@ async function main() {
const version = argv._[0];
await execCommand(`docker pull "joplin/server:${version}"`);
await execCommand(`docker tag "joplin/server:${version}" "joplin/server:latest"`);
await execCommand('docker push joplin/server:latest');
await execCommand2(`docker pull "joplin/server:${version}"`);
await execCommand2(`docker tag "joplin/server:${version}" "joplin/server:latest"`);
await execCommand2('docker push joplin/server:latest');
}
if (require.main === module) {

View File

@@ -1,9 +1,9 @@
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';
import * as fs from 'fs-extra';
import { readCredentialFile } from '@joplin/lib/utils/credentialFiles';
const fetch = require('node-fetch');
const execa = require('execa');
const { splitCommandString } = require('@joplin/lib/string-utils');
const moment = require('moment');
export interface GitHubReleaseAsset {
@@ -20,10 +20,27 @@ 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 readFile(changelogPath, 'UTF-8');
const currentText = await fs.readFile(changelogPath, 'UTF-8');
const lines = currentText.split('\n');
const beforeLines = [];
@@ -80,7 +97,7 @@ export async function completeReleaseWithChangelog(changelogPath: string, newVer
const newChangelog = await insertChangelog(newTag, changelogPath, changelog, isPreRelease, repoTagUrl);
await writeFile(changelogPath, newChangelog);
await fs.writeFile(changelogPath, newChangelog);
console.info('');
console.info('Verify that the changelog is correct:');
@@ -95,8 +112,8 @@ export async function completeReleaseWithChangelog(changelogPath: string, newVer
async function loadGitHubUsernameCache() {
const path = `${__dirname}/github_username_cache.json`;
if (await pathExists(path)) {
const jsonString = await readFile(path, 'utf8');
if (await fs.pathExists(path)) {
const jsonString = await fs.readFile(path, 'utf8');
return JSON.parse(jsonString);
}
@@ -105,7 +122,7 @@ async function loadGitHubUsernameCache() {
async function saveGitHubUsernameCache(cache: any) {
const path = `${__dirname}/github_username_cache.json`;
await writeFile(path, JSON.stringify(cache));
await fs.writeFile(path, JSON.stringify(cache));
}
// Returns the project root dir
@@ -146,6 +163,52 @@ 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;
@@ -173,21 +236,22 @@ export function toSystemSlashes(path: string) {
}
export async function setPackagePrivateField(filePath: string, value: any) {
const text = await readFile(filePath, 'utf8');
const text = await fs.readFile(filePath, 'utf8');
const obj = JSON.parse(text);
if (!value) {
delete obj.private;
} else {
obj.private = true;
}
await writeFile(filePath, JSON.stringify(obj, null, 2), 'utf8');
await fs.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 = createWriteStream(targetPath);
const file = fs.createWriteStream(targetPath);
https.get(url, (response: any) => {
if (response.statusCode !== 200) reject(new Error(`HTTP error ${response.statusCode}`));
response.pipe(file);
@@ -221,8 +285,10 @@ export function fileSha256(filePath: string) {
}
export async function unlinkForce(filePath: string) {
const fs = require('fs-extra');
try {
await unlink(filePath);
await fs.unlink(filePath);
} catch (error) {
if (error.code === 'ENOENT') return;
throw error;
@@ -230,8 +296,10 @@ export async function unlinkForce(filePath: string) {
}
export function fileExists(filePath: string) {
const fs = require('fs-extra');
return new Promise((resolve, reject) => {
stat(filePath, (error: any) => {
fs.stat(filePath, (error: any) => {
if (!error) {
resolve(true);
} else if (error.code === 'ENOENT') {
@@ -321,10 +389,7 @@ export function patreonOauthToken() {
}
export function githubOauthToken() {
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`);
return readCredentialFile('github_oauth_token.txt');
}
// Note that the GitHub API releases/latest is broken on the joplin-android repo
@@ -420,11 +485,12 @@ export function isMac() {
}
export async function insertContentIntoFile(filePath: string, markerOpen: string, markerClose: string, contentToInsert: string) {
let content = await readFile(filePath, 'utf-8');
const fs = require('fs-extra');
let content = await fs.readFile(filePath, 'utf-8');
// [^]* matches any character including new lines
const regex = new RegExp(`${markerOpen}[^]*?${markerClose}`);
content = content.replace(regex, markerOpen + contentToInsert + markerClose);
await writeFile(filePath, content);
await fs.writeFile(filePath, content);
}
export function dirname(path: string) {

View File

@@ -1,9 +1,43 @@
import { readFile } from 'fs-extra';
import { insertContentIntoFile, rootDir } from './tool-utils';
import markdownUtils, { MarkdownTableHeader, MarkdownTableJustify, MarkdownTableRow } from '@joplin/lib/markdownUtils';
import { GithubSponsor, loadSponsors, OrgSponsor } from './utils/loadSponsors';
import { GithubSponsor, GithubUser, OrgSponsor, Sponsors } from './website/utils/types';
import fetch from 'node-fetch';
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();
@@ -36,7 +70,9 @@ async function createGitHubSponsorTable(sponsors: GithubSponsor[]): Promise<stri
sponsorIndex++;
if (!sponsor) break;
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})`;
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})`;
}
if (Object.keys(row)) rows.push(row);
@@ -58,7 +94,7 @@ async function createOrgSponsorTable(sponsors: OrgSponsor[]): Promise<string> {
}
async function main() {
const sponsors = await loadSponsors();
const sponsors: Sponsors = JSON.parse(await readFile(sponsorsPath, 'utf8'));
await insertContentIntoFile(
readmePath,

View File

@@ -1,6 +1,5 @@
import { execCommand } from '@joplin/utils';
import { chdir } from 'process';
import { rootDir, gitRepoCleanTry } from './tool-utils';
import { execCommand2, rootDir, gitRepoCleanTry } from './tool-utils';
import updateDownloadPage from './website/updateDownloadPage';
async function main() {
@@ -8,23 +7,23 @@ async function main() {
if (doGitOperations) {
await gitRepoCleanTry();
await execCommand(['git', 'pull', '--rebase']);
await execCommand2(['git', 'pull', '--rebase']);
}
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`]);
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`]);
chdir(rootDir);
await execCommand(['yarn', 'run', 'buildApiDoc']);
await execCommand2(['yarn', 'run', 'buildApiDoc']);
await updateDownloadPage();
if (doGitOperations) {
await execCommand(['git', 'add', '-A']);
await execCommand(['git', 'commit', '-m', 'Update Markdown doc']);
await execCommand(['git', 'pull', '--rebase']);
await execCommand(['git', 'push']);
await execCommand2(['git', 'add', '-A']);
await execCommand2(['git', 'commit', '-m', 'Update Markdown doc']);
await execCommand2(['git', 'pull', '--rebase']);
await execCommand2(['git', 'push']);
}
}

View File

@@ -1,48 +0,0 @@
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;
};

View File

@@ -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, TemplateParams } from './utils/types';
import { AssetUrls, Env, Partials, PlanPageParams, Sponsors, TemplateParams } from './utils/types';
import { createFeatureTableMd, getPlans, loadStripeConfig } from '@joplin/lib/utils/joplinCloud';
import { stripOffFrontMatter } from './utils/frontMatter';
import { dirname, basename } from 'path';
@@ -13,7 +13,6 @@ 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;
@@ -176,6 +175,16 @@ 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();

View File

@@ -1,5 +1,4 @@
import { Plan, StripePublicConfig } from '@joplin/lib/utils/joplinCloud';
import { Sponsors } from '../../utils/loadSponsors';
import { OpenGraphTags } from './openGraph';
export enum Env {
@@ -7,10 +6,26 @@ 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;

View File

@@ -11,7 +11,7 @@
"browserify": "14.5.0",
"rollup": "0.50.1",
"standard": "17.0.0",
"turndown": "7.1.2",
"turndown": "7.1.1",
"turndown-attendant": "0.0.3"
},
"files": [

View File

@@ -13,7 +13,7 @@
"dependencies": {
"css": "3.0.0",
"html-entities": "1.4.0",
"jsdom": "21.1.1"
"jsdom": "21.0.0"
},
"devDependencies": {
"browserify": "14.5.0",

View File

@@ -1,2 +0,0 @@
dist/
node_modules/

Some files were not shown because too many files have changed in this diff Show More