You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2026-01-08 00:14:28 +02:00
Compare commits
13 Commits
v1.7.2
...
docker_ser
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dac3685a56 | ||
|
|
bdf0e50b56 | ||
|
|
0b14d927ce | ||
|
|
767041dddb | ||
|
|
df65b8e6de | ||
|
|
58c2bb5916 | ||
|
|
dce2f2955f | ||
|
|
fdbd790ce1 | ||
|
|
d979866f2f | ||
|
|
d3a53abe32 | ||
|
|
31ef1d675c | ||
|
|
58b5f4830c | ||
|
|
92095c5f34 |
@@ -6,5 +6,4 @@ packages/app-desktop
|
||||
packages/app-cli
|
||||
packages/app-mobile
|
||||
packages/app-clipper
|
||||
packages/generator-joplin
|
||||
packages/plugin-repo-cli
|
||||
packages/generator-joplin
|
||||
@@ -111,9 +111,6 @@ packages/app-cli/tests/models_Note.js.map
|
||||
packages/app-cli/tests/models_Setting.d.ts
|
||||
packages/app-cli/tests/models_Setting.js
|
||||
packages/app-cli/tests/models_Setting.js.map
|
||||
packages/app-cli/tests/services/plugins/RepositoryApi.d.ts
|
||||
packages/app-cli/tests/services/plugins/RepositoryApi.js
|
||||
packages/app-cli/tests/services/plugins/RepositoryApi.js.map
|
||||
packages/app-cli/tests/services/plugins/api/JoplinSettings.d.ts
|
||||
packages/app-cli/tests/services/plugins/api/JoplinSettings.js
|
||||
packages/app-cli/tests/services/plugins/api/JoplinSettings.js.map
|
||||
@@ -1374,12 +1371,6 @@ packages/lib/uuid.js.map
|
||||
packages/lib/versionInfo.d.ts
|
||||
packages/lib/versionInfo.js
|
||||
packages/lib/versionInfo.js.map
|
||||
packages/plugin-repo-cli/dummy.test.d.ts
|
||||
packages/plugin-repo-cli/dummy.test.js
|
||||
packages/plugin-repo-cli/dummy.test.js.map
|
||||
packages/plugin-repo-cli/index.d.ts
|
||||
packages/plugin-repo-cli/index.js
|
||||
packages/plugin-repo-cli/index.js.map
|
||||
packages/plugins/ToggleSidebars/api/index.d.ts
|
||||
packages/plugins/ToggleSidebars/api/index.js
|
||||
packages/plugins/ToggleSidebars/api/index.js.map
|
||||
@@ -1470,6 +1461,21 @@ packages/renderer/utils.js.map
|
||||
packages/server/src/app.d.ts
|
||||
packages/server/src/app.js
|
||||
packages/server/src/app.js.map
|
||||
packages/server/src/config-base.d.ts
|
||||
packages/server/src/config-base.js
|
||||
packages/server/src/config-base.js.map
|
||||
packages/server/src/config-buildTypes.d.ts
|
||||
packages/server/src/config-buildTypes.js
|
||||
packages/server/src/config-buildTypes.js.map
|
||||
packages/server/src/config-dev.d.ts
|
||||
packages/server/src/config-dev.js
|
||||
packages/server/src/config-dev.js.map
|
||||
packages/server/src/config-prod.d.ts
|
||||
packages/server/src/config-prod.js
|
||||
packages/server/src/config-prod.js.map
|
||||
packages/server/src/config-tests.d.ts
|
||||
packages/server/src/config-tests.js
|
||||
packages/server/src/config-tests.js.map
|
||||
packages/server/src/config.d.ts
|
||||
packages/server/src/config.js
|
||||
packages/server/src/config.js.map
|
||||
@@ -1680,13 +1686,10 @@ packages/server/src/utils/urlUtils.js.map
|
||||
packages/server/src/utils/uuidgen.d.ts
|
||||
packages/server/src/utils/uuidgen.js
|
||||
packages/server/src/utils/uuidgen.js.map
|
||||
packages/tools/lerna-add.d.ts
|
||||
packages/tools/lerna-add.js
|
||||
packages/tools/lerna-add.js.map
|
||||
packages/tools/build-plugin-repository.d.ts
|
||||
packages/tools/build-plugin-repository.js
|
||||
packages/tools/build-plugin-repository.js.map
|
||||
packages/tools/release-server.d.ts
|
||||
packages/tools/release-server.js
|
||||
packages/tools/release-server.js.map
|
||||
packages/tools/tool-utils.d.ts
|
||||
packages/tools/tool-utils.js
|
||||
packages/tools/tool-utils.js.map
|
||||
# AUTO-GENERATED - EXCLUDED TYPESCRIPT BUILD
|
||||
|
||||
33
.gitignore
vendored
33
.gitignore
vendored
@@ -99,9 +99,6 @@ packages/app-cli/tests/models_Note.js.map
|
||||
packages/app-cli/tests/models_Setting.d.ts
|
||||
packages/app-cli/tests/models_Setting.js
|
||||
packages/app-cli/tests/models_Setting.js.map
|
||||
packages/app-cli/tests/services/plugins/RepositoryApi.d.ts
|
||||
packages/app-cli/tests/services/plugins/RepositoryApi.js
|
||||
packages/app-cli/tests/services/plugins/RepositoryApi.js.map
|
||||
packages/app-cli/tests/services/plugins/api/JoplinSettings.d.ts
|
||||
packages/app-cli/tests/services/plugins/api/JoplinSettings.js
|
||||
packages/app-cli/tests/services/plugins/api/JoplinSettings.js.map
|
||||
@@ -1362,12 +1359,6 @@ packages/lib/uuid.js.map
|
||||
packages/lib/versionInfo.d.ts
|
||||
packages/lib/versionInfo.js
|
||||
packages/lib/versionInfo.js.map
|
||||
packages/plugin-repo-cli/dummy.test.d.ts
|
||||
packages/plugin-repo-cli/dummy.test.js
|
||||
packages/plugin-repo-cli/dummy.test.js.map
|
||||
packages/plugin-repo-cli/index.d.ts
|
||||
packages/plugin-repo-cli/index.js
|
||||
packages/plugin-repo-cli/index.js.map
|
||||
packages/plugins/ToggleSidebars/api/index.d.ts
|
||||
packages/plugins/ToggleSidebars/api/index.js
|
||||
packages/plugins/ToggleSidebars/api/index.js.map
|
||||
@@ -1458,6 +1449,21 @@ packages/renderer/utils.js.map
|
||||
packages/server/src/app.d.ts
|
||||
packages/server/src/app.js
|
||||
packages/server/src/app.js.map
|
||||
packages/server/src/config-base.d.ts
|
||||
packages/server/src/config-base.js
|
||||
packages/server/src/config-base.js.map
|
||||
packages/server/src/config-buildTypes.d.ts
|
||||
packages/server/src/config-buildTypes.js
|
||||
packages/server/src/config-buildTypes.js.map
|
||||
packages/server/src/config-dev.d.ts
|
||||
packages/server/src/config-dev.js
|
||||
packages/server/src/config-dev.js.map
|
||||
packages/server/src/config-prod.d.ts
|
||||
packages/server/src/config-prod.js
|
||||
packages/server/src/config-prod.js.map
|
||||
packages/server/src/config-tests.d.ts
|
||||
packages/server/src/config-tests.js
|
||||
packages/server/src/config-tests.js.map
|
||||
packages/server/src/config.d.ts
|
||||
packages/server/src/config.js
|
||||
packages/server/src/config.js.map
|
||||
@@ -1668,13 +1674,10 @@ packages/server/src/utils/urlUtils.js.map
|
||||
packages/server/src/utils/uuidgen.d.ts
|
||||
packages/server/src/utils/uuidgen.js
|
||||
packages/server/src/utils/uuidgen.js.map
|
||||
packages/tools/lerna-add.d.ts
|
||||
packages/tools/lerna-add.js
|
||||
packages/tools/lerna-add.js.map
|
||||
packages/tools/build-plugin-repository.d.ts
|
||||
packages/tools/build-plugin-repository.js
|
||||
packages/tools/build-plugin-repository.js.map
|
||||
packages/tools/release-server.d.ts
|
||||
packages/tools/release-server.js
|
||||
packages/tools/release-server.js.map
|
||||
packages/tools/tool-utils.d.ts
|
||||
packages/tools/tool-utils.js
|
||||
packages/tools/tool-utils.js.map
|
||||
# AUTO-GENERATED - EXCLUDED TYPESCRIPT BUILD
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
"buildApiDoc": "npm start --prefix=packages/app-cli -- apidoc ../../readme/api/references/rest_api.md",
|
||||
"buildDoc": "./packages/tools/build-all.sh",
|
||||
"buildPluginDoc": "typedoc --name 'Joplin Plugin API Documentation' --mode file -theme './Assets/PluginDocTheme/' --readme './Assets/PluginDocTheme/index.md' --excludeNotExported --excludeExternals --excludePrivate --excludeProtected --out docs/api/references/plugin_api packages/lib/services/plugins/api/",
|
||||
"buildPluginRepo": "node packages/tools/build-plugin-repository.js",
|
||||
"buildTranslations": "npm run tsc && node packages/tools/build-translation.js",
|
||||
"buildTranslationsNoTsc": "node packages/tools/build-translation.js",
|
||||
"buildWebsite": "npm run buildApiDoc && node ./packages/tools/build-website.js && npm run buildPluginDoc",
|
||||
@@ -25,7 +26,7 @@
|
||||
"linter-precommit": "./node_modules/.bin/eslint --resolve-plugins-relative-to . --fix --ext .js --ext .jsx --ext .ts --ext .tsx",
|
||||
"linter": "./node_modules/.bin/eslint --resolve-plugins-relative-to . --fix --quiet --ext .js --ext .jsx --ext .ts --ext .tsx",
|
||||
"postinstall": "npm run bootstrap --no-ci && npm run build",
|
||||
"publishAll": "git pull && npm run build && lerna version --yes --no-private --no-git-tag-version && gulp completePublishAll",
|
||||
"publishAll": "git pull && lerna version --yes --no-private --no-git-tag-version && gulp completePublishAll",
|
||||
"releaseAndroidClean": "node packages/tools/release-android.js",
|
||||
"releaseAndroid": "export PATH=\"/usr/local/opt/openjdk@11/bin:$PATH\" && node packages/tools/release-android.js",
|
||||
"releaseCli": "node packages/tools/release-cli.js",
|
||||
|
||||
@@ -1,8 +1,22 @@
|
||||
const gulp = require('gulp');
|
||||
const fs = require('fs-extra');
|
||||
const utils = require('@joplin/tools/gulp/utils');
|
||||
const { setPackagePrivateField } = require('@joplin/tools/tool-utils');
|
||||
const tasks = {
|
||||
// compileExtensions: {
|
||||
// fn: require('../Tools/gulp/tasks/compileExtensions.js'),
|
||||
// },
|
||||
// copyLib: require('../Tools/gulp/tasks/copyLib'),
|
||||
// tsc: require('../Tools/gulp/tasks/tsc'),
|
||||
// updateIgnoredTypeScriptBuild: require('../Tools/gulp/tasks/updateIgnoredTypeScriptBuild'),
|
||||
};
|
||||
|
||||
const tasks = {};
|
||||
// async function makePackagePublic(filePath) {
|
||||
// const text = await fs.readFile(filePath, 'utf8');
|
||||
// const obj = JSON.parse(text);
|
||||
// delete obj.private;
|
||||
// await fs.writeFile(filePath, JSON.stringify(obj), 'utf8');
|
||||
// }
|
||||
|
||||
tasks.prepareBuild = {
|
||||
fn: async () => {
|
||||
@@ -12,7 +26,8 @@ tasks.prepareBuild = {
|
||||
});
|
||||
|
||||
await utils.copyFile(`${__dirname}/package.json`, `${buildDir}/package.json`);
|
||||
await utils.setPackagePrivateField(`${buildDir}/package.json`, false);
|
||||
// await makePackagePublic(`${buildDir}/package.json`);
|
||||
await setPackagePrivateField(`${buildDir}/package.json`, false);
|
||||
|
||||
await utils.copyFile(`${__dirname}/package-lock.json`, `${buildDir}/package-lock.json`);
|
||||
await utils.copyFile(`${__dirname}/gulpfile.js`, `${buildDir}/gulpfile.js`);
|
||||
@@ -35,6 +50,14 @@ tasks.prepareTestBuild = {
|
||||
],
|
||||
});
|
||||
|
||||
// const rootDir = utils.rootDir();
|
||||
|
||||
// await utils.copyDir(`${rootDir}/packages/app-mobile/lib`, `${testBuildDir}/lib`, {
|
||||
// excluded: [
|
||||
// `${rootDir}/packages/renderer/node_modules`,
|
||||
// ],
|
||||
// });
|
||||
// await utils.copyDir(`${rootDir}/packages/app-mobile/locales`, `${testBuildDir}/locales`);
|
||||
await fs.mkdirp(`${testBuildDir}/data`);
|
||||
},
|
||||
};
|
||||
@@ -44,4 +67,12 @@ utils.registerGulpTasks(gulp, tasks);
|
||||
|
||||
gulp.task('build', gulp.series([
|
||||
'prepareBuild',
|
||||
// 'compileExtensions',
|
||||
// 'copyLib',
|
||||
]));
|
||||
|
||||
// gulp.task('buildTests', gulp.series([
|
||||
// // 'prepareTestBuild',
|
||||
// // 'compileExtensions',
|
||||
// // 'copyLib',
|
||||
// ]));
|
||||
|
||||
@@ -27,22 +27,17 @@ describe('InMemoryCache', function() {
|
||||
await time.msleep(510);
|
||||
expect(cache.value('test')).toBe(undefined);
|
||||
|
||||
// This test can sometimes fail in some cases, probably because it
|
||||
// sleeps for more than 100ms (when the computer is slow). Changing this
|
||||
// to use higher values would slow down the test unit too much, so let's
|
||||
// disable it for now.
|
||||
|
||||
// Check that the TTL is reset every time setValue is called
|
||||
// cache.setValue('test', 'something', 300);
|
||||
// await time.msleep(100);
|
||||
// cache.setValue('test', 'something', 300);
|
||||
// await time.msleep(100);
|
||||
// cache.setValue('test', 'something', 300);
|
||||
// await time.msleep(100);
|
||||
// cache.setValue('test', 'something', 300);
|
||||
// await time.msleep(100);
|
||||
cache.setValue('test', 'something', 300);
|
||||
await time.msleep(100);
|
||||
cache.setValue('test', 'something', 300);
|
||||
await time.msleep(100);
|
||||
cache.setValue('test', 'something', 300);
|
||||
await time.msleep(100);
|
||||
cache.setValue('test', 'something', 300);
|
||||
await time.msleep(100);
|
||||
|
||||
// expect(cache.value('test')).toBe('something');
|
||||
expect(cache.value('test')).toBe('something');
|
||||
});
|
||||
|
||||
it('should delete old records', async () => {
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
import RepositoryApi from '@joplin/lib/services/plugins/RepositoryApi';
|
||||
import shim from '@joplin/lib/shim';
|
||||
import { setupDatabaseAndSynchronizer, switchClient, supportDir, createTempDir } from '../../test-utils';
|
||||
|
||||
async function newRepoApi(): Promise<RepositoryApi> {
|
||||
const repo = new RepositoryApi(`${supportDir}/pluginRepo`, await createTempDir());
|
||||
await repo.loadManifests();
|
||||
return repo;
|
||||
}
|
||||
|
||||
describe('services_plugins_RepositoryApi', function() {
|
||||
|
||||
beforeEach(async (done: Function) => {
|
||||
await setupDatabaseAndSynchronizer(1);
|
||||
await switchClient(1);
|
||||
done();
|
||||
});
|
||||
|
||||
it('should get the manifests', (async () => {
|
||||
const api = await newRepoApi();
|
||||
const manifests = await api.manifests();
|
||||
expect(!!manifests.find(m => m.id === 'joplin.plugin.ambrt.backlinksToNote')).toBe(true);
|
||||
expect(!!manifests.find(m => m.id === 'org.joplinapp.plugins.ToggleSidebars')).toBe(true);
|
||||
}));
|
||||
|
||||
it('should search', (async () => {
|
||||
const api = await newRepoApi();
|
||||
|
||||
{
|
||||
const results = await api.search('to');
|
||||
expect(results.length).toBe(2);
|
||||
expect(!!results.find(m => m.id === 'joplin.plugin.ambrt.backlinksToNote')).toBe(true);
|
||||
expect(!!results.find(m => m.id === 'org.joplinapp.plugins.ToggleSidebars')).toBe(true);
|
||||
}
|
||||
|
||||
{
|
||||
const results = await api.search('backlink');
|
||||
expect(results.length).toBe(1);
|
||||
expect(!!results.find(m => m.id === 'joplin.plugin.ambrt.backlinksToNote')).toBe(true);
|
||||
}
|
||||
}));
|
||||
|
||||
it('should download a plugin', (async () => {
|
||||
const api = await newRepoApi();
|
||||
const pluginPath = await api.downloadPlugin('org.joplinapp.plugins.ToggleSidebars');
|
||||
expect(await shim.fsDriver().exists(pluginPath)).toBe(true);
|
||||
}));
|
||||
|
||||
it('should tell if a plugin can be updated', (async () => {
|
||||
const api = await newRepoApi();
|
||||
expect(await api.pluginCanBeUpdated('org.joplinapp.plugins.ToggleSidebars', '1.0.0')).toBe(true);
|
||||
expect(await api.pluginCanBeUpdated('org.joplinapp.plugins.ToggleSidebars', '1.0.2')).toBe(false);
|
||||
expect(await api.pluginCanBeUpdated('does.not.exist', '1.0.0')).toBe(false);
|
||||
}));
|
||||
|
||||
});
|
||||
@@ -1,25 +0,0 @@
|
||||
# Joplin Plugin Repository
|
||||
|
||||
This is the official Joplin Plugin Repository
|
||||
|
||||
## Installation
|
||||
|
||||
To install any of these plugins, open the desktop application, then go to the "Plugins" section in the Configuration screen. You can then search for any plugin and install it from there.
|
||||
|
||||
## Plugins
|
||||
|
||||
This repository contains the following plugins:
|
||||
|
||||
<!-- PLUGIN_LIST -->
|
||||
| Name | Version | Description | Author
|
||||
--- | --- | --- | --- | ---
|
||||
[🏠](https://discourse.joplinapp.org/t/insert-referencing-notes-backlinks-plugin/13632) | Backlinks to note | 1.0.4 | Creates backlinks to opened note | a
|
||||
[🏠](https://github.com/JackGruber/joplin-plugin-combine-notes) | Combine notes | 0.2.1 | Combine one or more notes | JackGruber
|
||||
[🏠](https://github.com/JackGruber/joplin-plugin-copytags) | Copy Tags | 0.3.2 | Plugin to extend the Joplin tagging menu with a coppy all tags and tagging list with more control. | JackGruber
|
||||
[🏠](https://discourse.joplinapp.org/t/go-to-note-tag-or-notebook-via-highlighting-text-in-editor/12731) | Create and go to #tags and @notebooks | 1.3.4 | Go to tag,notebook or note via links or via text | a
|
||||
[🏠](https://github.com/benji300/joplin-favorites) | Favorites | 1.0.0 | Save any notebook, note, to-do, tag, or search as favorite in an extra panel view for quick access. (v1.0.0) | Benji300
|
||||
[🏠](https://github.com/laurent22/joplin/tree/dev/packages/plugins/ToggleSidebars) | Note list and side bar toggle buttons | 1.0.2 | Adds buttons to toggle note list and sidebar | Laurent Cozic
|
||||
[🏠](https://github.com/JackGruber/joplin-plugin-note-overview) | Note overview | 1.0.0 | A note overview is created based on the defined search and the specified fields | JackGruber
|
||||
[🏠](https://github.com/benji300/joplin-note-tabs) | Note Tabs | 1.1.1 | Allows to open several notes at once in tabs and pin them. (v1.1.1) | Benji300
|
||||
[🏠](https://github.com/JackGruber/joplin-plugin-backup) | Simple Backup | 0.3.0 | Plugin to create manual and automatic backups | JackGruber
|
||||
<!-- PLUGIN_LIST -->
|
||||
@@ -1,29 +0,0 @@
|
||||
{
|
||||
"joplin.plugin.ambrt.backlinksToNote": {
|
||||
"manifest_version": 1,
|
||||
"id": "joplin.plugin.ambrt.backlinksToNote",
|
||||
"app_min_version": "1.5",
|
||||
"version": "1.0.4",
|
||||
"name": "Backlinks to note",
|
||||
"description": "Creates backlinks to opened note",
|
||||
"author": "a",
|
||||
"homepage_url": "https://discourse.joplinapp.org/t/insert-referencing-notes-backlinks-plugin/13632",
|
||||
"_publish_hash": "sha256:ab9c9bc776e167a3b1a9ec40a4927d93da14514c0508f46dd6e5ea3f8a3a6c3b",
|
||||
"_publish_commit": "master:5b74f93c687463572c46200292fa911e0ba96033",
|
||||
"_npm_package_name": "joplin-plugin-backlinks"
|
||||
},
|
||||
"org.joplinapp.plugins.ToggleSidebars": {
|
||||
"manifest_version": 1,
|
||||
"id": "org.joplinapp.plugins.ToggleSidebars",
|
||||
"app_min_version": "1.6",
|
||||
"version": "1.0.2",
|
||||
"name": "Note list and side bar toggle buttons",
|
||||
"description": "Adds buttons to toggle note list and sidebar",
|
||||
"author": "Laurent Cozic",
|
||||
"homepage_url": "https://github.com/laurent22/joplin/tree/dev/packages/plugins/ToggleSidebars",
|
||||
"repository_url": "https://github.com/laurent22/joplin/tree/dev/packages/plugins/ToggleSidebars",
|
||||
"_publish_hash": "sha256:e0d833b7ef1bb8f02ee4cb861ef1989621358c45a5614911071302dc0527a3b4",
|
||||
"_publish_commit": "dev:1b5b2342fc25717b77ad9f1627c1a334e5bbae54",
|
||||
"_npm_package_name": "@joplin/joplin-plugin-toggle-sidebars"
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"manifest_version": 1,
|
||||
"id": "joplin.plugin.ambrt.backlinksToNote",
|
||||
"app_min_version": "1.5",
|
||||
"version": "1.0.4",
|
||||
"name": "Backlinks to note",
|
||||
"description": "Creates backlinks to opened note",
|
||||
"author": "a",
|
||||
"homepage_url": "https://discourse.joplinapp.org/t/insert-referencing-notes-backlinks-plugin/13632",
|
||||
"_publish_hash": "sha256:ab9c9bc776e167a3b1a9ec40a4927d93da14514c0508f46dd6e5ea3f8a3a6c3b",
|
||||
"_publish_commit": "master:5b74f93c687463572c46200292fa911e0ba96033",
|
||||
"_npm_package_name": "joplin-plugin-backlinks"
|
||||
}
|
||||
Binary file not shown.
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"manifest_version": 1,
|
||||
"id": "org.joplinapp.plugins.ToggleSidebars",
|
||||
"app_min_version": "1.6",
|
||||
"version": "1.0.2",
|
||||
"name": "Note list and side bar toggle buttons",
|
||||
"description": "Adds buttons to toggle note list and sidebar",
|
||||
"author": "Laurent Cozic",
|
||||
"homepage_url": "https://github.com/laurent22/joplin/tree/dev/packages/plugins/ToggleSidebars",
|
||||
"repository_url": "https://github.com/laurent22/joplin/tree/dev/packages/plugins/ToggleSidebars",
|
||||
"_publish_hash": "sha256:e0d833b7ef1bb8f02ee4cb861ef1989621358c45a5614911071302dc0527a3b4",
|
||||
"_publish_commit": "dev:1b5b2342fc25717b77ad9f1627c1a334e5bbae54",
|
||||
"_npm_package_name": "@joplin/joplin-plugin-toggle-sidebars"
|
||||
}
|
||||
Binary file not shown.
@@ -233,7 +233,7 @@ function main(processArgv) {
|
||||
const configs = {
|
||||
// Builds the main src/index.ts and copy the extra content from /src to
|
||||
// /dist including scripts, CSS and any other asset.
|
||||
buildMain: [pluginConfig],
|
||||
buildMain: pluginConfig,
|
||||
|
||||
// Builds the extra scripts as defined in plugin.config.json. When doing
|
||||
// so, some JavaScript files that were copied in the previous might be
|
||||
@@ -247,7 +247,7 @@ function main(processArgv) {
|
||||
// run without this. So we give it an entry that we know is going to
|
||||
// exist and output in the publish dir. Then the plugin will delete this
|
||||
// temporary file before packaging the plugin.
|
||||
createArchive: [createArchiveConfig],
|
||||
createArchive: createArchiveConfig,
|
||||
};
|
||||
|
||||
// If we are running the first config step, we clean up and create the build
|
||||
@@ -270,10 +270,4 @@ try {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!exportedConfigs.length) {
|
||||
// Nothing to do - for example where there are no external scripts to
|
||||
// compile.
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
module.exports = exportedConfigs;
|
||||
|
||||
@@ -233,7 +233,7 @@ function main(processArgv) {
|
||||
const configs = {
|
||||
// Builds the main src/index.ts and copy the extra content from /src to
|
||||
// /dist including scripts, CSS and any other asset.
|
||||
buildMain: [pluginConfig],
|
||||
buildMain: pluginConfig,
|
||||
|
||||
// Builds the extra scripts as defined in plugin.config.json. When doing
|
||||
// so, some JavaScript files that were copied in the previous might be
|
||||
@@ -247,7 +247,7 @@ function main(processArgv) {
|
||||
// run without this. So we give it an entry that we know is going to
|
||||
// exist and output in the publish dir. Then the plugin will delete this
|
||||
// temporary file before packaging the plugin.
|
||||
createArchive: [createArchiveConfig],
|
||||
createArchive: createArchiveConfig,
|
||||
};
|
||||
|
||||
// If we are running the first config step, we clean up and create the build
|
||||
@@ -270,10 +270,4 @@ try {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!exportedConfigs.length) {
|
||||
// Nothing to do - for example where there are no external scripts to
|
||||
// compile.
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
module.exports = exportedConfigs;
|
||||
|
||||
@@ -233,7 +233,7 @@ function main(processArgv) {
|
||||
const configs = {
|
||||
// Builds the main src/index.ts and copy the extra content from /src to
|
||||
// /dist including scripts, CSS and any other asset.
|
||||
buildMain: [pluginConfig],
|
||||
buildMain: pluginConfig,
|
||||
|
||||
// Builds the extra scripts as defined in plugin.config.json. When doing
|
||||
// so, some JavaScript files that were copied in the previous might be
|
||||
@@ -247,7 +247,7 @@ function main(processArgv) {
|
||||
// run without this. So we give it an entry that we know is going to
|
||||
// exist and output in the publish dir. Then the plugin will delete this
|
||||
// temporary file before packaging the plugin.
|
||||
createArchive: [createArchiveConfig],
|
||||
createArchive: createArchiveConfig,
|
||||
};
|
||||
|
||||
// If we are running the first config step, we clean up and create the build
|
||||
@@ -270,10 +270,4 @@ try {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!exportedConfigs.length) {
|
||||
// Nothing to do - for example where there are no external scripts to
|
||||
// compile.
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
module.exports = exportedConfigs;
|
||||
|
||||
@@ -233,7 +233,7 @@ function main(processArgv) {
|
||||
const configs = {
|
||||
// Builds the main src/index.ts and copy the extra content from /src to
|
||||
// /dist including scripts, CSS and any other asset.
|
||||
buildMain: [pluginConfig],
|
||||
buildMain: pluginConfig,
|
||||
|
||||
// Builds the extra scripts as defined in plugin.config.json. When doing
|
||||
// so, some JavaScript files that were copied in the previous might be
|
||||
@@ -247,7 +247,7 @@ function main(processArgv) {
|
||||
// run without this. So we give it an entry that we know is going to
|
||||
// exist and output in the publish dir. Then the plugin will delete this
|
||||
// temporary file before packaging the plugin.
|
||||
createArchive: [createArchiveConfig],
|
||||
createArchive: createArchiveConfig,
|
||||
};
|
||||
|
||||
// If we are running the first config step, we clean up and create the build
|
||||
@@ -270,10 +270,4 @@ try {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!exportedConfigs.length) {
|
||||
// Nothing to do - for example where there are no external scripts to
|
||||
// compile.
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
module.exports = exportedConfigs;
|
||||
|
||||
@@ -233,7 +233,7 @@ function main(processArgv) {
|
||||
const configs = {
|
||||
// Builds the main src/index.ts and copy the extra content from /src to
|
||||
// /dist including scripts, CSS and any other asset.
|
||||
buildMain: [pluginConfig],
|
||||
buildMain: pluginConfig,
|
||||
|
||||
// Builds the extra scripts as defined in plugin.config.json. When doing
|
||||
// so, some JavaScript files that were copied in the previous might be
|
||||
@@ -247,7 +247,7 @@ function main(processArgv) {
|
||||
// run without this. So we give it an entry that we know is going to
|
||||
// exist and output in the publish dir. Then the plugin will delete this
|
||||
// temporary file before packaging the plugin.
|
||||
createArchive: [createArchiveConfig],
|
||||
createArchive: createArchiveConfig,
|
||||
};
|
||||
|
||||
// If we are running the first config step, we clean up and create the build
|
||||
@@ -270,10 +270,4 @@ try {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!exportedConfigs.length) {
|
||||
// Nothing to do - for example where there are no external scripts to
|
||||
// compile.
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
module.exports = exportedConfigs;
|
||||
|
||||
@@ -233,7 +233,7 @@ function main(processArgv) {
|
||||
const configs = {
|
||||
// Builds the main src/index.ts and copy the extra content from /src to
|
||||
// /dist including scripts, CSS and any other asset.
|
||||
buildMain: [pluginConfig],
|
||||
buildMain: pluginConfig,
|
||||
|
||||
// Builds the extra scripts as defined in plugin.config.json. When doing
|
||||
// so, some JavaScript files that were copied in the previous might be
|
||||
@@ -247,7 +247,7 @@ function main(processArgv) {
|
||||
// run without this. So we give it an entry that we know is going to
|
||||
// exist and output in the publish dir. Then the plugin will delete this
|
||||
// temporary file before packaging the plugin.
|
||||
createArchive: [createArchiveConfig],
|
||||
createArchive: createArchiveConfig,
|
||||
};
|
||||
|
||||
// If we are running the first config step, we clean up and create the build
|
||||
@@ -270,10 +270,4 @@ try {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!exportedConfigs.length) {
|
||||
// Nothing to do - for example where there are no external scripts to
|
||||
// compile.
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
module.exports = exportedConfigs;
|
||||
|
||||
@@ -233,7 +233,7 @@ function main(processArgv) {
|
||||
const configs = {
|
||||
// Builds the main src/index.ts and copy the extra content from /src to
|
||||
// /dist including scripts, CSS and any other asset.
|
||||
buildMain: [pluginConfig],
|
||||
buildMain: pluginConfig,
|
||||
|
||||
// Builds the extra scripts as defined in plugin.config.json. When doing
|
||||
// so, some JavaScript files that were copied in the previous might be
|
||||
@@ -247,7 +247,7 @@ function main(processArgv) {
|
||||
// run without this. So we give it an entry that we know is going to
|
||||
// exist and output in the publish dir. Then the plugin will delete this
|
||||
// temporary file before packaging the plugin.
|
||||
createArchive: [createArchiveConfig],
|
||||
createArchive: createArchiveConfig,
|
||||
};
|
||||
|
||||
// If we are running the first config step, we clean up and create the build
|
||||
@@ -270,10 +270,4 @@ try {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!exportedConfigs.length) {
|
||||
// Nothing to do - for example where there are no external scripts to
|
||||
// compile.
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
module.exports = exportedConfigs;
|
||||
|
||||
@@ -233,7 +233,7 @@ function main(processArgv) {
|
||||
const configs = {
|
||||
// Builds the main src/index.ts and copy the extra content from /src to
|
||||
// /dist including scripts, CSS and any other asset.
|
||||
buildMain: [pluginConfig],
|
||||
buildMain: pluginConfig,
|
||||
|
||||
// Builds the extra scripts as defined in plugin.config.json. When doing
|
||||
// so, some JavaScript files that were copied in the previous might be
|
||||
@@ -247,7 +247,7 @@ function main(processArgv) {
|
||||
// run without this. So we give it an entry that we know is going to
|
||||
// exist and output in the publish dir. Then the plugin will delete this
|
||||
// temporary file before packaging the plugin.
|
||||
createArchive: [createArchiveConfig],
|
||||
createArchive: createArchiveConfig,
|
||||
};
|
||||
|
||||
// If we are running the first config step, we clean up and create the build
|
||||
@@ -270,10 +270,4 @@ try {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!exportedConfigs.length) {
|
||||
// Nothing to do - for example where there are no external scripts to
|
||||
// compile.
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
module.exports = exportedConfigs;
|
||||
|
||||
@@ -233,7 +233,7 @@ function main(processArgv) {
|
||||
const configs = {
|
||||
// Builds the main src/index.ts and copy the extra content from /src to
|
||||
// /dist including scripts, CSS and any other asset.
|
||||
buildMain: [pluginConfig],
|
||||
buildMain: pluginConfig,
|
||||
|
||||
// Builds the extra scripts as defined in plugin.config.json. When doing
|
||||
// so, some JavaScript files that were copied in the previous might be
|
||||
@@ -247,7 +247,7 @@ function main(processArgv) {
|
||||
// run without this. So we give it an entry that we know is going to
|
||||
// exist and output in the publish dir. Then the plugin will delete this
|
||||
// temporary file before packaging the plugin.
|
||||
createArchive: [createArchiveConfig],
|
||||
createArchive: createArchiveConfig,
|
||||
};
|
||||
|
||||
// If we are running the first config step, we clean up and create the build
|
||||
@@ -270,10 +270,4 @@ try {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!exportedConfigs.length) {
|
||||
// Nothing to do - for example where there are no external scripts to
|
||||
// compile.
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
module.exports = exportedConfigs;
|
||||
|
||||
@@ -233,7 +233,7 @@ function main(processArgv) {
|
||||
const configs = {
|
||||
// Builds the main src/index.ts and copy the extra content from /src to
|
||||
// /dist including scripts, CSS and any other asset.
|
||||
buildMain: [pluginConfig],
|
||||
buildMain: pluginConfig,
|
||||
|
||||
// Builds the extra scripts as defined in plugin.config.json. When doing
|
||||
// so, some JavaScript files that were copied in the previous might be
|
||||
@@ -247,7 +247,7 @@ function main(processArgv) {
|
||||
// run without this. So we give it an entry that we know is going to
|
||||
// exist and output in the publish dir. Then the plugin will delete this
|
||||
// temporary file before packaging the plugin.
|
||||
createArchive: [createArchiveConfig],
|
||||
createArchive: createArchiveConfig,
|
||||
};
|
||||
|
||||
// If we are running the first config step, we clean up and create the build
|
||||
@@ -270,10 +270,4 @@ try {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!exportedConfigs.length) {
|
||||
// Nothing to do - for example where there are no external scripts to
|
||||
// compile.
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
module.exports = exportedConfigs;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"app_min_version": "1.4",
|
||||
"name": "Register Command Test",
|
||||
"description": "To test registering commands",
|
||||
"version": "1.0.3",
|
||||
"version": "1.0.0",
|
||||
"author": "Laurent Cozic",
|
||||
"homepage_url": "https://joplinapp.org"
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# - Update src/manifest.json with the new version number
|
||||
# - Run the below command
|
||||
# - Then the file /manifests.json also needs to be updated with the new manifest file
|
||||
|
||||
npm run dist && cp publish/org.joplinapp.plugins.RegisterCommandDemo.jpl ~/src/joplin-plugins-test/plugins/org.joplinapp.plugins.RegisterCommandDemo/plugin.jpl && cp publish/org.joplinapp.plugins.RegisterCommandDemo.json ~/src/joplin-plugins-test/plugins/org.joplinapp.plugins.RegisterCommandDemo/plugin.json
|
||||
@@ -233,7 +233,7 @@ function main(processArgv) {
|
||||
const configs = {
|
||||
// Builds the main src/index.ts and copy the extra content from /src to
|
||||
// /dist including scripts, CSS and any other asset.
|
||||
buildMain: [pluginConfig],
|
||||
buildMain: pluginConfig,
|
||||
|
||||
// Builds the extra scripts as defined in plugin.config.json. When doing
|
||||
// so, some JavaScript files that were copied in the previous might be
|
||||
@@ -247,7 +247,7 @@ function main(processArgv) {
|
||||
// run without this. So we give it an entry that we know is going to
|
||||
// exist and output in the publish dir. Then the plugin will delete this
|
||||
// temporary file before packaging the plugin.
|
||||
createArchive: [createArchiveConfig],
|
||||
createArchive: createArchiveConfig,
|
||||
};
|
||||
|
||||
// If we are running the first config step, we clean up and create the build
|
||||
@@ -270,10 +270,4 @@ try {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!exportedConfigs.length) {
|
||||
// Nothing to do - for example where there are no external scripts to
|
||||
// compile.
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
module.exports = exportedConfigs;
|
||||
|
||||
@@ -233,7 +233,7 @@ function main(processArgv) {
|
||||
const configs = {
|
||||
// Builds the main src/index.ts and copy the extra content from /src to
|
||||
// /dist including scripts, CSS and any other asset.
|
||||
buildMain: [pluginConfig],
|
||||
buildMain: pluginConfig,
|
||||
|
||||
// Builds the extra scripts as defined in plugin.config.json. When doing
|
||||
// so, some JavaScript files that were copied in the previous might be
|
||||
@@ -247,7 +247,7 @@ function main(processArgv) {
|
||||
// run without this. So we give it an entry that we know is going to
|
||||
// exist and output in the publish dir. Then the plugin will delete this
|
||||
// temporary file before packaging the plugin.
|
||||
createArchive: [createArchiveConfig],
|
||||
createArchive: createArchiveConfig,
|
||||
};
|
||||
|
||||
// If we are running the first config step, we clean up and create the build
|
||||
@@ -270,10 +270,4 @@ try {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!exportedConfigs.length) {
|
||||
// Nothing to do - for example where there are no external scripts to
|
||||
// compile.
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
module.exports = exportedConfigs;
|
||||
|
||||
@@ -233,7 +233,7 @@ function main(processArgv) {
|
||||
const configs = {
|
||||
// Builds the main src/index.ts and copy the extra content from /src to
|
||||
// /dist including scripts, CSS and any other asset.
|
||||
buildMain: [pluginConfig],
|
||||
buildMain: pluginConfig,
|
||||
|
||||
// Builds the extra scripts as defined in plugin.config.json. When doing
|
||||
// so, some JavaScript files that were copied in the previous might be
|
||||
@@ -247,7 +247,7 @@ function main(processArgv) {
|
||||
// run without this. So we give it an entry that we know is going to
|
||||
// exist and output in the publish dir. Then the plugin will delete this
|
||||
// temporary file before packaging the plugin.
|
||||
createArchive: [createArchiveConfig],
|
||||
createArchive: createArchiveConfig,
|
||||
};
|
||||
|
||||
// If we are running the first config step, we clean up and create the build
|
||||
@@ -270,10 +270,4 @@ try {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!exportedConfigs.length) {
|
||||
// Nothing to do - for example where there are no external scripts to
|
||||
// compile.
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
module.exports = exportedConfigs;
|
||||
|
||||
@@ -233,7 +233,7 @@ function main(processArgv) {
|
||||
const configs = {
|
||||
// Builds the main src/index.ts and copy the extra content from /src to
|
||||
// /dist including scripts, CSS and any other asset.
|
||||
buildMain: [pluginConfig],
|
||||
buildMain: pluginConfig,
|
||||
|
||||
// Builds the extra scripts as defined in plugin.config.json. When doing
|
||||
// so, some JavaScript files that were copied in the previous might be
|
||||
@@ -247,7 +247,7 @@ function main(processArgv) {
|
||||
// run without this. So we give it an entry that we know is going to
|
||||
// exist and output in the publish dir. Then the plugin will delete this
|
||||
// temporary file before packaging the plugin.
|
||||
createArchive: [createArchiveConfig],
|
||||
createArchive: createArchiveConfig,
|
||||
};
|
||||
|
||||
// If we are running the first config step, we clean up and create the build
|
||||
@@ -270,10 +270,4 @@ try {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!exportedConfigs.length) {
|
||||
// Nothing to do - for example where there are no external scripts to
|
||||
// compile.
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
module.exports = exportedConfigs;
|
||||
|
||||
@@ -233,7 +233,7 @@ function main(processArgv) {
|
||||
const configs = {
|
||||
// Builds the main src/index.ts and copy the extra content from /src to
|
||||
// /dist including scripts, CSS and any other asset.
|
||||
buildMain: [pluginConfig],
|
||||
buildMain: pluginConfig,
|
||||
|
||||
// Builds the extra scripts as defined in plugin.config.json. When doing
|
||||
// so, some JavaScript files that were copied in the previous might be
|
||||
@@ -247,7 +247,7 @@ function main(processArgv) {
|
||||
// run without this. So we give it an entry that we know is going to
|
||||
// exist and output in the publish dir. Then the plugin will delete this
|
||||
// temporary file before packaging the plugin.
|
||||
createArchive: [createArchiveConfig],
|
||||
createArchive: createArchiveConfig,
|
||||
};
|
||||
|
||||
// If we are running the first config step, we clean up and create the build
|
||||
@@ -270,10 +270,4 @@ try {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!exportedConfigs.length) {
|
||||
// Nothing to do - for example where there are no external scripts to
|
||||
// compile.
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
module.exports = exportedConfigs;
|
||||
|
||||
@@ -104,7 +104,6 @@ FileApiDriverLocal.fsDriver_ = fsDriver;
|
||||
|
||||
const logDir = `${__dirname}/../tests/logs`;
|
||||
const baseTempDir = `${__dirname}/../tests/tmp/${suiteName_}`;
|
||||
const supportDir = `${__dirname}/support`;
|
||||
|
||||
// We add a space in the data directory path as that will help uncover
|
||||
// various space-in-path issues.
|
||||
@@ -181,7 +180,6 @@ BaseItem.loadClass('Revision', Revision);
|
||||
Setting.setConstant('appId', 'net.cozic.joplintest-cli');
|
||||
Setting.setConstant('appType', 'cli');
|
||||
Setting.setConstant('tempDir', baseTempDir);
|
||||
Setting.setConstant('cacheDir', baseTempDir);
|
||||
Setting.setConstant('env', 'dev');
|
||||
|
||||
BaseService.logger_ = logger;
|
||||
@@ -866,4 +864,4 @@ class TestApp extends BaseApplication {
|
||||
}
|
||||
}
|
||||
|
||||
export { supportDir, waitForFolderCount, afterAllCleanUp, exportDir, newPluginService, newPluginScript, synchronizerStart, afterEachCleanUp, syncTargetName, setSyncTargetName, syncDir, createTempDir, isNetworkSyncTarget, kvStore, expectThrow, logger, expectNotThrow, resourceService, resourceFetcher, tempFilePath, allSyncTargetItemsEncrypted, msleep, setupDatabase, revisionService, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync, checkThrow, encryptionService, loadEncryptionMasterKey, fileContentEqual, decryptionWorker, currentClientId, id, ids, sortedIds, at, createNTestNotes, createNTestFolders, createNTestTags, TestApp };
|
||||
module.exports = { waitForFolderCount, afterAllCleanUp, exportDir, newPluginService, newPluginScript, synchronizerStart, afterEachCleanUp, syncTargetName, setSyncTargetName, syncDir, createTempDir, isNetworkSyncTarget, kvStore, expectThrow, logger, expectNotThrow, resourceService, resourceFetcher, tempFilePath, allSyncTargetItemsEncrypted, msleep, setupDatabase, revisionService, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync, checkThrow, encryptionService, loadEncryptionMasterKey, fileContentEqual, decryptionWorker, currentClientId, id, ids, sortedIds, at, createNTestNotes, createNTestFolders, createNTestTags, TestApp };
|
||||
|
||||
@@ -78,7 +78,7 @@ const commands = [
|
||||
require('./gui/NoteEditor/commands/showRevisions'),
|
||||
require('./gui/NoteList/commands/focusElementNoteList'),
|
||||
require('./gui/NoteListControls/commands/focusSearch'),
|
||||
require('./gui/Sidebar/commands/focusElementSideBar'),
|
||||
require('./gui/SideBar/commands/focusElementSideBar'),
|
||||
];
|
||||
|
||||
// Commands that are not tied to any particular component.
|
||||
@@ -527,7 +527,7 @@ class Application extends BaseApplication {
|
||||
// time, however we only effectively uninstall the plugin the next
|
||||
// time the app is started. What plugin should be uninstalled is
|
||||
// stored in the settings.
|
||||
const newSettings = service.clearUpdateState(await service.uninstallPlugins(pluginSettings));
|
||||
const newSettings = await service.uninstallPlugins(pluginSettings);
|
||||
Setting.setValue('plugins.states', newSettings);
|
||||
|
||||
try {
|
||||
|
||||
@@ -7,7 +7,6 @@ export enum ButtonLevel {
|
||||
Secondary = 'secondary',
|
||||
Tertiary = 'tertiary',
|
||||
SidebarSecondary = 'sidebarSecondary',
|
||||
Recommended = 'recommended',
|
||||
}
|
||||
|
||||
interface Props {
|
||||
@@ -122,20 +121,6 @@ const StyledButtonTertiary = styled(StyledButtonBase)`
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledButtonRecommended = styled(StyledButtonBase)`
|
||||
border: 1px solid ${(props: any) => props.theme.borderColor4};
|
||||
background-color: ${(props: any) => props.theme.warningBackgroundColor};
|
||||
|
||||
${StyledIcon} {
|
||||
color: ${(props: any) => props.theme.color};
|
||||
}
|
||||
|
||||
${StyledTitle} {
|
||||
color: ${(props: any) => props.theme.color};
|
||||
opacity: 0.9;
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledButtonSidebarSecondary = styled(StyledButtonBase)`
|
||||
background: none;
|
||||
border-color: ${(props: any) => props.theme.color2};
|
||||
@@ -182,11 +167,10 @@ function buttonClass(level: ButtonLevel) {
|
||||
if (level === ButtonLevel.Primary) return StyledButtonPrimary;
|
||||
if (level === ButtonLevel.Tertiary) return StyledButtonTertiary;
|
||||
if (level === ButtonLevel.SidebarSecondary) return StyledButtonSidebarSecondary;
|
||||
if (level === ButtonLevel.Recommended) return StyledButtonRecommended;
|
||||
return StyledButtonSecondary;
|
||||
}
|
||||
|
||||
function Button(props: Props) {
|
||||
export default function Button(props: Props) {
|
||||
const iconOnly = props.iconName && !props.title;
|
||||
|
||||
const StyledButton = buttonClass(props.level);
|
||||
@@ -213,5 +197,3 @@ function Button(props: Props) {
|
||||
</StyledButton>
|
||||
);
|
||||
}
|
||||
|
||||
export default styled(Button)`${space}`;
|
||||
|
||||
@@ -148,7 +148,6 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
|
||||
const createSettingComponents = (advanced: boolean) => {
|
||||
const output = [];
|
||||
|
||||
for (let i = 0; i < section.metadatas.length; i++) {
|
||||
const md = section.metadatas[i];
|
||||
if (!!md.advanced !== advanced) continue;
|
||||
@@ -161,8 +160,8 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
const settingComps = createSettingComponents(false);
|
||||
const advancedSettingComps = createSettingComponents(true);
|
||||
|
||||
const sectionWidths: Record<string, any> = {
|
||||
plugins: '100%',
|
||||
const sectionWidths: Record<string, number> = {
|
||||
plugins: 900,
|
||||
};
|
||||
|
||||
const sectionStyle: any = {
|
||||
@@ -306,7 +305,7 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
);
|
||||
}
|
||||
|
||||
private renderHeader(themeId: number, label: string, style: any = null) {
|
||||
private renderHeader(themeId: number, label: string) {
|
||||
const theme = themeStyle(themeId);
|
||||
|
||||
const labelStyle = Object.assign({}, theme.textStyle, {
|
||||
@@ -315,7 +314,6 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
fontSize: theme.fontSize * 1.25,
|
||||
fontWeight: 500,
|
||||
marginBottom: theme.mainPadding,
|
||||
...style,
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -459,7 +457,7 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
// There's probably a better way to do this but can't figure it out.
|
||||
|
||||
return (
|
||||
<div key={key + (`${value}`).toString()} style={rowStyle}>
|
||||
<div key={key + value.toString()} style={rowStyle}>
|
||||
<div style={{ ...controlStyle, backgroundColor: 'transparent', display: 'flex', alignItems: 'center' }}>
|
||||
<input
|
||||
id={`setting_checkbox_${key}`}
|
||||
@@ -566,7 +564,7 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
value={cmd[1]}
|
||||
spellCheck={false}
|
||||
/>
|
||||
<div style={{ width: inputStyle.width, minWidth: inputStyle.minWidth }}>
|
||||
<div style={{ width: inputStyle.width }}>
|
||||
{descriptionComp}
|
||||
</div>
|
||||
</div>
|
||||
@@ -595,7 +593,7 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
}}
|
||||
spellCheck={false}
|
||||
/>
|
||||
<div style={{ width: inputStyle.width, minWidth: inputStyle.minWidth }}>
|
||||
<div style={{ width: inputStyle.width }}>
|
||||
{descriptionComp}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -11,47 +11,34 @@ export enum InstallState {
|
||||
Installed = 3,
|
||||
}
|
||||
|
||||
export enum UpdateState {
|
||||
Idle = 1,
|
||||
CanUpdate = 2,
|
||||
Updating = 3,
|
||||
HasBeenUpdated = 4,
|
||||
}
|
||||
|
||||
interface Props {
|
||||
item?: PluginItem;
|
||||
manifest?: PluginManifest;
|
||||
installState?: InstallState;
|
||||
updateState?: UpdateState;
|
||||
themeId: number;
|
||||
onToggle?: Function;
|
||||
onDelete?: Function;
|
||||
onInstall?: Function;
|
||||
onUpdate?: Function;
|
||||
}
|
||||
|
||||
function manifestToItem(manifest: PluginManifest): PluginItem {
|
||||
return {
|
||||
id: manifest.id,
|
||||
name: manifest.name,
|
||||
version: manifest.version,
|
||||
description: manifest.description,
|
||||
enabled: true,
|
||||
deleted: false,
|
||||
devMode: false,
|
||||
hasBeenUpdated: false,
|
||||
};
|
||||
}
|
||||
|
||||
export interface PluginItem {
|
||||
id: string;
|
||||
name: string;
|
||||
version: string;
|
||||
description: string;
|
||||
enabled: boolean;
|
||||
deleted: boolean;
|
||||
devMode: boolean;
|
||||
hasBeenUpdated: boolean;
|
||||
}
|
||||
|
||||
const CellRoot = styled.div`
|
||||
@@ -63,7 +50,7 @@ const CellRoot = styled.div`
|
||||
padding: 15px;
|
||||
border: 1px solid ${props => props.theme.dividerColor};
|
||||
border-radius: 6px;
|
||||
width: 320px;
|
||||
width: 250px;
|
||||
margin-right: 20px;
|
||||
margin-bottom: 20px;
|
||||
box-shadow: 1px 1px 3px rgba(0,0,0,0.2);
|
||||
@@ -103,12 +90,6 @@ const StyledName = styled.div`
|
||||
flex: 1;
|
||||
`;
|
||||
|
||||
const StyledVersion = styled.span`
|
||||
margin-left: 5px;
|
||||
color: ${props => props.theme.colorFaded};
|
||||
font-size: ${props => props.theme.fontSize * 0.9}px;
|
||||
`;
|
||||
|
||||
const StyledDescription = styled.div`
|
||||
font-family: ${props => props.theme.fontFamily};
|
||||
color: ${props => props.theme.colorFaded};
|
||||
@@ -157,23 +138,6 @@ export default function(props: Props) {
|
||||
/>;
|
||||
}
|
||||
|
||||
function renderUpdateButton() {
|
||||
if (!props.onUpdate) return null;
|
||||
|
||||
let title = _('Update');
|
||||
if (props.updateState === UpdateState.Updating) title = _('Updating...');
|
||||
if (props.updateState === UpdateState.Idle) title = _('Updated');
|
||||
if (props.updateState === UpdateState.HasBeenUpdated) title = _('Updated');
|
||||
|
||||
return <Button
|
||||
ml={1}
|
||||
level={ButtonLevel.Recommended}
|
||||
onClick={() => props.onUpdate({ item })}
|
||||
title={title}
|
||||
disabled={props.updateState === UpdateState.HasBeenUpdated}
|
||||
/>;
|
||||
}
|
||||
|
||||
function renderFooter() {
|
||||
if (item.devMode) return null;
|
||||
|
||||
@@ -181,7 +145,6 @@ export default function(props: Props) {
|
||||
<CellFooter>
|
||||
{renderDeleteButton()}
|
||||
{renderInstallButton()}
|
||||
{renderUpdateButton()}
|
||||
<div style={{ display: 'flex', flex: 1 }}/>
|
||||
</CellFooter>
|
||||
);
|
||||
@@ -190,7 +153,7 @@ export default function(props: Props) {
|
||||
return (
|
||||
<CellRoot>
|
||||
<CellTop>
|
||||
<StyledName mb={'5px'}>{item.name} {item.deleted ? '(Deleted)' : ''} <StyledVersion>v{item.version}</StyledVersion></StyledName>
|
||||
<StyledName mb={'5px'}>{item.name} {item.deleted ? '(Deleted)' : ''}</StyledName>
|
||||
{renderToggleButton()}
|
||||
</CellTop>
|
||||
<CellContent>
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
import * as React from 'react';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import PluginService, { defaultPluginSetting, Plugins, PluginSetting, PluginSettings } from '@joplin/lib/services/plugins/PluginService';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import styled from 'styled-components';
|
||||
import SearchPlugins from './SearchPlugins';
|
||||
import PluginBox, { UpdateState } from './PluginBox';
|
||||
import PluginBox from './PluginBox';
|
||||
import Button, { ButtonLevel } from '../../../Button/Button';
|
||||
import bridge from '../../../../services/bridge';
|
||||
import produce from 'immer';
|
||||
import { OnChangeEvent } from '../../../lib/SearchInput/SearchInput';
|
||||
import { PluginItem } from './PluginBox';
|
||||
import RepositoryApi from '@joplin/lib/services/plugins/RepositoryApi';
|
||||
import Setting from '@joplin/lib/models/Setting';
|
||||
import useOnInstallHandler, { OnPluginSettingChangeEvent } from './useOnInstallHandler';
|
||||
const { space } = require('styled-system');
|
||||
|
||||
const maxWidth: number = 320;
|
||||
const maxWidth: number = 250;
|
||||
|
||||
const Root = styled.div`
|
||||
display: flex;
|
||||
@@ -29,7 +26,7 @@ const UserPluginsRoot = styled.div`
|
||||
`;
|
||||
|
||||
const ToolsButton = styled(Button)`
|
||||
margin-right: 6px;
|
||||
margin-right: 2px;
|
||||
`;
|
||||
|
||||
interface Props {
|
||||
@@ -41,15 +38,6 @@ interface Props {
|
||||
renderHeader: Function;
|
||||
}
|
||||
|
||||
let repoApi_: RepositoryApi = null;
|
||||
|
||||
function repoApi(): RepositoryApi {
|
||||
if (repoApi_) return repoApi_;
|
||||
repoApi_ = new RepositoryApi('https://github.com/joplin/plugins', Setting.value('tempDir'));
|
||||
// repoApi_ = new RepositoryApi('/Users/laurent/src/joplin-plugins-test', Setting.value('tempDir'));
|
||||
return repoApi_;
|
||||
}
|
||||
|
||||
function usePluginItems(plugins: Plugins, settings: PluginSettings): PluginItem[] {
|
||||
return useMemo(() => {
|
||||
const output: PluginItem[] = [];
|
||||
@@ -65,12 +53,10 @@ function usePluginItems(plugins: Plugins, settings: PluginSettings): PluginItem[
|
||||
output.push({
|
||||
id: pluginId,
|
||||
name: plugin.manifest.name,
|
||||
version: plugin.manifest.version,
|
||||
description: plugin.manifest.description,
|
||||
enabled: setting.enabled,
|
||||
deleted: setting.deleted,
|
||||
devMode: plugin.devMode,
|
||||
hasBeenUpdated: setting.hasBeenUpdated,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -84,9 +70,6 @@ function usePluginItems(plugins: Plugins, settings: PluginSettings): PluginItem[
|
||||
|
||||
export default function(props: Props) {
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
const [manifestsLoaded, setManifestsLoaded] = useState<boolean>(false);
|
||||
const [updatingPluginsIds, setUpdatingPluginIds] = useState<Record<string, boolean>>({});
|
||||
const [canBeUpdatedPluginIds, setCanBeUpdatedPluginIds] = useState<Record<string, boolean>>({});
|
||||
|
||||
const pluginService = PluginService.instance();
|
||||
|
||||
@@ -94,43 +77,6 @@ export default function(props: Props) {
|
||||
return pluginService.unserializePluginSettings(props.value);
|
||||
}, [props.value]);
|
||||
|
||||
const pluginItems = usePluginItems(pluginService.plugins, pluginSettings);
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
async function fetchManifests() {
|
||||
await repoApi().loadManifests();
|
||||
if (cancelled) return;
|
||||
setManifestsLoaded(true);
|
||||
}
|
||||
|
||||
void fetchManifests();
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!manifestsLoaded) return () => {};
|
||||
|
||||
let cancelled = false;
|
||||
|
||||
async function fetchPluginIds() {
|
||||
const pluginIds = await repoApi().canBeUpdatedPlugins(pluginItems as any);
|
||||
if (cancelled) return;
|
||||
const conv: Record<string, boolean> = {};
|
||||
pluginIds.forEach(id => conv[id] = true);
|
||||
setCanBeUpdatedPluginIds(conv);
|
||||
}
|
||||
|
||||
void fetchPluginIds();
|
||||
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [manifestsLoaded, pluginItems]);
|
||||
|
||||
const onDelete = useCallback(async (event: any) => {
|
||||
const item: PluginItem = event.item;
|
||||
const confirm = await bridge().showConfirmMessageBox(_('Delete plugin "%s"?', item.name));
|
||||
@@ -172,12 +118,6 @@ export default function(props: Props) {
|
||||
props.onChange({ value: pluginService.serializePluginSettings(newSettings) });
|
||||
}, [pluginSettings, props.onChange]);
|
||||
|
||||
const onPluginSettingsChange = useCallback((event: OnPluginSettingChangeEvent) => {
|
||||
props.onChange({ value: pluginService.serializePluginSettings(event.value) });
|
||||
}, []);
|
||||
|
||||
const onUpdate = useOnInstallHandler(setUpdatingPluginIds, pluginSettings, repoApi, onPluginSettingsChange, true);
|
||||
|
||||
const onToolsClick = useCallback(async () => {
|
||||
const template = [];
|
||||
|
||||
@@ -204,22 +144,12 @@ export default function(props: Props) {
|
||||
for (const item of items) {
|
||||
if (item.deleted) continue;
|
||||
|
||||
const isUpdating = updatingPluginsIds[item.id];
|
||||
const onUpdateHandler = canBeUpdatedPluginIds[item.id] ? onUpdate : null;
|
||||
|
||||
let updateState = UpdateState.Idle;
|
||||
if (onUpdateHandler) updateState = UpdateState.CanUpdate;
|
||||
if (isUpdating) updateState = UpdateState.Updating;
|
||||
if (item.hasBeenUpdated) updateState = UpdateState.HasBeenUpdated;
|
||||
|
||||
output.push(<PluginBox
|
||||
key={item.id}
|
||||
item={item}
|
||||
themeId={props.themeId}
|
||||
updateState={updateState}
|
||||
onDelete={onDelete}
|
||||
onToggle={onToggle}
|
||||
onUpdate={onUpdateHandler}
|
||||
/>);
|
||||
}
|
||||
|
||||
@@ -244,11 +174,13 @@ export default function(props: Props) {
|
||||
}
|
||||
}
|
||||
|
||||
function renderSearchArea() {
|
||||
return (
|
||||
const pluginItems = usePluginItems(pluginService.plugins, pluginSettings);
|
||||
|
||||
return (
|
||||
<Root>
|
||||
<div style={{ marginBottom: 20 }}>
|
||||
{props.renderHeader(props.themeId, _('Search for plugins'))}
|
||||
<SearchPlugins
|
||||
disabled={!manifestsLoaded}
|
||||
maxWidth={maxWidth}
|
||||
themeId={props.themeId}
|
||||
searchQuery={searchQuery}
|
||||
@@ -256,32 +188,18 @@ export default function(props: Props) {
|
||||
onSearchQueryChange={onSearchQueryChange}
|
||||
onPluginSettingsChange={onSearchPluginSettingsChange}
|
||||
renderDescription={props.renderDescription}
|
||||
repoApi={repoApi}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function renderBottomArea() {
|
||||
if (searchQuery) return null;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div style={{ display: 'flex', flexDirection: 'row', maxWidth }}>
|
||||
<ToolsButton tooltip={_('Plugin tools')} iconName="fas fa-cog" level={ButtonLevel.Secondary} onClick={onToolsClick}/>
|
||||
<div style={{ display: 'flex', flex: 1 }}>
|
||||
{props.renderHeader(props.themeId, _('Manage your plugins'))}
|
||||
</div>
|
||||
<ToolsButton tooltip={_('Plugin tools')} iconName="fas fa-cog" level={ButtonLevel.Primary} onClick={onToolsClick}/>
|
||||
</div>
|
||||
{renderUserPlugins(pluginItems)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Root>
|
||||
{renderSearchArea()}
|
||||
{renderBottomArea()}
|
||||
</Root>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import RepositoryApi from '@joplin/lib/services/plugins/RepositoryApi';
|
||||
import AsyncActionQueue from '@joplin/lib/AsyncActionQueue';
|
||||
import { PluginManifest } from '@joplin/lib/services/plugins/utils/types';
|
||||
import PluginBox, { InstallState } from './PluginBox';
|
||||
import Setting from '@joplin/lib/models/Setting';
|
||||
import { PluginSettings } from '@joplin/lib/services/plugins/PluginService';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import useOnInstallHandler from './useOnInstallHandler';
|
||||
@@ -26,18 +27,24 @@ interface Props {
|
||||
onPluginSettingsChange(event: any): void;
|
||||
renderDescription: Function;
|
||||
maxWidth: number;
|
||||
repoApi(): RepositoryApi;
|
||||
disabled: boolean;
|
||||
}
|
||||
|
||||
let repoApi_: RepositoryApi = null;
|
||||
|
||||
function repoApi(): RepositoryApi {
|
||||
if (repoApi_) return repoApi_;
|
||||
repoApi_ = new RepositoryApi('https://github.com/joplin/plugins', Setting.value('tempDir'));
|
||||
return repoApi_;
|
||||
}
|
||||
|
||||
export default function(props: Props) {
|
||||
const [searchStarted, setSearchStarted] = useState(false);
|
||||
const [manifests, setManifests] = useState<PluginManifest[]>([]);
|
||||
const asyncSearchQueue = useRef(new AsyncActionQueue(10));
|
||||
const asyncSearchQueue = useRef(new AsyncActionQueue(200));
|
||||
const [installingPluginsIds, setInstallingPluginIds] = useState<Record<string, boolean>>({});
|
||||
const [searchResultCount, setSearchResultCount] = useState(null);
|
||||
|
||||
const onInstall = useOnInstallHandler(setInstallingPluginIds, props.pluginSettings, props.repoApi, props.onPluginSettingsChange, false);
|
||||
const onInstall = useOnInstallHandler(setInstallingPluginIds, props.pluginSettings, repoApi, props.onPluginSettingsChange);
|
||||
|
||||
useEffect(() => {
|
||||
setSearchResultCount(null);
|
||||
@@ -46,7 +53,7 @@ export default function(props: Props) {
|
||||
setManifests([]);
|
||||
setSearchResultCount(null);
|
||||
} else {
|
||||
const r = await props.repoApi().search(props.searchQuery);
|
||||
const r = await repoApi().search(props.searchQuery);
|
||||
setManifests(r);
|
||||
setSearchResultCount(r.length);
|
||||
}
|
||||
@@ -100,8 +107,6 @@ export default function(props: Props) {
|
||||
onChange={onChange}
|
||||
onSearchButtonClick={onSearchButtonClick}
|
||||
searchStarted={searchStarted}
|
||||
placeholder={_('Search for plugins...')}
|
||||
disabled={props.disabled}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -6,13 +6,7 @@ import Logger from '@joplin/lib/Logger';
|
||||
|
||||
const logger = Logger.create('useOnInstallHandler');
|
||||
|
||||
export interface OnPluginSettingChangeEvent {
|
||||
value: PluginSettings;
|
||||
}
|
||||
|
||||
type OnPluginSettingChangeHandler = (event: OnPluginSettingChangeEvent)=> void;
|
||||
|
||||
export default function(setInstallingPluginIds: Function, pluginSettings: PluginSettings, repoApi: Function, onPluginSettingsChange: OnPluginSettingChangeHandler, isUpdate: boolean) {
|
||||
export default function(setInstallingPluginIds: Function, pluginSettings: PluginSettings, repoApi: Function, onPluginSettingsChange: Function) {
|
||||
return useCallback(async (event: any) => {
|
||||
const pluginId = event.item.id;
|
||||
|
||||
@@ -25,11 +19,7 @@ export default function(setInstallingPluginIds: Function, pluginSettings: Plugin
|
||||
let installError = null;
|
||||
|
||||
try {
|
||||
if (isUpdate) {
|
||||
await PluginService.instance().updatePluginFromRepo(repoApi(), pluginId);
|
||||
} else {
|
||||
await PluginService.instance().installPluginFromRepo(repoApi(), pluginId);
|
||||
}
|
||||
await PluginService.instance().installPluginFromRepo(repoApi(), pluginId);
|
||||
} catch (error) {
|
||||
installError = error;
|
||||
logger.error(error);
|
||||
@@ -38,7 +28,6 @@ export default function(setInstallingPluginIds: Function, pluginSettings: Plugin
|
||||
if (!installError) {
|
||||
const newSettings = produce(pluginSettings, (draft: PluginSettings) => {
|
||||
draft[pluginId] = defaultPluginSetting();
|
||||
if (isUpdate) draft[pluginId].hasBeenUpdated = true;
|
||||
});
|
||||
|
||||
onPluginSettingsChange({ value: newSettings });
|
||||
|
||||
@@ -41,8 +41,6 @@ interface Props {
|
||||
onKeyDown?: Function;
|
||||
onSearchButtonClick: Function;
|
||||
searchStarted: boolean;
|
||||
placeholder?: string;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
export interface OnChangeEvent {
|
||||
@@ -62,13 +60,12 @@ export default function(props: Props) {
|
||||
ref={props.inputRef}
|
||||
value={props.value}
|
||||
type="text"
|
||||
placeholder={props.placeholder || _('Search...')}
|
||||
placeholder={_('Search...')}
|
||||
onChange={onChange}
|
||||
onFocus={props.onFocus}
|
||||
onBlur={props.onBlur}
|
||||
onKeyDown={props.onKeyDown}
|
||||
spellCheck={false}
|
||||
disabled={props.disabled}
|
||||
/>
|
||||
<SearchButton onClick={props.onSearchButtonClick}>
|
||||
<SearchButtonIcon className={iconName}/>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
const gulp = require('gulp');
|
||||
const utils = require('@joplin/tools/gulp/utils');
|
||||
const fs = require('fs-extra');
|
||||
|
||||
const tasks = {
|
||||
compileScripts: {
|
||||
@@ -17,18 +18,55 @@ const tasks = {
|
||||
electronRebuild: {
|
||||
fn: require('./tools/electronRebuild.js'),
|
||||
},
|
||||
// compileExtensions: {
|
||||
// fn: require('@joplin/tools/gulp/tasks/compileExtensions.js'),
|
||||
// },
|
||||
// copyLib: require('@joplin/tools/gulp/tasks/copyLib'),
|
||||
tsc: require('@joplin/tools/gulp/tasks/tsc'),
|
||||
updateIgnoredTypeScriptBuild: require('@joplin/tools/gulp/tasks/updateIgnoredTypeScriptBuild'),
|
||||
|
||||
linkReact: {
|
||||
fn: async () => {
|
||||
// React is a dependency of both the lib and app-desktop
|
||||
// packages, which cause a duplicate React issue. To go around
|
||||
// this, one way is to manually link the package.
|
||||
//
|
||||
// Note that React must also be unlinked in preinstall step
|
||||
// otherwise there will be permission errors when running
|
||||
// `lerna bootstrap`
|
||||
//
|
||||
// https://reactjs.org/warnings/invalid-hook-call-warning.html#duplicate-react
|
||||
process.chdir(__dirname);
|
||||
await fs.remove('./node_modules/react');
|
||||
await fs.remove('./node_modules/react-dom');
|
||||
await utils.execCommand('npm link ../lib/node_modules/react');
|
||||
await utils.execCommand('npm link ../lib/node_modules/react-dom');
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
utils.registerGulpTasks(gulp, tasks);
|
||||
|
||||
// const buildSeries = [
|
||||
// // 'compileExtensions',
|
||||
// // 'copyLib',
|
||||
// ];
|
||||
|
||||
// On Windows also run tsc because `npm run watch` locks some folders
|
||||
// which makes the copyPluginAssets command fail. For that reason,
|
||||
// it's not possible to run watch on Windows while testing the desktop app.
|
||||
// if (require('os').platform() === 'win32') {
|
||||
// buildSeries.push('tsc');
|
||||
// }
|
||||
|
||||
const buildParallel = [
|
||||
// gulp.series(...buildSeries),
|
||||
'compileScripts',
|
||||
'compilePackageInfo',
|
||||
'copyPluginAssets',
|
||||
'copyTinyMceLangs',
|
||||
'updateIgnoredTypeScriptBuild',
|
||||
// 'linkReact',
|
||||
];
|
||||
|
||||
gulp.task('build', gulp.parallel(...buildParallel));
|
||||
|
||||
2
packages/app-desktop/package-lock.json
generated
2
packages/app-desktop/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/app-desktop",
|
||||
"version": "1.7.2",
|
||||
"version": "1.7.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/app-desktop",
|
||||
"version": "1.7.2",
|
||||
"version": "1.7.0",
|
||||
"description": "Joplin for Desktop",
|
||||
"main": "main.js",
|
||||
"private": true,
|
||||
|
||||
@@ -635,8 +635,8 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
let resource = Resource.new();
|
||||
resource.id = uuid.create();
|
||||
resource.mime = mimeType;
|
||||
resource.title = pickerResponse.name ? pickerResponse.name : '';
|
||||
resource.file_extension = safeFileExtension(fileExtension(pickerResponse.name ? pickerResponse.name : localFilePath));
|
||||
resource.title = pickerResponse.fileName ? pickerResponse.fileName : '';
|
||||
resource.file_extension = safeFileExtension(fileExtension(pickerResponse.fileName ? pickerResponse.fileName : localFilePath));
|
||||
|
||||
if (!resource.mime) resource.mime = 'application/octet-stream';
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const gulp = require('gulp');
|
||||
const fs = require('fs-extra');
|
||||
const utils = require('@joplin/tools/gulp/utils');
|
||||
|
||||
const tasks = {
|
||||
@@ -11,6 +12,23 @@ const tasks = {
|
||||
podInstall: {
|
||||
fn: require('./tools/podInstall'),
|
||||
},
|
||||
prepareRelease: {
|
||||
fn: require('./tools/prepareRelease'),
|
||||
},
|
||||
// clean: {
|
||||
// fn: require('./tools/clean'),
|
||||
// },
|
||||
linkReact: {
|
||||
fn: async () => {
|
||||
// React is a dependency of both the lib and app-desktop
|
||||
// packages, which cause a duplicate React issue. To go around
|
||||
// this, one way is to manually link the package.
|
||||
// https://reactjs.org/warnings/invalid-hook-call-warning.html#duplicate-react
|
||||
process.chdir(__dirname);
|
||||
await fs.remove('./node_modules/react');
|
||||
await utils.execCommand('npm link ../lib/node_modules/react');
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
utils.registerGulpTasks(gulp, tasks);
|
||||
@@ -18,5 +36,6 @@ utils.registerGulpTasks(gulp, tasks);
|
||||
gulp.task('build', gulp.series(
|
||||
'buildReactNativeInjectedJs',
|
||||
'encodeAssets',
|
||||
// 'linkReact',
|
||||
'podInstall'
|
||||
));
|
||||
|
||||
32
packages/app-mobile/tools/prepareRelease.js
Normal file
32
packages/app-mobile/tools/prepareRelease.js
Normal file
@@ -0,0 +1,32 @@
|
||||
// This is to replace the symlinks inside node_modules with the actual packages
|
||||
// as I assumed it was needed to build the final release. However it seems
|
||||
// Android `assembleRelease` handles symlinks properly so maybe this is not
|
||||
// needed after all ¯\_(ツ)_/¯
|
||||
|
||||
const { copyDir } = require('@joplin/tools/gulp/utils');
|
||||
const { rootDir, deleteLink, toSystemSlashes } = require('@joplin/tools/tool-utils');
|
||||
const mobileDir = `${rootDir}/packages/app-mobile`;
|
||||
|
||||
module.exports = async function() {
|
||||
const dirsToCopy = [
|
||||
'fork-htmlparser2',
|
||||
'fork-sax',
|
||||
'lib',
|
||||
'renderer',
|
||||
];
|
||||
|
||||
const destDir = `${mobileDir}/node_modules/@joplin`;
|
||||
|
||||
for (const dir of dirsToCopy) {
|
||||
const destPath = toSystemSlashes(`${destDir}/${dir}`);
|
||||
const sourcePath = toSystemSlashes(`${rootDir}/packages/${dir}`);
|
||||
|
||||
console.info(`Copying ${sourcePath} => ${destPath}`);
|
||||
|
||||
// TODO: copy symlink so that it can be restored
|
||||
await deleteLink(destPath);
|
||||
await copyDir(sourcePath, destPath, {
|
||||
excluded: ['node_modules'],
|
||||
});
|
||||
}
|
||||
};
|
||||
31
packages/app-mobile/tools/unlinkReact.js
Normal file
31
packages/app-mobile/tools/unlinkReact.js
Normal file
@@ -0,0 +1,31 @@
|
||||
// const fs = require('fs');
|
||||
// const { execSync } = require("child_process");
|
||||
|
||||
// const isWindows = process.platform === "win32";
|
||||
|
||||
// function toSystemSlashes(path) {
|
||||
// const os = process.platform;
|
||||
// if (os === 'win32') return path.replace(/\//g, '\\');
|
||||
// return path.replace(/\\/g, '/');
|
||||
// }
|
||||
|
||||
// const nodeModulesPath = `${__dirname}/../node_modules`;
|
||||
|
||||
// function deleteLink(path) {
|
||||
// if (isWindows) {
|
||||
// try {
|
||||
// execSync(`rmdir "${toSystemSlashes(path)}"`, { stdio : 'pipe' });
|
||||
// } catch (error) {
|
||||
// // console.info('Error: ' + error.message);
|
||||
// }
|
||||
// } else {
|
||||
// try {
|
||||
// fs.unlinkSync(toSystemSlashes(path));
|
||||
// } catch (error) {
|
||||
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// deleteLink(nodeModulesPath + '/react');
|
||||
// deleteLink(nodeModulesPath + '/react-dom');
|
||||
2
packages/fork-htmlparser2/package-lock.json
generated
2
packages/fork-htmlparser2/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/fork-htmlparser2",
|
||||
"version": "4.1.19",
|
||||
"version": "4.1.15",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@joplin/fork-htmlparser2",
|
||||
"description": "Fast & forgiving HTML/XML/RSS parser",
|
||||
"version": "4.1.19",
|
||||
"version": "4.1.15",
|
||||
"author": "Felix Boehm <me@feedic.com>",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
@@ -52,7 +52,7 @@
|
||||
"coveralls": "^3.0.1",
|
||||
"eslint": "^6.0.0",
|
||||
"eslint-config-prettier": "^6.0.0",
|
||||
"jest": "^26.6.3",
|
||||
"jest": "^24.8.0",
|
||||
"prettier": "^1.18.2",
|
||||
"ts-jest": "^24.0.2",
|
||||
"typescript": "^3.5.3"
|
||||
|
||||
2
packages/fork-sax/package-lock.json
generated
2
packages/fork-sax/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/fork-sax",
|
||||
"version": "1.2.23",
|
||||
"version": "1.2.19",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "@joplin/fork-sax",
|
||||
"description": "An evented streaming XML parser in JavaScript",
|
||||
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me/)",
|
||||
"version": "1.2.23",
|
||||
"version": "1.2.19",
|
||||
"main": "lib/sax.js",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
||||
@@ -34,4 +34,4 @@
|
||||
"repository": "https://github.com/laurent22/generator-joplin",
|
||||
"license": "MIT",
|
||||
"private": true
|
||||
}
|
||||
}
|
||||
@@ -667,7 +667,6 @@ export default class BaseApplication {
|
||||
const resourceDirName = 'resources';
|
||||
const resourceDir = `${profileDir}/${resourceDirName}`;
|
||||
const tempDir = `${profileDir}/tmp`;
|
||||
const cacheDir = `${profileDir}/cache`;
|
||||
|
||||
Setting.setConstant('env', initArgs.env);
|
||||
Setting.setConstant('profileDir', profileDir);
|
||||
@@ -675,7 +674,6 @@ export default class BaseApplication {
|
||||
Setting.setConstant('resourceDirName', resourceDirName);
|
||||
Setting.setConstant('resourceDir', resourceDir);
|
||||
Setting.setConstant('tempDir', tempDir);
|
||||
Setting.setConstant('cacheDir', cacheDir);
|
||||
Setting.setConstant('pluginDir', `${profileDir}/plugins`);
|
||||
|
||||
SyncTargetRegistry.addClass(SyncTargetFilesystem);
|
||||
@@ -697,7 +695,6 @@ export default class BaseApplication {
|
||||
await fs.mkdirp(profileDir, 0o755);
|
||||
await fs.mkdirp(resourceDir, 0o755);
|
||||
await fs.mkdirp(tempDir, 0o755);
|
||||
await fs.mkdirp(cacheDir, 0o755);
|
||||
|
||||
// Clean up any remaining watched files (they start with "edit-")
|
||||
await shim.fsDriver().removeAllThatStartWith(profileDir, 'edit-');
|
||||
|
||||
@@ -1659,7 +1659,6 @@ Setting.constants_ = {
|
||||
profileDir: '',
|
||||
templateDir: '',
|
||||
tempDir: '',
|
||||
cacheDir: '',
|
||||
pluginDir: '',
|
||||
flagOpenDevTools: false,
|
||||
syncVersion: 2,
|
||||
|
||||
2
packages/lib/package-lock.json
generated
2
packages/lib/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/lib",
|
||||
"version": "1.7.2",
|
||||
"version": "1.0.16",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/lib",
|
||||
"version": "1.7.2",
|
||||
"version": "1.0.16",
|
||||
"description": "Joplin Core library",
|
||||
"author": "Laurent Cozic",
|
||||
"homepage": "",
|
||||
@@ -22,11 +22,11 @@
|
||||
"typescript": "^4.0.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@joplin/fork-htmlparser2": "^4.1.19",
|
||||
"@joplin/fork-sax": "^1.2.23",
|
||||
"@joplin/renderer": "^1.7.2",
|
||||
"@joplin/turndown": "^4.0.41",
|
||||
"@joplin/turndown-plugin-gfm": "^1.0.23",
|
||||
"@joplin/fork-htmlparser2": "^4.1.15",
|
||||
"@joplin/fork-sax": "^1.2.19",
|
||||
"@joplin/renderer": "^1.0.24",
|
||||
"@joplin/turndown": "^4.0.37",
|
||||
"@joplin/turndown-plugin-gfm": "^1.0.19",
|
||||
"async-mutex": "^0.1.3",
|
||||
"aws-sdk": "^2.588.0",
|
||||
"base-64": "^0.1.0",
|
||||
|
||||
@@ -8,7 +8,6 @@ import { filename, dirname, rtrimSlashes } from '../../path-utils';
|
||||
import Setting from '../../models/Setting';
|
||||
import Logger from '../../Logger';
|
||||
import RepositoryApi from './RepositoryApi';
|
||||
import produce from 'immer';
|
||||
const compareVersions = require('compare-versions');
|
||||
const uslug = require('uslug');
|
||||
const md5File = require('md5-file/promise');
|
||||
@@ -32,19 +31,12 @@ export interface Plugins {
|
||||
export interface PluginSetting {
|
||||
enabled: boolean;
|
||||
deleted: boolean;
|
||||
|
||||
// After a plugin has been updated, the user needs to restart the app before
|
||||
// loading the new version. In the meantime, we set this property to `true`
|
||||
// so that we know the plugin has been updated. It is used for example to
|
||||
// disable the Update button.
|
||||
hasBeenUpdated: boolean;
|
||||
}
|
||||
|
||||
export function defaultPluginSetting(): PluginSetting {
|
||||
return {
|
||||
enabled: true,
|
||||
deleted: false,
|
||||
hasBeenUpdated: false,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -100,10 +92,6 @@ export default class PluginService extends BaseService {
|
||||
delete this.plugins_[pluginId];
|
||||
}
|
||||
|
||||
private async deletePluginFiles(plugin: Plugin) {
|
||||
await shim.fsDriver().remove(plugin.baseDir);
|
||||
}
|
||||
|
||||
public pluginById(id: string): Plugin {
|
||||
if (!this.plugins_[id]) throw new Error(`Plugin not found: ${id}`);
|
||||
|
||||
@@ -185,7 +173,7 @@ export default class PluginService extends BaseService {
|
||||
const fname = filename(path);
|
||||
const hash = await md5File(path);
|
||||
|
||||
const unpackDir = `${Setting.value('cacheDir')}/${fname}`;
|
||||
const unpackDir = `${Setting.value('tempDir')}/${fname}`;
|
||||
const manifestFilePath = `${unpackDir}/manifest.json`;
|
||||
|
||||
let manifest: any = await this.loadManifestToObject(manifestFilePath);
|
||||
@@ -206,7 +194,7 @@ export default class PluginService extends BaseService {
|
||||
|
||||
manifest._package_hash = hash;
|
||||
|
||||
await shim.fsDriver().writeFile(manifestFilePath, JSON.stringify(manifest, null, '\t'), 'utf8');
|
||||
await shim.fsDriver().writeFile(manifestFilePath, JSON.stringify(manifest), 'utf8');
|
||||
}
|
||||
|
||||
return this.loadPluginFromPath(unpackDir);
|
||||
@@ -357,10 +345,6 @@ export default class PluginService extends BaseService {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
public async updatePluginFromRepo(repoApi: RepositoryApi, pluginId: string): Promise<Plugin> {
|
||||
return this.installPluginFromRepo(repoApi, pluginId);
|
||||
}
|
||||
|
||||
public async installPlugin(jplPath: string): Promise<Plugin> {
|
||||
logger.info(`Installing plugin: "${jplPath}"`);
|
||||
|
||||
@@ -368,7 +352,6 @@ export default class PluginService extends BaseService {
|
||||
// from where it is now to check that it is valid and to retrieve
|
||||
// the plugin ID.
|
||||
const preloadedPlugin = await this.loadPluginFromPath(jplPath);
|
||||
await this.deletePluginFiles(preloadedPlugin);
|
||||
|
||||
const destPath = `${Setting.value('pluginDir')}/${preloadedPlugin.id}.jpl`;
|
||||
await shim.fsDriver().copy(jplPath, destPath);
|
||||
@@ -419,16 +402,6 @@ export default class PluginService extends BaseService {
|
||||
return newSettings;
|
||||
}
|
||||
|
||||
// On startup the "hasBeenUpdated" prop can be cleared since the new version
|
||||
// of the plugin has now been loaded.
|
||||
public clearUpdateState(settings: PluginSettings): PluginSettings {
|
||||
return produce(settings, (draft: PluginSettings) => {
|
||||
for (const pluginId in draft) {
|
||||
if (draft[pluginId].hasBeenUpdated) draft[pluginId].hasBeenUpdated = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public async destroy() {
|
||||
await this.runner_.waitForSandboxCalls();
|
||||
}
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
import shim from '../../shim';
|
||||
import { PluginManifest } from './utils/types';
|
||||
const md5 = require('md5');
|
||||
const compareVersions = require('compare-versions');
|
||||
|
||||
export default class RepositoryApi {
|
||||
|
||||
// As a base URL, this class can support either a remote repository or a
|
||||
// local one (a directory path), which is useful for testing.
|
||||
//
|
||||
// For now, if the baseUrl is an actual URL it's assumed it's a GitHub repo
|
||||
// URL, such as https://github.com/joplin/plugins
|
||||
// For now, it's assumed that the baseUrl is a GitHub repo URL, such as
|
||||
// https://github.com/joplin/plugins
|
||||
//
|
||||
// Later on, other repo types could be supported.
|
||||
private baseUrl_: string;
|
||||
@@ -21,29 +17,8 @@ export default class RepositoryApi {
|
||||
this.tempDir_ = tempDir;
|
||||
}
|
||||
|
||||
public async loadManifests() {
|
||||
const manifestsText = await this.fetchText('manifests.json');
|
||||
try {
|
||||
const manifests = JSON.parse(manifestsText);
|
||||
if (!manifests) throw new Error('Invalid or missing JSON');
|
||||
this.manifests_ = Object.keys(manifests).map(id => {
|
||||
return manifests[id];
|
||||
});
|
||||
} catch (error) {
|
||||
throw new Error(`Could not parse JSON: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
private get isLocalRepo(): boolean {
|
||||
return this.baseUrl_.indexOf('http') !== 0;
|
||||
}
|
||||
|
||||
private get contentBaseUrl(): string {
|
||||
if (this.isLocalRepo) {
|
||||
return this.baseUrl_;
|
||||
} else {
|
||||
return `${this.baseUrl_.replace(/github\.com/, 'raw.githubusercontent.com')}/master`;
|
||||
}
|
||||
return `${this.baseUrl_.replace(/github\.com/, 'raw.githubusercontent.com')}/master`;
|
||||
}
|
||||
|
||||
private fileUrl(relativePath: string): string {
|
||||
@@ -51,11 +26,7 @@ export default class RepositoryApi {
|
||||
}
|
||||
|
||||
private async fetchText(path: string): Promise<string> {
|
||||
if (this.isLocalRepo) {
|
||||
return shim.fsDriver().readFile(this.fileUrl(path), 'utf8');
|
||||
} else {
|
||||
return shim.fetchText(this.fileUrl(path));
|
||||
}
|
||||
return shim.fetchText(this.fileUrl(path));
|
||||
}
|
||||
|
||||
public async search(query: string): Promise<PluginManifest[]> {
|
||||
@@ -89,40 +60,27 @@ export default class RepositoryApi {
|
||||
const fileUrl = this.fileUrl(`plugins/${manifest.id}/plugin.jpl`);
|
||||
const hash = md5(Date.now() + Math.random());
|
||||
const targetPath = `${this.tempDir_}/${hash}_${manifest.id}.jpl`;
|
||||
const response = await shim.fetchBlob(fileUrl, {
|
||||
path: targetPath,
|
||||
});
|
||||
|
||||
if (this.isLocalRepo) {
|
||||
await shim.fsDriver().copy(fileUrl, targetPath);
|
||||
} else {
|
||||
const response = await shim.fetchBlob(fileUrl, {
|
||||
path: targetPath,
|
||||
});
|
||||
|
||||
if (!response.ok) throw new Error(`Could not download plugin "${pluginId}" from "${fileUrl}"`);
|
||||
}
|
||||
|
||||
if (!response.ok) throw new Error(`Could not download plugin "${pluginId}" from "${fileUrl}"`);
|
||||
return targetPath;
|
||||
}
|
||||
|
||||
public async manifests(): Promise<PluginManifest[]> {
|
||||
if (!this.manifests_) throw new Error('Manifests have no been loaded!');
|
||||
return this.manifests_;
|
||||
}
|
||||
|
||||
public async canBeUpdatedPlugins(installedManifests: PluginManifest[]): Promise<string[]> {
|
||||
const output = [];
|
||||
|
||||
for (const manifest of installedManifests) {
|
||||
const canBe = await this.pluginCanBeUpdated(manifest.id, manifest.version);
|
||||
if (canBe) output.push(manifest.id);
|
||||
private async manifests(): Promise<PluginManifest[]> {
|
||||
if (this.manifests_) return this.manifests_;
|
||||
const manifestsText = await this.fetchText('manifests.json');
|
||||
try {
|
||||
const manifests = JSON.parse(manifestsText);
|
||||
if (!manifests) throw new Error('Invalid or missing JSON');
|
||||
this.manifests_ = Object.keys(manifests).map(id => {
|
||||
return manifests[id];
|
||||
});
|
||||
return this.manifests_;
|
||||
} catch (error) {
|
||||
throw new Error(`Could not parse JSON: ${error.message}`);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
// Dummy test because the Jest setup is done but there's for now no test.
|
||||
|
||||
describe('dummy', () => {
|
||||
|
||||
it('should pass', () => {
|
||||
expect(1).toBe(1);
|
||||
});
|
||||
|
||||
});
|
||||
7815
packages/plugin-repo-cli/package-lock.json
generated
7815
packages/plugin-repo-cli/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,33 +0,0 @@
|
||||
{
|
||||
"name": "@joplin/plugin-repo-cli",
|
||||
"version": "1.7.4",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"bin": {
|
||||
"plugin-repo-cli": "./index.js"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"scripts": {
|
||||
"tsc": "tsc --project tsconfig.json",
|
||||
"watch": "tsc --watch --project tsconfig.json",
|
||||
"test": "jest",
|
||||
"test-ci": "npm run test"
|
||||
},
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@joplin/lib": "^1.7.2",
|
||||
"@joplin/tools": "^1.7.2",
|
||||
"fs-extra": "^9.0.1",
|
||||
"yargs": "^16.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/fs-extra": "^9.0.6",
|
||||
"@types/jest": "^26.0.15",
|
||||
"@types/node": "^14.14.6",
|
||||
"jest": "^26.6.3",
|
||||
"typescript": "^4.1.3"
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"include": [
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
],
|
||||
"exclude": [
|
||||
"**/node_modules",
|
||||
],
|
||||
}
|
||||
2
packages/renderer/package-lock.json
generated
2
packages/renderer/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/renderer",
|
||||
"version": "1.7.2",
|
||||
"version": "1.0.24",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/renderer",
|
||||
"version": "1.7.2",
|
||||
"version": "1.0.24",
|
||||
"description": "The Joplin note renderer, used the mobile and desktop application",
|
||||
"repository": "https://github.com/laurent22/joplin/tree/dev/packages/renderer",
|
||||
"main": "index.js",
|
||||
@@ -24,7 +24,7 @@
|
||||
"typescript": "^4.0.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@joplin/fork-htmlparser2": "^4.1.19",
|
||||
"@joplin/fork-htmlparser2": "^4.1.15",
|
||||
"font-awesome-filetypes": "^2.1.0",
|
||||
"fs-extra": "^8.1.0",
|
||||
"highlight.js": "^10.2.1",
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import * as fs from 'fs-extra';
|
||||
import * as path from 'path';
|
||||
import * as process from 'process';
|
||||
import validatePluginId from '@joplin/lib/services/plugins/utils/validatePluginId';
|
||||
import markdownUtils, { MarkdownTableHeader, MarkdownTableRow } from '@joplin/lib/markdownUtils';
|
||||
import { execCommand2, resolveRelativePathWithinDir, gitPullTry, gitRepoCleanTry, gitRepoClean } from '@joplin/tools/tool-utils.js';
|
||||
const { execCommand, execCommandVerbose, rootDir, resolveRelativePathWithinDir, gitPullTry } = require('./tool-utils.js');
|
||||
|
||||
interface NpmPackage {
|
||||
name: string;
|
||||
@@ -47,7 +45,6 @@ async function checkPluginRepository(dirPath: string) {
|
||||
|
||||
const previousDir = process.cwd();
|
||||
process.chdir(dirPath);
|
||||
await gitRepoCleanTry();
|
||||
await gitPullTry();
|
||||
process.chdir(previousDir);
|
||||
}
|
||||
@@ -73,13 +70,13 @@ async function extractPluginFilesFromPackage(existingManifests: any, workDir: st
|
||||
const previousDir = process.cwd();
|
||||
process.chdir(workDir);
|
||||
|
||||
await execCommand2(`npm install ${packageName} --save --ignore-scripts`, { showOutput: false });
|
||||
await execCommandVerbose('npm', ['install', packageName, '--save', '--ignore-scripts']);
|
||||
|
||||
const pluginDir = resolveRelativePathWithinDir(workDir, 'node_modules', packageName, 'publish');
|
||||
|
||||
const files = await fs.readdir(pluginDir);
|
||||
const manifestFilePath = path.resolve(pluginDir, files.find((f: any) => path.extname(f) === '.json'));
|
||||
const pluginFilePath = path.resolve(pluginDir, files.find((f: any) => path.extname(f) === '.jpl'));
|
||||
const manifestFilePath = path.resolve(pluginDir, files.find(f => path.extname(f) === '.json'));
|
||||
const pluginFilePath = path.resolve(pluginDir, files.find(f => path.extname(f) === '.jpl'));
|
||||
|
||||
if (!(await fs.pathExists(manifestFilePath))) throw new Error(`Could not find manifest file at ${manifestFilePath}`);
|
||||
if (!(await fs.pathExists(pluginFilePath))) throw new Error(`Could not find plugin file at ${pluginFilePath}`);
|
||||
@@ -158,41 +155,23 @@ async function updateReadme(readmePath: string, manifests: any) {
|
||||
|
||||
const tableRegex = /<!-- PLUGIN_LIST -->([^]*)<!-- PLUGIN_LIST -->/;
|
||||
|
||||
const content = await fs.pathExists(readmePath) ? await fs.readFile(readmePath, 'utf8') : '<!-- PLUGIN_LIST -->\n<!-- PLUGIN_LIST -->';
|
||||
const content = await fs.readFile(readmePath, 'utf8');
|
||||
const newContent = content.replace(tableRegex, `<!-- PLUGIN_LIST -->\n${mdTable}\n<!-- PLUGIN_LIST -->`);
|
||||
|
||||
await fs.writeFile(readmePath, newContent, 'utf8');
|
||||
}
|
||||
|
||||
interface CommandBuildArgs {
|
||||
pluginRepoDir: string;
|
||||
}
|
||||
|
||||
enum ProcessingActionType {
|
||||
Add = 1,
|
||||
Update = 2,
|
||||
}
|
||||
|
||||
function commitMessage(actionType: ProcessingActionType, npmPackage: NpmPackage): string {
|
||||
const output: string[] = [];
|
||||
|
||||
if (actionType === ProcessingActionType.Add) {
|
||||
output.push('New');
|
||||
} else {
|
||||
output.push('Update');
|
||||
}
|
||||
|
||||
output.push(`${npmPackage.name}@${npmPackage.version}`);
|
||||
|
||||
return output.join(': ');
|
||||
}
|
||||
|
||||
async function processNpmPackage(npmPackage: NpmPackage, repoDir: string) {
|
||||
async function main() {
|
||||
// We assume that the repository is located in a directory next to the main
|
||||
// Joplin monorepo.
|
||||
const repoDir = path.resolve(path.dirname(rootDir), 'joplin-plugins');
|
||||
const tempDir = `${repoDir}/temp`;
|
||||
const pluginManifestsPath = path.resolve(repoDir, 'manifests.json');
|
||||
const obsoleteManifestsPath = path.resolve(repoDir, 'obsoletes.json');
|
||||
const errorsPath = path.resolve(repoDir, 'errors.json');
|
||||
|
||||
await checkPluginRepository(repoDir);
|
||||
|
||||
await fs.mkdirp(tempDir);
|
||||
|
||||
const originalPluginManifests = await readJsonFile(pluginManifestsPath, {});
|
||||
@@ -202,31 +181,29 @@ async function processNpmPackage(npmPackage: NpmPackage, repoDir: string) {
|
||||
...obsoleteManifests,
|
||||
};
|
||||
|
||||
const searchResults = (await execCommand('npm search joplin-plugin --searchlimit 5000 --json')).trim();
|
||||
const npmPackages = pluginInfoFromSearchResults(JSON.parse(searchResults));
|
||||
|
||||
const packageTempDir = `${tempDir}/packages`;
|
||||
|
||||
await fs.mkdirp(packageTempDir);
|
||||
const previousDir = process.cwd();
|
||||
process.chdir(packageTempDir);
|
||||
await execCommand2('npm init --yes --loglevel silent', { quiet: true });
|
||||
await execCommand('npm init --yes --loglevel silent');
|
||||
|
||||
const errors: any = await readJsonFile(errorsPath, {});
|
||||
delete errors[npmPackage.name];
|
||||
const errors: any[] = [];
|
||||
|
||||
let actionType: ProcessingActionType = ProcessingActionType.Update;
|
||||
let manifests: any = {};
|
||||
|
||||
try {
|
||||
const destDir = `${repoDir}/plugins/`;
|
||||
const manifest = await extractPluginFilesFromPackage(existingManifests, packageTempDir, npmPackage.name, destDir);
|
||||
|
||||
if (!existingManifests[manifest.id]) {
|
||||
actionType = ProcessingActionType.Add;
|
||||
for (const npmPackage of npmPackages) {
|
||||
try {
|
||||
const packageName = npmPackage.name;
|
||||
const destDir = `${repoDir}/plugins/`;
|
||||
const manifest = await extractPluginFilesFromPackage(existingManifests, packageTempDir, packageName, destDir);
|
||||
if (!obsoleteManifests[manifest.id]) manifests[manifest.id] = manifest;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
errors.push(error);
|
||||
}
|
||||
|
||||
if (!obsoleteManifests[manifest.id]) manifests[manifest.id] = manifest;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
errors[npmPackage.name] = error.message || '';
|
||||
}
|
||||
|
||||
// We preserve the original manifests so that if a plugin has been removed
|
||||
@@ -240,91 +217,20 @@ async function processNpmPackage(npmPackage: NpmPackage, repoDir: string) {
|
||||
|
||||
await fs.writeFile(pluginManifestsPath, JSON.stringify(manifests, null, '\t'), 'utf8');
|
||||
|
||||
if (Object.keys(errors).length) {
|
||||
await fs.writeFile(errorsPath, JSON.stringify(errors, null, '\t'), 'utf8');
|
||||
if (errors.length) {
|
||||
const toWrite = errors.map((e: any) => {
|
||||
return {
|
||||
message: e.message || '',
|
||||
};
|
||||
});
|
||||
await fs.writeFile(errorsPath, JSON.stringify(toWrite, null, '\t'), 'utf8');
|
||||
} else {
|
||||
await fs.remove(errorsPath);
|
||||
}
|
||||
|
||||
await updateReadme(`${repoDir}/README.md`, manifests);
|
||||
|
||||
process.chdir(previousDir);
|
||||
await fs.remove(tempDir);
|
||||
|
||||
process.chdir(repoDir);
|
||||
|
||||
if (!(await gitRepoClean())) {
|
||||
await execCommand2('git add -A', { showOutput: false });
|
||||
await execCommand2(['git', 'commit', '-m', commitMessage(actionType, npmPackage)], { showOutput: false });
|
||||
} else {
|
||||
console.info('Nothing to commit');
|
||||
}
|
||||
}
|
||||
|
||||
async function commandBuild(args: CommandBuildArgs) {
|
||||
console.info(new Date(), 'Building repository...');
|
||||
|
||||
const repoDir = args.pluginRepoDir;
|
||||
await checkPluginRepository(repoDir);
|
||||
|
||||
const searchResults = (await execCommand2('npm search joplin-plugin --searchlimit 5000 --json', { showOutput: false })).trim();
|
||||
const npmPackages = pluginInfoFromSearchResults(JSON.parse(searchResults));
|
||||
|
||||
for (const npmPackage of npmPackages) {
|
||||
await processNpmPackage(npmPackage, repoDir);
|
||||
}
|
||||
|
||||
await execCommand2('git push');
|
||||
}
|
||||
|
||||
async function commandVersion() {
|
||||
const p = await readJsonFile(path.resolve(__dirname, 'package.json'));
|
||||
console.info(`Version ${p.version}`);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const scriptName: string = 'plugin-repo-cli';
|
||||
|
||||
const commands: Record<string, Function> = {
|
||||
build: commandBuild,
|
||||
version: commandVersion,
|
||||
};
|
||||
|
||||
let selectedCommand: string = '';
|
||||
let selectedCommandArgs: string = '';
|
||||
|
||||
function setSelectedCommand(name: string, args: any) {
|
||||
selectedCommand = name;
|
||||
selectedCommandArgs = args;
|
||||
}
|
||||
|
||||
require('yargs')
|
||||
.scriptName(scriptName)
|
||||
.usage('$0 <cmd> [args]')
|
||||
|
||||
.command('build <plugin-repo-dir>', 'Build the plugin repository', (yargs: any) => {
|
||||
yargs.positional('plugin-repo-dir', {
|
||||
type: 'string',
|
||||
describe: 'Directory where the plugin repository is located',
|
||||
});
|
||||
}, (args: any) => setSelectedCommand('build', args))
|
||||
|
||||
.command('version', 'Gives version info', () => {}, (args: any) => setSelectedCommand('version', args))
|
||||
|
||||
.help()
|
||||
.argv;
|
||||
|
||||
if (!selectedCommand) {
|
||||
console.error(`Please provide a command name or type \`${scriptName} --help\` for help`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!commands[selectedCommand]) {
|
||||
console.error(`No such command: ${selectedCommand}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
await commands[selectedCommand](selectedCommandArgs);
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
@@ -155,15 +155,4 @@ utils.registerGulpTasks = function(gulp, tasks) {
|
||||
}
|
||||
};
|
||||
|
||||
utils.setPackagePrivateField = async function(filePath, value) {
|
||||
const text = await fs.readFile(filePath, 'utf8');
|
||||
const obj = JSON.parse(text);
|
||||
if (!value) {
|
||||
delete obj.private;
|
||||
} else {
|
||||
obj.private = true;
|
||||
}
|
||||
await fs.writeFile(filePath, JSON.stringify(obj, null, 2), 'utf8');
|
||||
};
|
||||
|
||||
module.exports = utils;
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
// // npx lerna add --no-bootstrap --scope @joplin/plugin-repo-builder -D jest && npx lerna bootstrap --no-ci --include-dependents --include-dependencies --scope @joplin/plugin-repo-builder
|
||||
|
||||
// import { execCommand2, rootDir, gitPullTry } from './tool-utils.js';
|
||||
|
||||
// async function main() {
|
||||
// const argv = require('yargs').argv;
|
||||
|
||||
// console.info(process.argv);
|
||||
|
||||
// const args = [];
|
||||
// if (argv.D) args.push('-D');
|
||||
|
||||
// await execCommand2('npx lerna add --no-bootstrap --scope @joplin/plugin-repo-builder -D jest');
|
||||
|
||||
// //npx lerna add --no-bootstrap --scope @joplin/plugin-repo-builder -D jest && npx lerna bootstrap --no-ci --include-dependents --include-dependencies --scope @joplin/plugin-repo-builder
|
||||
// // process.chdir(rootDir);
|
||||
// // const version = (await execCommand2('npm version patch')).trim();
|
||||
// // const versionShort = version.substr(1);
|
||||
// // const tagName = `server-${version}`;
|
||||
|
||||
// // process.chdir(rootDir);
|
||||
// // console.info(`Running from: ${process.cwd()}`);
|
||||
|
||||
// // await execCommand2(`docker build -t "joplin/server:${versionShort}" -f Dockerfile.server .`);
|
||||
// // await execCommand2(`docker tag "joplin/server:${versionShort}" "joplin/server:latest"`);
|
||||
// // await execCommand2(`docker push joplin/server:${versionShort}`);
|
||||
// // await execCommand2('docker push joplin/server:latest');
|
||||
|
||||
// // await execCommand2('git add -A');
|
||||
// // await execCommand2(`git commit -m 'Server release ${version}'`);
|
||||
// // await execCommand2(`git tag ${tagName}`);
|
||||
// // await execCommand2('git push');
|
||||
// // await execCommand2('git push --tags');
|
||||
// }
|
||||
|
||||
// main().catch((error) => {
|
||||
// console.error('Fatal error');
|
||||
// console.error(error);
|
||||
// process.exit(1);
|
||||
// });
|
||||
@@ -14,9 +14,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Generator: Poedit 2.4.2\n"
|
||||
"POT-Creation-Date: \n"
|
||||
"PO-Revision-Date: \n"
|
||||
"X-Generator: Poedit 2.3.1\n"
|
||||
|
||||
#: packages/app-desktop/bridge.js:106 packages/app-desktop/bridge.js:110
|
||||
#: packages/app-desktop/bridge.js:126 packages/app-desktop/bridge.js:134
|
||||
@@ -63,17 +61,16 @@ msgstr "Batal"
|
||||
msgid ""
|
||||
"The app is now going to close. Please relaunch it to complete the process."
|
||||
msgstr ""
|
||||
"Aplikasi akan ditutup. Silakan luncurkan ulang untuk menyelesaikan prosesnya."
|
||||
|
||||
#: packages/app-desktop/plugins/GotoAnything.js:431
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Type a note title or part of its content to jump to it. Or type # followed "
|
||||
"by a tag name, or @ followed by a notebook name. Or type : to search for "
|
||||
"commands."
|
||||
msgstr ""
|
||||
"Ketik judul catatan atau bagian di isinya untuk temukan catatan yang dicari. "
|
||||
"Atau ketik # diikuti dengan nama label, atau @ diikuti dengan nama buku "
|
||||
"catatan. Atau ketik : untuk mencari perintah."
|
||||
"Ketik judul catatan atau bagian dari isinya untuk melompat ke sana. Atau "
|
||||
"ketik # diikuti dengan nama label, atau @ diikuti dengan nama buku catatan."
|
||||
|
||||
#: packages/app-desktop/plugins/GotoAnything.js:456
|
||||
#: packages/app-desktop/gui/KeymapConfig/utils/getLabel.js:20
|
||||
@@ -119,8 +116,9 @@ msgid "New version: %s"
|
||||
msgstr "Versi baru: %s"
|
||||
|
||||
#: packages/app-desktop/checkForUpdates.js:154
|
||||
#, fuzzy
|
||||
msgid "Download"
|
||||
msgstr "Unduh"
|
||||
msgstr "Terunduh"
|
||||
|
||||
#: packages/app-desktop/checkForUpdates.js:154
|
||||
msgid "Full Release Notes"
|
||||
@@ -279,6 +277,7 @@ msgid "strong text"
|
||||
msgstr "teks yang ditekankan lebih kuat (strong text)"
|
||||
|
||||
#: packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/CodeMirror.js:179
|
||||
#, fuzzy
|
||||
msgid "emphasised text"
|
||||
msgstr "teks yang ditekankan (emphasized text)"
|
||||
|
||||
@@ -325,6 +324,7 @@ msgid "Paste"
|
||||
msgstr "Tempel"
|
||||
|
||||
#: packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/plugins/lists.js:2151
|
||||
#, fuzzy
|
||||
msgid "Checkbox list"
|
||||
msgstr "Kotak centang"
|
||||
|
||||
@@ -355,7 +355,7 @@ msgstr "Masukkan Waktu dan Tanggal"
|
||||
|
||||
#: packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/TinyMCE.js:1003
|
||||
msgid "Drop notes or files here"
|
||||
msgstr "Taruh catatan atau file di sini"
|
||||
msgstr ""
|
||||
|
||||
#: packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/TinyMCE.js:1003
|
||||
#, fuzzy
|
||||
@@ -368,8 +368,6 @@ msgid ""
|
||||
"Please wait for all attachments to be downloaded and decrypted. You may also "
|
||||
"switch to %s to edit the note."
|
||||
msgstr ""
|
||||
"Silakan tunggu sampai semua lampiran sudah diunduh dan didekripsi. Anda juga "
|
||||
"bisa beralih ke %s untuk mengedit catatan."
|
||||
|
||||
#: packages/app-desktop/gui/NoteEditor/utils/useMessageHandler.js:73
|
||||
msgid "There was an error downloading this attachment:"
|
||||
@@ -390,7 +388,7 @@ msgstr "Simpan sebagai..."
|
||||
|
||||
#: packages/app-desktop/gui/NoteEditor/utils/contextMenu.js:74
|
||||
msgid "Reveal file in folder"
|
||||
msgstr "Buka file di berkas"
|
||||
msgstr ""
|
||||
|
||||
#: packages/app-desktop/gui/NoteEditor/utils/contextMenu.js:82
|
||||
msgid "Copy path to clipboard"
|
||||
@@ -418,26 +416,24 @@ msgid ""
|
||||
"This Rich Text editor has a number of limitations and it is recommended to "
|
||||
"be aware of them before using it."
|
||||
msgstr ""
|
||||
"Editor Rich Text ini punya beberapa keterbatasan dan Anda dianjurkan untuk "
|
||||
"tahu keterbatasannya sebelum menggunakan editor ini."
|
||||
|
||||
#: packages/app-desktop/gui/NoteEditor/NoteEditor.js:340
|
||||
msgid "Read more about it"
|
||||
msgstr "Baca lebih lanjut"
|
||||
msgstr ""
|
||||
|
||||
#: packages/app-desktop/gui/NoteEditor/NoteEditor.js:345
|
||||
msgid "Dismiss"
|
||||
msgstr "Abaikan"
|
||||
msgstr ""
|
||||
|
||||
#: packages/app-desktop/gui/NoteEditor/NoteEditor.js:381
|
||||
msgid "The following attachments are being watched for changes:"
|
||||
msgstr "Lampiran ini sedang diawasi untuk perubahan:"
|
||||
msgstr ""
|
||||
|
||||
#: packages/app-desktop/gui/NoteEditor/NoteEditor.js:384
|
||||
msgid ""
|
||||
"The attachments will no longer be watched when you switch to a different "
|
||||
"note."
|
||||
msgstr "Lampiran tidak akan diawasi ketika Anda berganti ke catatan lain."
|
||||
msgstr ""
|
||||
|
||||
#: packages/app-desktop/gui/NoteEditor/NoteEditor.js:389
|
||||
#, javascript-format
|
||||
@@ -485,32 +481,34 @@ msgid "Horizontal Rule"
|
||||
msgstr "Garis Horisontal"
|
||||
|
||||
#: packages/app-desktop/gui/NoteEditor/commands/editorCommandDeclarations.js:88
|
||||
#, fuzzy
|
||||
msgid "Delete line"
|
||||
msgstr "Hapus catatan"
|
||||
msgstr "Hapus catatan?"
|
||||
|
||||
#: packages/app-desktop/gui/NoteEditor/commands/editorCommandDeclarations.js:92
|
||||
msgid "Undo"
|
||||
msgstr "Urungkan"
|
||||
msgstr ""
|
||||
|
||||
#: packages/app-desktop/gui/NoteEditor/commands/editorCommandDeclarations.js:96
|
||||
msgid "Redo"
|
||||
msgstr "Ulangi"
|
||||
msgstr ""
|
||||
|
||||
#: packages/app-desktop/gui/NoteEditor/commands/editorCommandDeclarations.js:100
|
||||
msgid "Indent less"
|
||||
msgstr "Kurangi indentasi"
|
||||
msgstr ""
|
||||
|
||||
#: packages/app-desktop/gui/NoteEditor/commands/editorCommandDeclarations.js:104
|
||||
msgid "Indent more"
|
||||
msgstr "Tambah indentasi"
|
||||
msgstr ""
|
||||
|
||||
#: packages/app-desktop/gui/NoteEditor/commands/editorCommandDeclarations.js:108
|
||||
#, fuzzy
|
||||
msgid "Toggle comment"
|
||||
msgstr "Lihat/sembunyikan komentar"
|
||||
msgstr "Alihkan daftar catatan"
|
||||
|
||||
#: packages/app-desktop/gui/NoteEditor/commands/editorCommandDeclarations.js:112
|
||||
msgid "Sort selected lines"
|
||||
msgstr "Sortir baris terpilih"
|
||||
msgstr ""
|
||||
|
||||
#: packages/app-desktop/gui/NoteEditor/commands/editorCommandDeclarations.js:116
|
||||
msgid "Swap line up"
|
||||
@@ -582,9 +580,9 @@ msgstr "Properti catatan"
|
||||
|
||||
#: packages/app-desktop/gui/KeymapConfig/KeymapConfigScreen.js:63
|
||||
#: packages/lib/services/KeymapService.js:176
|
||||
#, javascript-format
|
||||
#, fuzzy, javascript-format
|
||||
msgid "Error: %s"
|
||||
msgstr "Terjadi kesalahan: %s"
|
||||
msgstr "Kesalahan"
|
||||
|
||||
#: packages/app-desktop/gui/KeymapConfig/KeymapConfigScreen.js:110
|
||||
#: packages/app-desktop/gui/EncryptionConfigScreen.min.js:443
|
||||
@@ -601,11 +599,12 @@ msgstr "Impor"
|
||||
|
||||
#: packages/app-desktop/gui/KeymapConfig/KeymapConfigScreen.js:126
|
||||
msgid "Command"
|
||||
msgstr "Perintah"
|
||||
msgstr ""
|
||||
|
||||
#: packages/app-desktop/gui/KeymapConfig/KeymapConfigScreen.js:127
|
||||
#, fuzzy
|
||||
msgid "Keyboard Shortcut"
|
||||
msgstr "Pintasan Papan Ketik"
|
||||
msgstr "Mode Papan Ketik"
|
||||
|
||||
#: packages/app-desktop/gui/KeymapConfig/utils/getLabel.js:14
|
||||
#: packages/app-desktop/gui/MenuBar.js:156 packages/app-desktop/app.js:338
|
||||
@@ -628,8 +627,9 @@ msgid "Website and documentation"
|
||||
msgstr "Situs web dan dokumentasi"
|
||||
|
||||
#: packages/app-desktop/gui/KeymapConfig/utils/getLabel.js:24
|
||||
#, fuzzy
|
||||
msgid "Hide Joplin"
|
||||
msgstr "Sembunyikan Joplin"
|
||||
msgstr "Tentang Joplin"
|
||||
|
||||
#: packages/app-desktop/gui/KeymapConfig/utils/getLabel.js:26
|
||||
#: packages/app-desktop/gui/MenuBar.js:408
|
||||
@@ -637,8 +637,9 @@ msgid "Close Window"
|
||||
msgstr "Tutup jendela"
|
||||
|
||||
#: packages/app-desktop/gui/KeymapConfig/utils/getLabel.js:30
|
||||
#, fuzzy
|
||||
msgid "Preferences"
|
||||
msgstr "Preferensi"
|
||||
msgstr "Preferensi..."
|
||||
|
||||
#: packages/app-desktop/gui/KeymapConfig/utils/getLabel.js:30
|
||||
#: packages/app-desktop/gui/MenuBar.js:284 packages/app-desktop/gui/Root.js:100
|
||||
@@ -646,20 +647,19 @@ msgid "Options"
|
||||
msgstr "Pilihan"
|
||||
|
||||
#: packages/app-desktop/gui/KeymapConfig/utils/getLabel.js:37
|
||||
#, fuzzy
|
||||
msgid "Invalid"
|
||||
msgstr "Jawaban tidak valid"
|
||||
msgstr "Jawaban tidak valid: %s"
|
||||
|
||||
#: packages/app-desktop/gui/KeymapConfig/ShortcutRecorder.js:49
|
||||
msgid "Press the shortcut"
|
||||
msgstr "Klik pintasan"
|
||||
msgstr ""
|
||||
|
||||
#: packages/app-desktop/gui/KeymapConfig/ShortcutRecorder.js:49
|
||||
msgid ""
|
||||
"Press the shortcut and then press ENTER. Or, press BACKSPACE to clear the "
|
||||
"shortcut."
|
||||
msgstr ""
|
||||
"Klik pintasan kemudian tekan ENTER atau tekan BACKSPACE untuk menghapus "
|
||||
"pintasan."
|
||||
|
||||
#: packages/app-desktop/gui/KeymapConfig/ShortcutRecorder.js:50
|
||||
#: packages/app-desktop/gui/EncryptionConfigScreen.min.js:96
|
||||
@@ -673,13 +673,11 @@ msgid ""
|
||||
"may take a few minutes to complete and the app needs to be restarted. To "
|
||||
"proceed please click on the link."
|
||||
msgstr ""
|
||||
"Target sinkronisasi harus diperbarui sebelum Joplin dapat sinkronisasi. "
|
||||
"Operasinya akan berjalan beberapa menit dan aplikasi perlu dimulai ulang. "
|
||||
"Untuk melanjutkan, silakan klik linknya."
|
||||
|
||||
#: packages/app-desktop/gui/MainScreen/MainScreen.js:405
|
||||
#, fuzzy
|
||||
msgid "Restart and upgrade"
|
||||
msgstr "Mulai ulang dan upgrade"
|
||||
msgstr "Kunci master yang perlu upgrade"
|
||||
|
||||
#: packages/app-desktop/gui/MainScreen/MainScreen.js:409
|
||||
msgid "Some items cannot be synchronised."
|
||||
@@ -721,8 +719,6 @@ msgstr "Info lain"
|
||||
#: packages/app-desktop/gui/MainScreen/MainScreen.js:528
|
||||
msgid "Use the arrows to move the layout items. Press \"Escape\" to exit."
|
||||
msgstr ""
|
||||
"Gunakan tanda panah untuk memindahkan item tata letak. Tekan \"Escape\" "
|
||||
"untuk keluar."
|
||||
|
||||
#: packages/app-desktop/gui/MainScreen/commands/showNoteContentProperties.js:18
|
||||
msgid "Statistics..."
|
||||
@@ -786,12 +782,13 @@ msgid "Toggle editor layout"
|
||||
msgstr "Alihkan tata letak editor"
|
||||
|
||||
#: packages/app-desktop/gui/MainScreen/commands/toggleEditors.js:18
|
||||
#, fuzzy
|
||||
msgid "Toggle editors"
|
||||
msgstr "Alihkan editor"
|
||||
msgstr "Alihkan tata letak editor"
|
||||
|
||||
#: packages/app-desktop/gui/MainScreen/commands/toggleLayoutMoveMode.js:16
|
||||
msgid "Change application layout"
|
||||
msgstr "Ubah tata letak aplikasi"
|
||||
msgstr ""
|
||||
|
||||
#: packages/app-desktop/gui/MainScreen/commands/renameTag.js:30
|
||||
msgid "Rename tag:"
|
||||
@@ -808,7 +805,7 @@ msgstr "Judul buku catatan:"
|
||||
#: packages/app-desktop/gui/MainScreen/commands/showSpellCheckerMenu.js:19
|
||||
#: packages/lib/services/spellChecker/SpellCheckerService.js:180
|
||||
msgid "Spell checker"
|
||||
msgstr "Pemeriksa ejaan"
|
||||
msgstr ""
|
||||
|
||||
#: packages/app-desktop/gui/MainScreen/commands/showShareNoteDialog.js:16
|
||||
msgid "Share note..."
|
||||
@@ -1002,8 +999,9 @@ msgstr "Templat"
|
||||
|
||||
#: packages/app-desktop/gui/MenuBar.js:377
|
||||
#: packages/app-desktop/gui/MenuBar.js:423
|
||||
#, fuzzy
|
||||
msgid "Export all"
|
||||
msgstr "Ekspor semuanya"
|
||||
msgstr "Ekspor"
|
||||
|
||||
#: packages/app-desktop/gui/MenuBar.js:389
|
||||
#, javascript-format
|
||||
@@ -1238,23 +1236,27 @@ msgstr ""
|
||||
"Penting: Anda hanya perlu menjalankan ini SEKALI pada satu perangkat."
|
||||
|
||||
#: packages/app-desktop/gui/EncryptionConfigScreen.min.js:198
|
||||
#, fuzzy
|
||||
msgid "Re-encryption"
|
||||
msgstr "Enkripsi ulang"
|
||||
msgstr "Enkripsi"
|
||||
|
||||
#: packages/app-desktop/gui/EncryptionConfigScreen.min.js:213
|
||||
msgid "Ignore"
|
||||
msgstr "Abaikan"
|
||||
msgstr ""
|
||||
|
||||
#: packages/app-desktop/gui/EncryptionConfigScreen.min.js:244
|
||||
#: packages/app-mobile/components/screens/encryption-config.js:215
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Disabling encryption means *all* your notes and attachments are going to be "
|
||||
"re-synchronised and sent unencrypted to the sync target. Do you wish to "
|
||||
"continue?"
|
||||
msgstr ""
|
||||
"Menonaktifkan enkripsi berarti *semua* catatan dan lampiran Anda akan "
|
||||
"disinkronkan ulang dan dikirim dalam keadaan tidak terenkripsi ke target "
|
||||
"sinkronisasi. Apa Anda mau lanjut?"
|
||||
"Mengaktifkan enkripsi berarti *semua* catatan dan lampiran Anda akan "
|
||||
"disinkronkan ulang dan dikirim dalam keadaan terenkripsi ke target "
|
||||
"sinkronisasi. Jangan sampai kehilangan kata sandinya karena, untuk alasan "
|
||||
"keamanan, ini akan menjadi *hanya* satu-satunya cara untuk mendekripsi data! "
|
||||
"Untuk mengaktifkan enkripsi, silakan masukkan kata sandi Anda di bawah ini."
|
||||
|
||||
#: packages/app-desktop/gui/EncryptionConfigScreen.min.js:246
|
||||
#: packages/app-mobile/components/screens/encryption-config.js:150
|
||||
@@ -1267,8 +1269,8 @@ msgstr ""
|
||||
"Mengaktifkan enkripsi berarti *semua* catatan dan lampiran Anda akan "
|
||||
"disinkronkan ulang dan dikirim dalam keadaan terenkripsi ke target "
|
||||
"sinkronisasi. Jangan sampai kehilangan kata sandinya karena, untuk alasan "
|
||||
"keamanan, ini *hanya* satu-satunya cara untuk mendekripsi data! Untuk "
|
||||
"mengaktifkan enkripsi, silakan masukkan kata sandi Anda di bawah ini."
|
||||
"keamanan, ini akan menjadi *hanya* satu-satunya cara untuk mendekripsi data! "
|
||||
"Untuk mengaktifkan enkripsi, silakan masukkan kata sandi Anda di bawah ini."
|
||||
|
||||
#: packages/app-desktop/gui/EncryptionConfigScreen.min.js:275
|
||||
#: packages/app-mobile/components/screens/encryption-config.js:258
|
||||
@@ -1281,24 +1283,28 @@ msgid "Enable encryption"
|
||||
msgstr "Aktifkan enkripsi"
|
||||
|
||||
#: packages/app-desktop/gui/EncryptionConfigScreen.min.js:290
|
||||
#, fuzzy
|
||||
msgid "Master Keys"
|
||||
msgstr "Kunci Master"
|
||||
msgstr "Kunci Master %s"
|
||||
|
||||
#: packages/app-desktop/gui/EncryptionConfigScreen.min.js:304
|
||||
#, fuzzy
|
||||
msgid "Active"
|
||||
msgstr "Aktif"
|
||||
msgstr "Aksi"
|
||||
|
||||
#: packages/app-desktop/gui/EncryptionConfigScreen.min.js:314
|
||||
msgid "Source"
|
||||
msgstr "Sumber"
|
||||
msgstr ""
|
||||
|
||||
#: packages/app-desktop/gui/EncryptionConfigScreen.min.js:329
|
||||
#, fuzzy
|
||||
msgid "Password"
|
||||
msgstr "Kata sandi"
|
||||
msgstr "Kata sandi:"
|
||||
|
||||
#: packages/app-desktop/gui/EncryptionConfigScreen.min.js:334
|
||||
#, fuzzy
|
||||
msgid "Password OK"
|
||||
msgstr "Kata sandi OK"
|
||||
msgstr "Kata sandi:"
|
||||
|
||||
#: packages/app-desktop/gui/EncryptionConfigScreen.min.js:343
|
||||
msgid ""
|
||||
@@ -1306,10 +1312,6 @@ msgid ""
|
||||
"as \"active\"). Any of the keys might be used for decryption, depending on "
|
||||
"how the notes or notebooks were originally encrypted."
|
||||
msgstr ""
|
||||
"Peringatan: Hanya satu kunci master yang akan digunakan untuk enkripsi "
|
||||
"(kunci yang ditandai \"aktif\"). Kunci yang lain mungkin digunakan untuk "
|
||||
"dekripsi, tergantung bagaimana buku catatan atau catatannya awalnya "
|
||||
"dienkripsi."
|
||||
|
||||
#: packages/app-desktop/gui/EncryptionConfigScreen.min.js:371
|
||||
#: packages/app-mobile/components/screens/encryption-config.js:248
|
||||
@@ -1420,7 +1422,7 @@ msgstr "Telusuri..."
|
||||
|
||||
#: packages/app-desktop/gui/ConfigScreen/ConfigScreen.js:456
|
||||
msgid "The application must be restarted for these changes to take effect."
|
||||
msgstr "Aplikasi harus dimulai ulang agar perubahan ini diterapkan."
|
||||
msgstr ""
|
||||
|
||||
#: packages/app-desktop/gui/ConfigScreen/ConfigScreen.js:468
|
||||
#: packages/app-desktop/gui/NoteList/NoteList.js:163
|
||||
@@ -1429,24 +1431,25 @@ msgstr "Lakukan sekarang"
|
||||
|
||||
#: packages/app-desktop/gui/ConfigScreen/ConfigScreen.js:468
|
||||
msgid "Later"
|
||||
msgstr "Nanti"
|
||||
msgstr ""
|
||||
|
||||
#: packages/app-desktop/gui/ConfigScreen/ConfigScreen.js:521
|
||||
#, fuzzy
|
||||
msgid "Restart now"
|
||||
msgstr "Mulai ulang sekarang"
|
||||
msgstr "Dapatkan sekarang:"
|
||||
|
||||
#: packages/app-desktop/gui/ConfigScreen/ButtonBar.js:27
|
||||
msgid "Apply"
|
||||
msgstr "Terapkan"
|
||||
|
||||
#: packages/app-desktop/gui/ConfigScreen/controls/PluginsStates.js:137
|
||||
#, javascript-format
|
||||
#, fuzzy, javascript-format
|
||||
msgid "Delete plugin \"%s\"?"
|
||||
msgstr "Hapus plugin \"%s\"?"
|
||||
msgstr "Hapus catatan \"%s\"?"
|
||||
|
||||
#: packages/app-desktop/gui/ConfigScreen/controls/PluginsStates.js:181
|
||||
msgid "Install plugin"
|
||||
msgstr "Pasang plugin"
|
||||
msgstr ""
|
||||
|
||||
#: packages/app-desktop/gui/PromptDialog.min.js:249
|
||||
msgid "Clear"
|
||||
@@ -1483,11 +1486,12 @@ msgstr "Viewer"
|
||||
#: packages/app-desktop/gui/NoteContentPropertiesDialog.js:105
|
||||
#, javascript-format
|
||||
msgid "Read time: %s min"
|
||||
msgstr "Waktu baca: %s menit"
|
||||
msgstr ""
|
||||
|
||||
#: packages/app-desktop/gui/NoteContentPropertiesDialog.js:108
|
||||
#, fuzzy
|
||||
msgid "Statistics"
|
||||
msgstr "Statistik"
|
||||
msgstr "Statistik..."
|
||||
|
||||
#: packages/app-desktop/gui/NoteContentPropertiesDialog.js:113
|
||||
#: packages/app-desktop/gui/ShareNoteDialog.js:175
|
||||
@@ -1615,16 +1619,18 @@ msgid_plural "Copy Shareable Links"
|
||||
msgstr[0] "Salin Tautan yang Dapat Dibagikan"
|
||||
|
||||
#: packages/app-desktop/commands/toggleExternalEditing.js:18
|
||||
#, fuzzy
|
||||
msgid "Toggle external editing"
|
||||
msgstr "Ubah pengeditan eksternal"
|
||||
msgstr "Hentikan pengeditan eksternal"
|
||||
|
||||
#: packages/app-desktop/commands/toggleExternalEditing.js:37
|
||||
msgid "Stop"
|
||||
msgstr ""
|
||||
|
||||
#: packages/app-desktop/commands/copyDevCommand.js:18
|
||||
#, fuzzy
|
||||
msgid "Copy dev mode command to clipboard"
|
||||
msgstr "Salin perintah dev mode ke papan klip"
|
||||
msgstr "Salin jalur ke papan klip"
|
||||
|
||||
#: packages/app-desktop/commands/stopExternalEditing.js:18
|
||||
msgid "Stop external editing"
|
||||
@@ -1641,8 +1647,9 @@ msgid "Error opening note in editor: %s"
|
||||
msgstr "Terjadi kesalahan saat membuka catatan di editor: %s"
|
||||
|
||||
#: packages/app-desktop/commands/openProfileDirectory.js:18
|
||||
#, fuzzy
|
||||
msgid "Open profile directory"
|
||||
msgstr "Buka direktori profil"
|
||||
msgstr "Buka direktori templat"
|
||||
|
||||
#: packages/app-desktop/app.js:336
|
||||
#, javascript-format
|
||||
@@ -1670,8 +1677,9 @@ msgid "Save alarm"
|
||||
msgstr "Simpan alarm"
|
||||
|
||||
#: packages/app-mobile/components/NoteBodyViewer/hooks/useOnResourceLongPress.js:28
|
||||
#, fuzzy
|
||||
msgid "Open"
|
||||
msgstr "Buka"
|
||||
msgstr "Buka..."
|
||||
|
||||
#: packages/app-mobile/components/NoteBodyViewer/hooks/useOnResourceLongPress.js:29
|
||||
#: packages/app-mobile/components/screens/Note.js:796
|
||||
@@ -1742,9 +1750,8 @@ msgid "Refresh"
|
||||
msgstr "Segarkan"
|
||||
|
||||
#: packages/app-mobile/components/screens/UpgradeSyncTargetScreen.js:42
|
||||
#, fuzzy
|
||||
msgid "Sync Target Upgrade"
|
||||
msgstr "Sinkronisasi Target Peningkatan"
|
||||
msgstr ""
|
||||
|
||||
#: packages/app-mobile/components/screens/notes.js:154
|
||||
#: packages/app-cli/app/command-rmbook.js:26
|
||||
@@ -1960,14 +1967,11 @@ msgid ""
|
||||
"\n"
|
||||
"You may turn off this option at any time in the Configuration screen."
|
||||
msgstr ""
|
||||
"Untuk menghubungkan geolokasi dengan catatan, aplikasi perlu izin Anda untuk "
|
||||
"mengakses lokasi Anda.\n"
|
||||
"\n"
|
||||
"Anda dapat mematikan fungsi ini kapan saja di layar Konfigurasi."
|
||||
|
||||
#: packages/app-mobile/components/screens/Note.js:343
|
||||
#, fuzzy
|
||||
msgid "Permission needed"
|
||||
msgstr "Izin diperlukan"
|
||||
msgstr "Izin penggunaan kamera"
|
||||
|
||||
#: packages/app-mobile/components/screens/Note.js:449
|
||||
#: packages/app-cli/app/command-rmnote.js:27
|
||||
@@ -2048,12 +2052,11 @@ msgid ""
|
||||
"The default admin password is insecure and has not been changed! [Change it "
|
||||
"now](%s)"
|
||||
msgstr ""
|
||||
"Kata sandi default admin tidak aman dan belum diubah. [Ubah sekarang](%s)"
|
||||
|
||||
#: packages/lib/onedrive-api-node-utils.js:46
|
||||
#, javascript-format
|
||||
msgid "All potential ports are in use - please report the issue at %s"
|
||||
msgstr "Semua port potensial sedang digunakan - silakan laporkan isu di %s"
|
||||
msgstr ""
|
||||
|
||||
#: packages/lib/onedrive-api-node-utils.js:86
|
||||
msgid ""
|
||||
@@ -2089,8 +2092,9 @@ msgid "Dropbox"
|
||||
msgstr "Dropbox"
|
||||
|
||||
#: packages/lib/SyncTargetJoplinServer.js:30
|
||||
#, fuzzy
|
||||
msgid "Joplin Server"
|
||||
msgstr "Server Joplin"
|
||||
msgstr "Situs web Joplin"
|
||||
|
||||
#: packages/lib/shim-init-node.js:201
|
||||
#, javascript-format
|
||||
@@ -2235,19 +2239,21 @@ msgstr ""
|
||||
|
||||
#: packages/lib/models/Setting.js:259
|
||||
msgid "Joplin Server URL"
|
||||
msgstr "URL Server Joplin"
|
||||
msgstr ""
|
||||
|
||||
#: packages/lib/models/Setting.js:273
|
||||
#, fuzzy
|
||||
msgid "Joplin Server Directory"
|
||||
msgstr "Direktori Ekspor Joplin"
|
||||
|
||||
#: packages/lib/models/Setting.js:283
|
||||
msgid "Joplin Server username"
|
||||
msgstr "Nama pengguna Server Joplin"
|
||||
msgstr ""
|
||||
|
||||
#: packages/lib/models/Setting.js:293
|
||||
#, fuzzy
|
||||
msgid "Joplin Server password"
|
||||
msgstr "Kata sandi Server Joplin"
|
||||
msgstr "Masukkan kata sandi master:"
|
||||
|
||||
#: packages/lib/models/Setting.js:305
|
||||
msgid "Attachment download behaviour"
|
||||
@@ -2380,8 +2386,9 @@ msgid "Enable typographer support"
|
||||
msgstr "Aktifkan dukungan typographer"
|
||||
|
||||
#: packages/lib/models/Setting.js:562
|
||||
#, fuzzy
|
||||
msgid "Enable Linkify"
|
||||
msgstr "Aktifkan Linkify"
|
||||
msgstr "Aktifkan riwayat catatan"
|
||||
|
||||
#: packages/lib/models/Setting.js:563
|
||||
msgid "Enable math expressions"
|
||||
@@ -2396,16 +2403,17 @@ msgid "Enable Mermaid diagrams support"
|
||||
msgstr "Aktifkan dukungan diagram Mermaid"
|
||||
|
||||
#: packages/lib/models/Setting.js:566
|
||||
#, fuzzy
|
||||
msgid "Enable audio player"
|
||||
msgstr "Aktifkan pemutar audio"
|
||||
msgstr "Aktifkan emoji markdown"
|
||||
|
||||
#: packages/lib/models/Setting.js:567
|
||||
msgid "Enable video player"
|
||||
msgstr "Aktifkan pemutar video"
|
||||
msgstr ""
|
||||
|
||||
#: packages/lib/models/Setting.js:568
|
||||
msgid "Enable PDF viewer"
|
||||
msgstr "Aktifkan penampil PDF"
|
||||
msgstr ""
|
||||
|
||||
#: packages/lib/models/Setting.js:569
|
||||
msgid "Enable ==mark== syntax"
|
||||
@@ -2482,18 +2490,20 @@ msgid "Editor font family"
|
||||
msgstr "Keluarga font pada editor"
|
||||
|
||||
#: packages/lib/models/Setting.js:641
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"This should be a *monospace* font or some elements will render incorrectly. "
|
||||
"If the font is incorrect or empty, it will default to a generic monospace "
|
||||
"font."
|
||||
msgstr ""
|
||||
"Ini harus font *monospace* atau beberapa elemen tidak akan berfungsi "
|
||||
"sebagaimana mestinya. Jika font tidak benar atau kosong, font akan disetel "
|
||||
"secara otomatis ke font monospace generik."
|
||||
"Ini harus font *monospace* atau ia tidak akan berfungsi sebagaimana "
|
||||
"mestinya. Jika font tidak benar atau kosong, font akan disetel secara "
|
||||
"otomatis ke font monospace generik."
|
||||
|
||||
#: packages/lib/models/Setting.js:662
|
||||
#, fuzzy
|
||||
msgid "Custom stylesheet for rendered Markdown"
|
||||
msgstr "Lembar gaya untuk rendering Markdown"
|
||||
msgstr "Lembar gaya khusus untuk gaya keseluruhan aplikasi Joplin"
|
||||
|
||||
#: packages/lib/models/Setting.js:678
|
||||
msgid "Custom stylesheet for Joplin-wide app styles"
|
||||
@@ -2724,8 +2734,9 @@ msgid "Web Clipper"
|
||||
msgstr "Web Clipper"
|
||||
|
||||
#: packages/lib/models/Setting.js:1389
|
||||
#, fuzzy
|
||||
msgid "Keyboard Shortcuts"
|
||||
msgstr "Pintasan Papan Ketik"
|
||||
msgstr "Mode Papan Ketik"
|
||||
|
||||
#: packages/lib/models/Setting.js:1396
|
||||
msgid ""
|
||||
@@ -2763,20 +2774,17 @@ msgid "Downloaded"
|
||||
msgstr "Terunduh"
|
||||
|
||||
#: packages/lib/models/Resource.js:382
|
||||
#, javascript-format
|
||||
#, fuzzy, javascript-format
|
||||
msgid "Attachment conflict: \"%s\""
|
||||
msgstr "Konflik lampiran: \"%s\""
|
||||
msgstr "Lampiran"
|
||||
|
||||
#: packages/lib/models/Resource.js:383
|
||||
#, javascript-format
|
||||
#, fuzzy, javascript-format
|
||||
msgid ""
|
||||
"There was a [conflict](%s) on the attachment below.\n"
|
||||
"\n"
|
||||
"%s"
|
||||
msgstr ""
|
||||
"Terjadi konflik (%s) saat mengunduh lampiran ini:\n"
|
||||
"\n"
|
||||
"%s"
|
||||
msgstr "Terjadi kesalahan saat mengunduh lampiran ini:"
|
||||
|
||||
#: packages/lib/models/Tag.js:202
|
||||
#, javascript-format
|
||||
@@ -2970,7 +2978,6 @@ msgstr "Sedang berlangsung"
|
||||
msgid ""
|
||||
"Unknown item type downloaded - please upgrade Joplin to the latest version"
|
||||
msgstr ""
|
||||
"Tipe item tidak dikenal diunduh - silakan perbarui Joplin ke versi terbaru"
|
||||
|
||||
#: packages/lib/JoplinServerApi.js:71
|
||||
#, javascript-format
|
||||
@@ -3000,7 +3007,7 @@ msgstr "Sistem berkas"
|
||||
|
||||
#: packages/lib/commands/historyForward.js:17
|
||||
msgid "Forward"
|
||||
msgstr "Maju"
|
||||
msgstr ""
|
||||
|
||||
#: packages/lib/versionInfo.js:10
|
||||
#, javascript-format
|
||||
@@ -3030,7 +3037,7 @@ msgstr "Versi Profil: %s"
|
||||
#: packages/lib/versionInfo.js:25
|
||||
#, javascript-format
|
||||
msgid "Keychain Supported: %s"
|
||||
msgstr "Keychain Didukung: %s"
|
||||
msgstr ""
|
||||
|
||||
#: packages/lib/services/RevisionService.js:221
|
||||
msgid "Restored Notes"
|
||||
@@ -3079,14 +3086,14 @@ msgid "HTML Directory"
|
||||
msgstr "Direktori HTML"
|
||||
|
||||
#: packages/lib/services/interop/InteropService.js:127
|
||||
#, javascript-format
|
||||
#, fuzzy, javascript-format
|
||||
msgid "Cannot load \"%s\" module for format \"%s\" and output \"%s\""
|
||||
msgstr "Tidak dapat memuat modul \"%s\" untuk format \"%s\" dan output \"%s\""
|
||||
msgstr "Tidak dapat memuat modul \"%s\" untuk format \"%s\""
|
||||
|
||||
#: packages/lib/services/interop/InteropService.js:150
|
||||
#, javascript-format
|
||||
#, fuzzy, javascript-format
|
||||
msgid "Cannot load \"%s\" module for format \"%s\" and target \"%s\""
|
||||
msgstr "Tidak dapat memuat modul \"%s\" untuk format \"%s\" dan target \"%s\""
|
||||
msgstr "Tidak dapat memuat modul \"%s\" untuk format \"%s\""
|
||||
|
||||
#: packages/lib/services/interop/InteropService.js:194
|
||||
#: packages/lib/services/interop/InteropService.js:206
|
||||
@@ -3124,23 +3131,23 @@ msgstr "Silakan tentukan format impor untuk %s"
|
||||
|
||||
#: packages/lib/services/KeymapService.js:273
|
||||
msgid "command"
|
||||
msgstr "perintah"
|
||||
msgstr ""
|
||||
|
||||
#: packages/lib/services/KeymapService.js:273
|
||||
#: packages/lib/services/KeymapService.js:278
|
||||
#, javascript-format
|
||||
msgid "\"%s\" is missing the required \"%s\" property."
|
||||
msgstr "\"%s\" tidak menemukan properti \"%s\"."
|
||||
msgstr ""
|
||||
|
||||
#: packages/lib/services/KeymapService.js:278
|
||||
#: packages/lib/services/KeymapService.js:285
|
||||
msgid "accelerator"
|
||||
msgstr "akselerator"
|
||||
msgstr ""
|
||||
|
||||
#: packages/lib/services/KeymapService.js:285
|
||||
#, javascript-format
|
||||
#, fuzzy, javascript-format
|
||||
msgid "Invalid %s: %s."
|
||||
msgstr "%s tidak valid: %s."
|
||||
msgstr "Jawaban tidak valid: %s"
|
||||
|
||||
#: packages/lib/services/KeymapService.js:303
|
||||
#, javascript-format
|
||||
@@ -3148,13 +3155,11 @@ msgid ""
|
||||
"Accelerator \"%s\" is used for \"%s\" and \"%s\" commands. This may lead to "
|
||||
"unexpected behaviour."
|
||||
msgstr ""
|
||||
"Akselerator \"%s\" digunakan untuk perintah \"%s\" dan \"%s\". Ini bisa "
|
||||
"memberikan dampak tidak terduga."
|
||||
|
||||
#: packages/lib/services/KeymapService.js:328
|
||||
#, javascript-format
|
||||
msgid "Accelerator \"%s\" is not valid."
|
||||
msgstr "Akselerator \"%s\" tidak valid."
|
||||
msgstr ""
|
||||
|
||||
#: packages/lib/services/report.js:121
|
||||
msgid "Items that cannot be synchronised"
|
||||
@@ -3218,8 +3223,9 @@ msgid "Downloaded and encrypted"
|
||||
msgstr "Terunduh dan terenkripsi"
|
||||
|
||||
#: packages/lib/services/report.js:193
|
||||
#, fuzzy
|
||||
msgid "Created locally"
|
||||
msgstr "Item lokal yang dibuat"
|
||||
msgstr "Item lokal yang dibuat: %d."
|
||||
|
||||
#: packages/lib/services/report.js:206
|
||||
msgid "Attachments that could not be downloaded"
|
||||
@@ -3274,19 +3280,20 @@ msgstr "Di %s: %s"
|
||||
|
||||
#: packages/lib/services/spellChecker/SpellCheckerService.js:107
|
||||
msgid "No suggestions"
|
||||
msgstr "Tidak ada saran"
|
||||
msgstr ""
|
||||
|
||||
#: packages/lib/services/spellChecker/SpellCheckerService.js:114
|
||||
msgid "Add to dictionary"
|
||||
msgstr "Tambahkan ke kamus"
|
||||
msgstr ""
|
||||
|
||||
#: packages/lib/services/spellChecker/SpellCheckerService.js:153
|
||||
msgid "Use spell checker"
|
||||
msgstr "Gunakan pemeriksa ejaan"
|
||||
msgstr ""
|
||||
|
||||
#: packages/lib/services/spellChecker/SpellCheckerService.js:173
|
||||
#, fuzzy
|
||||
msgid "Change language"
|
||||
msgstr "Ubah bahasa"
|
||||
msgstr "Bahasa"
|
||||
|
||||
#: packages/app-cli/app/command-cp.js:13
|
||||
msgid ""
|
||||
@@ -3361,9 +3368,9 @@ msgid "Do not ask for confirmation."
|
||||
msgstr "Jangan meminta konfirmasi."
|
||||
|
||||
#: packages/app-cli/app/command-import.js:27
|
||||
#, javascript-format
|
||||
#, fuzzy, javascript-format
|
||||
msgid "Output format: %s"
|
||||
msgstr "Format output: %s"
|
||||
msgstr "Format sumber: %s"
|
||||
|
||||
#: packages/app-cli/app/command-import.js:65
|
||||
msgid "Importing notes..."
|
||||
@@ -3517,7 +3524,7 @@ msgstr ""
|
||||
|
||||
#: packages/app-cli/app/command-sync.js:35
|
||||
msgid "Upgrade the sync target to the latest version."
|
||||
msgstr "Perbarui target sinkronisasi ke versi terakhir."
|
||||
msgstr ""
|
||||
|
||||
#: packages/app-cli/app/command-sync.js:105
|
||||
#, javascript-format
|
||||
@@ -3547,6 +3554,7 @@ msgid "Synchronisation target: %s (%s)"
|
||||
msgstr "Target sinkronisasi: %s (%s)"
|
||||
|
||||
#: packages/app-cli/app/command-sync.js:177
|
||||
#, fuzzy
|
||||
msgid "Cannot initialise synchroniser."
|
||||
msgstr "Tidak dapat menginisiasi penyinkron."
|
||||
|
||||
@@ -3561,7 +3569,7 @@ msgstr "Mengunduh sumber daya..."
|
||||
#: packages/app-cli/app/command-sync.js:242
|
||||
#, javascript-format
|
||||
msgid "Sync target must be upgraded! Run `%s` to proceed."
|
||||
msgstr "Target sinkronisasi harus diperbarui. Jalankan `%s` untuk melanjutkan."
|
||||
msgstr ""
|
||||
|
||||
#: packages/app-cli/app/command-sync.js:260
|
||||
msgid "Cancelling... Please wait."
|
||||
@@ -3620,11 +3628,12 @@ msgstr "Catatan tidak ada: \"%s\". Buat?"
|
||||
|
||||
#: packages/app-cli/app/command-edit.js:75
|
||||
msgid "Starting to edit note. Close the editor to get back to the prompt."
|
||||
msgstr "Mulai mengedit catatan. Tutup editor untuk kembali ke prompt."
|
||||
msgstr ""
|
||||
|
||||
#: packages/app-cli/app/command-edit.js:97
|
||||
#, fuzzy
|
||||
msgid "Note has been saved."
|
||||
msgstr "Catatan sudah disimpan."
|
||||
msgstr "Belum ada buku catatan yang ditentukan."
|
||||
|
||||
#: packages/app-cli/app/app-gui.js:452
|
||||
msgid "To delete a tag, untag the associated notes."
|
||||
|
||||
2
packages/tools/package-lock.json
generated
2
packages/tools/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/tools",
|
||||
"version": "1.7.2",
|
||||
"version": "1.0.16",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/tools",
|
||||
"version": "1.7.2",
|
||||
"version": "1.0.16",
|
||||
"description": "Various tools for Joplin",
|
||||
"main": "index.js",
|
||||
"author": "Laurent Cozic",
|
||||
@@ -18,7 +18,7 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@joplin/lib": "^1.7.2",
|
||||
"@joplin/lib": "^1.0.16",
|
||||
"execa": "^4.1.0",
|
||||
"fs-extra": "^4.0.3",
|
||||
"gettext-parser": "^1.3.0",
|
||||
|
||||
@@ -1,40 +1,37 @@
|
||||
'use strict';
|
||||
const __awaiter = (this && this.__awaiter) || function(thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function(resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function(resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator['throw'](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, '__esModule', { value: true });
|
||||
const tool_utils_1 = require('./tool-utils');
|
||||
const appDir = `${tool_utils_1.rootDir}/packages/app-desktop`;
|
||||
function main() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
yield tool_utils_1.gitPullTry(false);
|
||||
const argv = require('yargs').argv;
|
||||
process.chdir(appDir);
|
||||
console.info(`Running from: ${process.cwd()}`);
|
||||
const version = (yield tool_utils_1.execCommand2('npm version patch')).trim();
|
||||
const tagName = version;
|
||||
console.info(`New version number: ${version}`);
|
||||
console.info(yield tool_utils_1.execCommand2('git add -A'));
|
||||
console.info(yield tool_utils_1.execCommand2(`git commit -m "Desktop release ${version}"`));
|
||||
console.info(yield tool_utils_1.execCommand2(`git tag ${tagName}`));
|
||||
console.info(yield tool_utils_1.execCommand2('git push && git push --tags'));
|
||||
const releaseOptions = { isDraft: true, isPreRelease: !!argv.beta };
|
||||
console.info('Release options: ', releaseOptions);
|
||||
const release = yield tool_utils_1.githubRelease('joplin', tagName, releaseOptions);
|
||||
console.info(`Created GitHub release: ${release.html_url}`);
|
||||
console.info('GitHub release page: https://github.com/laurent22/joplin/releases');
|
||||
console.info(`To create changelog: node packages/tools/git-changelog.js ${version}`);
|
||||
});
|
||||
const { execCommand, githubRelease, rootDir } = require('./tool-utils.js');
|
||||
|
||||
const appDir = `${rootDir}/packages/app-desktop`;
|
||||
|
||||
async function main() {
|
||||
const argv = require('yargs').argv;
|
||||
|
||||
process.chdir(appDir);
|
||||
|
||||
console.info(`Running from: ${process.cwd()}`);
|
||||
|
||||
const version = (await execCommand('npm version patch')).trim();
|
||||
const tagName = version;
|
||||
|
||||
console.info(`New version number: ${version}`);
|
||||
|
||||
console.info(await execCommand('git add -A'));
|
||||
console.info(await execCommand(`git commit -m "Desktop release ${version}"`));
|
||||
console.info(await execCommand(`git tag ${tagName}`));
|
||||
console.info(await execCommand('git push && git push --tags'));
|
||||
|
||||
const releaseOptions = { isDraft: true, isPreRelease: !!argv.beta };
|
||||
|
||||
console.info('Release options: ', releaseOptions);
|
||||
|
||||
const release = await githubRelease('joplin', tagName, releaseOptions);
|
||||
|
||||
console.info(`Created GitHub release: ${release.html_url}`);
|
||||
console.info('GitHub release page: https://github.com/laurent22/joplin/releases');
|
||||
console.info(`To create changelog: node packages/tools/git-changelog.js ${version}`);
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error('Fatal error');
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
// # sourceMappingURL=release-electron.js.map
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
import { execCommand2, githubRelease, gitPullTry, rootDir } from './tool-utils';
|
||||
|
||||
const appDir = `${rootDir}/packages/app-desktop`;
|
||||
|
||||
async function main() {
|
||||
await gitPullTry(false);
|
||||
|
||||
const argv = require('yargs').argv;
|
||||
|
||||
process.chdir(appDir);
|
||||
|
||||
console.info(`Running from: ${process.cwd()}`);
|
||||
|
||||
const version = (await execCommand2('npm version patch')).trim();
|
||||
const tagName = version;
|
||||
|
||||
console.info(`New version number: ${version}`);
|
||||
|
||||
console.info(await execCommand2('git add -A'));
|
||||
console.info(await execCommand2(`git commit -m "Desktop release ${version}"`));
|
||||
console.info(await execCommand2(`git tag ${tagName}`));
|
||||
console.info(await execCommand2('git push && git push --tags'));
|
||||
|
||||
const releaseOptions = { isDraft: true, isPreRelease: !!argv.beta };
|
||||
|
||||
console.info('Release options: ', releaseOptions);
|
||||
|
||||
const release = await githubRelease('joplin', tagName, releaseOptions);
|
||||
|
||||
console.info(`Created GitHub release: ${release.html_url}`);
|
||||
console.info('GitHub release page: https://github.com/laurent22/joplin/releases');
|
||||
console.info(`To create changelog: node packages/tools/git-changelog.js ${version}`);
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error('Fatal error');
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -1,4 +1,4 @@
|
||||
import { execCommand2, rootDir, gitPullTry } from './tool-utils';
|
||||
const { execCommand2, rootDir, gitPullTry } = require('./tool-utils.js');
|
||||
|
||||
const serverDir = `${rootDir}/packages/server`;
|
||||
|
||||
|
||||
@@ -80,10 +80,6 @@ async function main() {
|
||||
await updatePackageVersion(`${rootDir}/packages/app-cli/package.json`, majorMinorVersion);
|
||||
await updatePackageVersion(`${rootDir}/packages/generator-joplin/package.json`, majorMinorVersion);
|
||||
await updatePackageVersion(`${rootDir}/packages/server/package.json`, majorMinorVersion);
|
||||
await updatePackageVersion(`${rootDir}/packages/plugin-repo-cli/package.json`, majorMinorVersion);
|
||||
await updatePackageVersion(`${rootDir}/packages/lib/package.json`, majorMinorVersion);
|
||||
await updatePackageVersion(`${rootDir}/packages/renderer/package.json`, majorMinorVersion);
|
||||
await updatePackageVersion(`${rootDir}/packages/tools/package.json`, majorMinorVersion);
|
||||
await updateGradleVersion(`${rootDir}/packages/app-mobile/android/app/build.gradle`, majorMinorVersion);
|
||||
await updateCodeProjVersion(`${rootDir}/packages/app-mobile/ios/Joplin.xcodeproj/project.pbxproj`, iosVersionHack(majorMinorVersion));
|
||||
await updateClipperManifestVersion(`${rootDir}/packages/app-clipper/manifest.json`, majorMinorVersion);
|
||||
|
||||
@@ -1,50 +1,16 @@
|
||||
import * as fs from 'fs-extra';
|
||||
|
||||
const fetch = require('node-fetch');
|
||||
const fs = require('fs-extra');
|
||||
const execa = require('execa');
|
||||
const { execSync } = require('child_process');
|
||||
const { splitCommandString } = require('@joplin/lib/string-utils');
|
||||
|
||||
function quotePath(path: string) {
|
||||
if (!path) return '';
|
||||
if (path.indexOf('"') < 0 && path.indexOf(' ') < 0) return path;
|
||||
path = path.replace(/"/, '\\"');
|
||||
return `"${path}"`;
|
||||
}
|
||||
const toolUtils = {};
|
||||
|
||||
function commandToString(commandName: string, args: string[] = []) {
|
||||
const output = [quotePath(commandName)];
|
||||
|
||||
for (const arg of args) {
|
||||
output.push(quotePath(arg));
|
||||
}
|
||||
|
||||
return output.join(' ');
|
||||
}
|
||||
|
||||
async function loadGitHubUsernameCache() {
|
||||
const path = `${__dirname}/github_username_cache.json`;
|
||||
|
||||
if (await fs.pathExists(path)) {
|
||||
const jsonString = await fs.readFile(path, 'utf8');
|
||||
return JSON.parse(jsonString);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
async function saveGitHubUsernameCache(cache: any) {
|
||||
const path = `${__dirname}/github_username_cache.json`;
|
||||
await fs.writeFile(path, JSON.stringify(cache));
|
||||
}
|
||||
|
||||
// Returns the project root dir
|
||||
export const rootDir = require('path').dirname(require('path').dirname(__dirname));
|
||||
|
||||
export function execCommand(command: string) {
|
||||
toolUtils.execCommand = function(command) {
|
||||
const exec = require('child_process').exec;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
exec(command, (error: any, stdout: any, stderr: any) => {
|
||||
exec(command, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
if (error.signal == 'SIGTERM') {
|
||||
resolve('Process was killed');
|
||||
@@ -56,28 +22,39 @@ export function execCommand(command: string) {
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
function quotePath(path) {
|
||||
if (!path) return '';
|
||||
if (path.indexOf('"') < 0 && path.indexOf(' ') < 0) return path;
|
||||
path = path.replace(/"/, '\\"');
|
||||
return `"${path}"`;
|
||||
}
|
||||
|
||||
export function resolveRelativePathWithinDir(baseDir: string, ...relativePath: string[]) {
|
||||
function commandToString(commandName, args = []) {
|
||||
const output = [quotePath(commandName)];
|
||||
|
||||
for (const arg of args) {
|
||||
output.push(quotePath(arg));
|
||||
}
|
||||
|
||||
return output.join(' ');
|
||||
}
|
||||
|
||||
toolUtils.resolveRelativePathWithinDir = function(baseDir, ...relativePath) {
|
||||
const path = require('path');
|
||||
const resolvedBaseDir = path.resolve(baseDir);
|
||||
const resolvedPath = path.resolve(baseDir, ...relativePath);
|
||||
if (resolvedPath.indexOf(resolvedBaseDir) !== 0) throw new Error(`Resolved path for relative path "${JSON.stringify(relativePath)}" is not within base directory "${baseDir}" (Was resolved to ${resolvedPath})`);
|
||||
return resolvedPath;
|
||||
}
|
||||
};
|
||||
|
||||
export function execCommandVerbose(commandName: string, args: string[] = []) {
|
||||
toolUtils.execCommandVerbose = function(commandName, args = []) {
|
||||
console.info(`> ${commandToString(commandName, args)}`);
|
||||
const promise = execa(commandName, args);
|
||||
promise.stdout.pipe(process.stdout);
|
||||
return promise;
|
||||
}
|
||||
|
||||
interface ExecCommandOptions {
|
||||
showInput?: boolean;
|
||||
showOutput?: boolean;
|
||||
quiet?: boolean;
|
||||
}
|
||||
};
|
||||
|
||||
// There's lot of execCommandXXX functions, but eventually all scripts should
|
||||
// use the one below, which supports:
|
||||
@@ -85,63 +62,66 @@ interface ExecCommandOptions {
|
||||
// - 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> {
|
||||
toolUtils.execCommand2 = async function(command, options = null) {
|
||||
options = {
|
||||
showInput: true,
|
||||
showOutput: true,
|
||||
quiet: false,
|
||||
...options,
|
||||
};
|
||||
|
||||
if (options.quiet) {
|
||||
options.showInput = false;
|
||||
options.showOutput = 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[];
|
||||
if (options.showInput) console.info(`> ${command}`);
|
||||
const args = splitCommandString(command);
|
||||
const executableName = args[0];
|
||||
args.splice(0, 1);
|
||||
const promise = execa(executableName, args);
|
||||
if (options.showOutput) promise.stdout.pipe(process.stdout);
|
||||
const result = await promise;
|
||||
return result.stdout.trim();
|
||||
}
|
||||
return result.stdout;
|
||||
};
|
||||
|
||||
export function execCommandWithPipes(executable: string, args: string[]) {
|
||||
toolUtils.execCommandWithPipes = function(executable, args) {
|
||||
const spawn = require('child_process').spawn;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const child = spawn(executable, args, { stdio: 'inherit' });
|
||||
|
||||
child.on('error', (error: any) => {
|
||||
child.on('error', (error) => {
|
||||
reject(error);
|
||||
});
|
||||
|
||||
child.on('close', (code: any) => {
|
||||
child.on('close', (code) => {
|
||||
if (code !== 0) {
|
||||
reject(`Ended with code ${code}`);
|
||||
} else {
|
||||
resolve(null);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export function toSystemSlashes(path: string) {
|
||||
toolUtils.toSystemSlashes = function(path) {
|
||||
const os = process.platform;
|
||||
if (os === 'win32') return path.replace(/\//g, '\\');
|
||||
return path.replace(/\\/g, '/');
|
||||
}
|
||||
};
|
||||
|
||||
export async function setPackagePrivateField(filePath: string, value: any) {
|
||||
toolUtils.deleteLink = async function(path) {
|
||||
if (toolUtils.isWindows()) {
|
||||
try {
|
||||
execSync(`rmdir "${toolUtils.toSystemSlashes(path)}"`, { stdio: 'pipe' });
|
||||
} catch (error) {
|
||||
// console.info('Error: ' + error.message);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
fs.unlinkSync(toolUtils.toSystemSlashes(path));
|
||||
} catch (error) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
toolUtils.setPackagePrivateField = async function(filePath, value) {
|
||||
const text = await fs.readFile(filePath, 'utf8');
|
||||
const obj = JSON.parse(text);
|
||||
if (!value) {
|
||||
@@ -150,9 +130,9 @@ export async function setPackagePrivateField(filePath: string, value: any) {
|
||||
obj.private = true;
|
||||
}
|
||||
await fs.writeFile(filePath, JSON.stringify(obj, null, 2), 'utf8');
|
||||
}
|
||||
};
|
||||
|
||||
export async function credentialDir() {
|
||||
toolUtils.credentialDir = async function() {
|
||||
const username = require('os').userInfo().username;
|
||||
|
||||
const toTry = [
|
||||
@@ -163,45 +143,48 @@ export async function credentialDir() {
|
||||
];
|
||||
|
||||
for (const dirPath of toTry) {
|
||||
if (await fs.pathExists(dirPath)) return dirPath;
|
||||
if (await fs.exists(dirPath)) return dirPath;
|
||||
}
|
||||
|
||||
throw new Error(`Could not find credential directory in any of these paths: ${JSON.stringify(toTry)}`);
|
||||
}
|
||||
};
|
||||
|
||||
export async function credentialFile(filename: string) {
|
||||
const rootDir = await credentialDir();
|
||||
// Returns the project root dir
|
||||
toolUtils.rootDir = require('path').dirname(require('path').dirname(__dirname));
|
||||
|
||||
toolUtils.credentialFile = async function(filename) {
|
||||
const rootDir = await toolUtils.credentialDir();
|
||||
const output = `${rootDir}/${filename}`;
|
||||
if (!(await fs.pathExists(output))) throw new Error(`No such file: ${output}`);
|
||||
if (!(await fs.exists(output))) throw new Error(`No such file: ${output}`);
|
||||
return output;
|
||||
}
|
||||
};
|
||||
|
||||
export async function readCredentialFile(filename: string) {
|
||||
const filePath = await credentialFile(filename);
|
||||
toolUtils.readCredentialFile = async function(filename) {
|
||||
const filePath = await toolUtils.credentialFile(filename);
|
||||
const r = await fs.readFile(filePath);
|
||||
return r.toString();
|
||||
}
|
||||
};
|
||||
|
||||
export async function downloadFile(url: string, targetPath: string) {
|
||||
toolUtils.downloadFile = function(url, targetPath) {
|
||||
const https = require('https');
|
||||
const fs = require('fs');
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const file = fs.createWriteStream(targetPath);
|
||||
https.get(url, function(response: any) {
|
||||
https.get(url, function(response) {
|
||||
if (response.statusCode !== 200) reject(new Error(`HTTP error ${response.statusCode}`));
|
||||
response.pipe(file);
|
||||
file.on('finish', function() {
|
||||
// file.close();
|
||||
resolve(null);
|
||||
resolve();
|
||||
});
|
||||
}).on('error', (error: any) => {
|
||||
}).on('error', (error) => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export function fileSha256(filePath: string) {
|
||||
toolUtils.fileSha256 = function(filePath) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const crypto = require('crypto');
|
||||
const fs = require('fs');
|
||||
@@ -209,18 +192,18 @@ export function fileSha256(filePath: string) {
|
||||
const shasum = crypto.createHash(algo);
|
||||
|
||||
const s = fs.ReadStream(filePath);
|
||||
s.on('data', function(d: any) { shasum.update(d); });
|
||||
s.on('data', function(d) { shasum.update(d); });
|
||||
s.on('end', function() {
|
||||
const d = shasum.digest('hex');
|
||||
resolve(d);
|
||||
});
|
||||
s.on('error', function(error: any) {
|
||||
s.on('error', function(error) {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export async function unlinkForce(filePath: string) {
|
||||
toolUtils.unlinkForce = async function(filePath) {
|
||||
const fs = require('fs-extra');
|
||||
|
||||
try {
|
||||
@@ -229,13 +212,13 @@ export async function unlinkForce(filePath: string) {
|
||||
if (error.code === 'ENOENT') return;
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export function fileExists(filePath: string) {
|
||||
toolUtils.fileExists = async function(filePath) {
|
||||
const fs = require('fs-extra');
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.stat(filePath, function(err: any) {
|
||||
fs.stat(filePath, function(err) {
|
||||
if (err == null) {
|
||||
resolve(true);
|
||||
} else if (err.code == 'ENOENT') {
|
||||
@@ -245,39 +228,44 @@ export function fileExists(filePath: string) {
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
async function loadGitHubUsernameCache() {
|
||||
const path = `${__dirname}/github_username_cache.json`;
|
||||
|
||||
if (await fs.exists(path)) {
|
||||
const jsonString = await fs.readFile(path);
|
||||
return JSON.parse(jsonString);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
export async function gitRepoClean(): Promise<boolean> {
|
||||
const output = await execCommand2('git status --porcelain', { quiet: true });
|
||||
return !output.trim();
|
||||
async function saveGitHubUsernameCache(cache) {
|
||||
const path = `${__dirname}/github_username_cache.json`;
|
||||
await fs.writeFile(path, JSON.stringify(cache));
|
||||
}
|
||||
|
||||
|
||||
export async function gitRepoCleanTry() {
|
||||
if (!(await gitRepoClean())) throw new Error(`There are pending changes in the repository: ${process.cwd()}`);
|
||||
}
|
||||
|
||||
export async function gitPullTry(ignoreIfNotBranch = true) {
|
||||
toolUtils.gitPullTry = async function() {
|
||||
try {
|
||||
await execCommand('git pull');
|
||||
await toolUtils.execCommand('git pull');
|
||||
} catch (error) {
|
||||
if (ignoreIfNotBranch && error.message.includes('no tracking information for the current branch')) {
|
||||
if (error.message.includes('no tracking information for the current branch')) {
|
||||
console.info('Skipping git pull because no tracking information on current branch');
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export async function githubUsername(email: string, name: string) {
|
||||
toolUtils.githubUsername = async function(email, name) {
|
||||
const cache = await loadGitHubUsernameCache();
|
||||
const cacheKey = `${email}:${name}`;
|
||||
if (cacheKey in cache) return cache[cacheKey];
|
||||
|
||||
let output = null;
|
||||
|
||||
const oauthToken = await githubOauthToken();
|
||||
const oauthToken = await toolUtils.githubOauthToken();
|
||||
|
||||
const urlsToTry = [
|
||||
`https://api.github.com/search/users?q=${encodeURI(email)}+in:email`,
|
||||
@@ -308,23 +296,23 @@ export async function githubUsername(email: string, name: string) {
|
||||
await saveGitHubUsernameCache(cache);
|
||||
|
||||
return output;
|
||||
}
|
||||
};
|
||||
|
||||
export function patreonOauthToken() {
|
||||
return readCredentialFile('patreon_oauth_token.txt');
|
||||
}
|
||||
toolUtils.patreonOauthToken = async function() {
|
||||
return toolUtils.readCredentialFile('patreon_oauth_token.txt');
|
||||
};
|
||||
|
||||
export function githubOauthToken() {
|
||||
return readCredentialFile('github_oauth_token.txt');
|
||||
}
|
||||
toolUtils.githubOauthToken = async function() {
|
||||
return toolUtils.readCredentialFile('github_oauth_token.txt');
|
||||
};
|
||||
|
||||
export async function githubRelease(project: string, tagName: string, options: any = null) {
|
||||
toolUtils.githubRelease = async function(project, tagName, options = null) {
|
||||
options = Object.assign({}, {
|
||||
isDraft: false,
|
||||
isPreRelease: false,
|
||||
}, options);
|
||||
|
||||
const oauthToken = await githubOauthToken();
|
||||
const oauthToken = await toolUtils.githubOauthToken();
|
||||
|
||||
const response = await fetch(`https://api.github.com/repos/laurent22/${project}/releases`, {
|
||||
method: 'POST',
|
||||
@@ -348,9 +336,9 @@ export async function githubRelease(project: string, tagName: string, options: a
|
||||
if (!responseJson.url) throw new Error(`No URL for release: ${responseText}`);
|
||||
|
||||
return responseJson;
|
||||
}
|
||||
};
|
||||
|
||||
export function readline(question: string) {
|
||||
toolUtils.readline = question => {
|
||||
return new Promise((resolve) => {
|
||||
const readline = require('readline');
|
||||
|
||||
@@ -359,61 +347,63 @@ export function readline(question: string) {
|
||||
output: process.stdout,
|
||||
});
|
||||
|
||||
rl.question(`${question} `, (answer: string) => {
|
||||
rl.question(`${question} `, answer => {
|
||||
resolve(answer);
|
||||
rl.close();
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export function isLinux() {
|
||||
toolUtils.isLinux = () => {
|
||||
return process && process.platform === 'linux';
|
||||
}
|
||||
};
|
||||
|
||||
export function isWindows() {
|
||||
toolUtils.isWindows = () => {
|
||||
return process && process.platform === 'win32';
|
||||
}
|
||||
};
|
||||
|
||||
export function isMac() {
|
||||
toolUtils.isMac = () => {
|
||||
return process && process.platform === 'darwin';
|
||||
}
|
||||
};
|
||||
|
||||
export async function insertContentIntoFile(filePath: string, markerOpen: string, markerClose: string, contentToInsert: string) {
|
||||
toolUtils.insertContentIntoFile = async function(filePath, markerOpen, markerClose, contentToInsert) {
|
||||
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 fs.writeFile(filePath, content);
|
||||
}
|
||||
};
|
||||
|
||||
export function dirname(path: string) {
|
||||
toolUtils.dirname = (path) => {
|
||||
if (!path) throw new Error('Path is empty');
|
||||
const s = path.split(/\/|\\/);
|
||||
s.pop();
|
||||
return s.join('/');
|
||||
}
|
||||
};
|
||||
|
||||
export function basename(path: string) {
|
||||
toolUtils.basename = (path) => {
|
||||
if (!path) throw new Error('Path is empty');
|
||||
const s = path.split(/\/|\\/);
|
||||
return s[s.length - 1];
|
||||
}
|
||||
};
|
||||
|
||||
export function filename(path: string, includeDir = false) {
|
||||
toolUtils.filename = (path, includeDir = false) => {
|
||||
if (!path) throw new Error('Path is empty');
|
||||
const output = includeDir ? path : basename(path);
|
||||
const output = includeDir ? path : toolUtils.basename(path);
|
||||
if (output.indexOf('.') < 0) return output;
|
||||
|
||||
const splitted = output.split('.');
|
||||
splitted.pop();
|
||||
return splitted.join('.');
|
||||
}
|
||||
};
|
||||
|
||||
export function fileExtension(path: string) {
|
||||
toolUtils.fileExtension = (path) => {
|
||||
if (!path) throw new Error('Path is empty');
|
||||
|
||||
const output = path.split('.');
|
||||
if (output.length <= 1) return '';
|
||||
return output[output.length - 1];
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = toolUtils;
|
||||
2
packages/turndown-plugin-gfm/package-lock.json
generated
2
packages/turndown-plugin-gfm/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/turndown-plugin-gfm",
|
||||
"version": "1.0.23",
|
||||
"version": "1.0.19",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"version": "1.0.23",
|
||||
"version": "1.0.19",
|
||||
"author": "Dom Christie",
|
||||
"main": "lib/turndown-plugin-gfm.cjs.js",
|
||||
"module": "lib/turndown-plugin-gfm.es.js",
|
||||
|
||||
2
packages/turndown/package-lock.json
generated
2
packages/turndown/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/turndown",
|
||||
"version": "4.0.41",
|
||||
"version": "4.0.37",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@joplin/turndown",
|
||||
"description": "A library that converts HTML to Markdown",
|
||||
"version": "4.0.41",
|
||||
"version": "4.0.37",
|
||||
"author": "Dom Christie",
|
||||
"main": "lib/turndown.cjs.js",
|
||||
"module": "lib/turndown.es.js",
|
||||
|
||||
Reference in New Issue
Block a user