1
0
mirror of https://github.com/laurent22/joplin.git synced 2026-01-20 00:46:28 +02:00

Compare commits

..

2 Commits

Author SHA1 Message Date
Laurent Cozic
9bba9a8ed6 Plugins: Fixed issue with toolbar button key not being unique 2020-11-20 16:19:57 +00:00
Laurent Cozic
3344e84c7c fix link 2020-11-20 15:52:08 +00:00
120 changed files with 419 additions and 823 deletions

View File

@@ -151,9 +151,12 @@ packages/app-cli/app/LinkSelector.js.map
packages/app-cli/app/services/plugins/PluginRunner.d.ts
packages/app-cli/app/services/plugins/PluginRunner.js
packages/app-cli/app/services/plugins/PluginRunner.js.map
packages/app-cli/tests/EnexToMd.d.ts
packages/app-cli/tests/EnexToMd.js
packages/app-cli/tests/EnexToMd.js.map
packages/app-cli/build/LinkSelector.d.ts
packages/app-cli/build/LinkSelector.js
packages/app-cli/build/LinkSelector.js.map
packages/app-cli/build/services/plugins/PluginRunner.d.ts
packages/app-cli/build/services/plugins/PluginRunner.js
packages/app-cli/build/services/plugins/PluginRunner.js.map
packages/app-cli/tests/InMemoryCache.d.ts
packages/app-cli/tests/InMemoryCache.js
packages/app-cli/tests/InMemoryCache.js.map

9
.gitignore vendored
View File

@@ -143,9 +143,12 @@ packages/app-cli/app/LinkSelector.js.map
packages/app-cli/app/services/plugins/PluginRunner.d.ts
packages/app-cli/app/services/plugins/PluginRunner.js
packages/app-cli/app/services/plugins/PluginRunner.js.map
packages/app-cli/tests/EnexToMd.d.ts
packages/app-cli/tests/EnexToMd.js
packages/app-cli/tests/EnexToMd.js.map
packages/app-cli/build/LinkSelector.d.ts
packages/app-cli/build/LinkSelector.js
packages/app-cli/build/LinkSelector.js.map
packages/app-cli/build/services/plugins/PluginRunner.d.ts
packages/app-cli/build/services/plugins/PluginRunner.js
packages/app-cli/build/services/plugins/PluginRunner.js.map
packages/app-cli/tests/InMemoryCache.d.ts
packages/app-cli/tests/InMemoryCache.js
packages/app-cli/tests/InMemoryCache.js.map

View File

@@ -1,6 +1,6 @@
{
"name": "joplin",
"version": "1.4.7",
"version": "1.4.3",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@@ -31,7 +31,7 @@
],
"owner": "Laurent Cozic"
},
"version": "1.4.9",
"version": "1.4.3",
"bin": {
"joplin": "./main.js"
},

View File

@@ -0,0 +1,67 @@
/* eslint-disable no-unused-vars */
const os = require('os');
const time = require('@joplin/lib/time').default;
const { filename } = require('@joplin/lib/path-utils');
const { asyncTest, fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('./test-utils.js');
const Folder = require('@joplin/lib/models/Folder.js');
const Note = require('@joplin/lib/models/Note.js');
const BaseModel = require('@joplin/lib/BaseModel').default;
const shim = require('@joplin/lib/shim').default;
const { enexXmlToMd } = require('@joplin/lib/import-enex-md-gen.js');
process.on('unhandledRejection', (reason, p) => {
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
});
describe('EnexToMd', function() {
beforeEach(async (done) => {
await setupDatabaseAndSynchronizer(1);
await switchClient(1);
done();
});
it('should convert from Enex to Markdown', asyncTest(async () => {
const basePath = `${__dirname}/enex_to_md`;
const files = await shim.fsDriver().readDirStats(basePath);
for (let i = 0; i < files.length; i++) {
const htmlFilename = files[i].path;
if (htmlFilename.indexOf('.html') < 0) continue;
const htmlPath = `${basePath}/${htmlFilename}`;
const mdPath = `${basePath}/${filename(htmlFilename)}.md`;
// if (htmlFilename !== 'multiline_inner_text.html') continue;
const html = await shim.fsDriver().readFile(htmlPath);
let expectedMd = await shim.fsDriver().readFile(mdPath);
let actualMd = await enexXmlToMd(`<div>${html}</div>`, []);
if (os.EOL === '\r\n') {
expectedMd = expectedMd.replace(/\r\n/g, '\n');
actualMd = actualMd.replace(/\r\n/g, '\n');
}
if (actualMd !== expectedMd) {
console.info('');
console.info(`Error converting file: ${htmlFilename}`);
console.info('--------------------------------- Got:');
console.info(actualMd.split('\n'));
console.info('--------------------------------- Expected:');
console.info(expectedMd.split('\n'));
console.info('--------------------------------------------');
console.info('');
expect(false).toBe(true);
// return;
} else {
expect(true).toBe(true);
}
}
}));
});

View File

@@ -1,99 +0,0 @@
import { NoteEntity, ResourceEntity, TagEntity } from '@joplin/lib/services/database/types';
import shim from '@joplin/lib/shim';
const fs = require('fs-extra');
const os = require('os');
const { filename } = require('@joplin/lib/path-utils');
const { setupDatabaseAndSynchronizer, switchClient } = require('./test-utils.js');
const { enexXmlToMd } = require('@joplin/lib/import-enex-md-gen.js');
const { importEnex } = require('@joplin/lib/import-enex');
const Note = require('@joplin/lib/models/Note');
const Tag = require('@joplin/lib/models/Tag');
const Resource = require('@joplin/lib/models/Resource');
const enexSampleBaseDir = `${__dirname}/enex_to_md`;
describe('EnexToMd', function() {
beforeEach(async (done) => {
await setupDatabaseAndSynchronizer(1);
await switchClient(1);
done();
});
it('should convert ENEX content to Markdown', async () => {
const files = await shim.fsDriver().readDirStats(enexSampleBaseDir);
for (let i = 0; i < files.length; i++) {
const htmlFilename = files[i].path;
if (htmlFilename.indexOf('.html') < 0) continue;
const htmlPath = `${enexSampleBaseDir}/${htmlFilename}`;
const mdPath = `${enexSampleBaseDir}/${filename(htmlFilename)}.md`;
// if (htmlFilename !== 'multiline_inner_text.html') continue;
const html = await shim.fsDriver().readFile(htmlPath);
let expectedMd = await shim.fsDriver().readFile(mdPath);
let actualMd = await enexXmlToMd(`<div>${html}</div>`, []);
if (os.EOL === '\r\n') {
expectedMd = expectedMd.replace(/\r\n/g, '\n');
actualMd = actualMd.replace(/\r\n/g, '\n');
}
if (actualMd !== expectedMd) {
console.info('');
console.info(`Error converting file: ${htmlFilename}`);
console.info('--------------------------------- Got:');
console.info(actualMd.split('\n'));
console.info('--------------------------------- Expected:');
console.info(expectedMd.split('\n'));
console.info('--------------------------------------------');
console.info('');
expect(false).toBe(true);
// return;
} else {
expect(true).toBe(true);
}
}
});
it('should import ENEX metadata', async () => {
const filePath = `${enexSampleBaseDir}/sample-enex.xml`;
await importEnex('', filePath);
const note: NoteEntity = (await Note.all())[0];
expect(note.title).toBe('Test Note for Export');
expect(note.body).toBe([
' Hello, World.',
'',
'![snapshot-DAE9FC15-88E3-46CF-B744-DA9B1B56EB57.jpg](:/3d0f4d01abc02cf8c4dc1c796df8c4b2)',
].join('\n'));
expect(note.created_time).toBe(1375217524000);
expect(note.updated_time).toBe(1376560800000);
expect(note.latitude).toBe('33.88394692');
expect(note.longitude).toBe('-117.91913551');
expect(note.altitude).toBe('96.0000');
expect(note.author).toBe('Brett Kelly');
const tag: TagEntity = (await Tag.tagsByNoteId(note.id))[0];
expect(tag.title).toBe('fake-tag');
const resource: ResourceEntity = (await Resource.all())[0];
expect(resource.id).toBe('3d0f4d01abc02cf8c4dc1c796df8c4b2');
const stat = await fs.stat(Resource.fullPath(resource));
expect(stat.size).toBe(277);
});
it('should handle invalid dates', async () => {
const filePath = `${enexSampleBaseDir}/invalid_date.enex`;
await importEnex('', filePath);
const note: NoteEntity = (await Note.all())[0];
expect(note.created_time).toBe(1521822724000); // 20180323T163204Z
expect(note.updated_time).toBe(1521822724000); // Because this date was invalid, it is set to the created time instead
});
});

View File

@@ -147,27 +147,27 @@ describe('MdToHtml', function() {
expect(result.html.trim()).toBe('<div id="rendered-md"><p>just <strong>testing</strong></p>\n</div>');
}));
// it('should render links correctly', asyncTest(async () => {
// const mdToHtml = newTestMdToHtml();
it('should render links correctly', asyncTest(async () => {
const mdToHtml = newTestMdToHtml();
// const testCases = [
// // None of these should result in a link
// ['https://example.com', 'https://example.com'],
// ['file://C:\\AUTOEXEC.BAT', 'file://C:\\AUTOEXEC.BAT'],
// ['example.com', 'example.com'],
// ['oo.ps', 'oo.ps'],
// ['test@example.com', 'test@example.com'],
const testCases = [
// None of these should result in a link
['https://example.com', 'https://example.com'],
['file://C:\\AUTOEXEC.BAT', 'file://C:\\AUTOEXEC.BAT'],
['example.com', 'example.com'],
['oo.ps', 'oo.ps'],
['test@example.com', 'test@example.com'],
// // Those should be converted to links
// ['<https://example.com>', '<a data-from-md title=\'https://example.com\' href=\'https://example.com\'>https://example.com</a>'],
// ['[ok](https://example.com)', '<a data-from-md title=\'https://example.com\' href=\'https://example.com\'>ok</a>'],
// ];
// Those should be converted to links
['<https://example.com>', '<a data-from-md title=\'https://example.com\' href=\'https://example.com\'>https://example.com</a>'],
['[ok](https://example.com)', '<a data-from-md title=\'https://example.com\' href=\'https://example.com\'>ok</a>'],
];
// for (const testCase of testCases) {
// const [input, expected] = testCase;
// const actual = await mdToHtml.render(input, null, { bodyOnly: true, plainResourceRendering: true });
// expect(actual.html).toBe(expected);
// }
// }));
for (const testCase of testCases) {
const [input, expected] = testCase;
const actual = await mdToHtml.render(input, null, { bodyOnly: true, plainResourceRendering: true });
expect(actual.html).toBe(expected);
}
}));
});

View File

@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE en-export SYSTEM "http://xml.evernote.com/pub/evernote-export3.dtd">
<en-export export-date="20201223T053642Z" application="Evernote" version="10.4.3">
<note>
<title>Fruit Tree Assessment</title>
<created>20180323T163204Z</created>
<updated>10101T000000Z</updated>
<content>
<![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd"
><en-note>Fruit Tree</en-note> ]]>
</content>
</note>
</en-export>

View File

@@ -1,47 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE en-export SYSTEM "http://xml.evernote.com/pub/evernote-export3.dtd">
<en-export export-date="20130730T205637Z" application="Evernote" version="Evernote Mac">
<note>
<title>Test Note for Export</title>
<content>
<![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd">
<en-note style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">
Hello, World.
<div>
<br/>
</div>
<div>
<en-media alt="" type="image/jpeg" hash="dd7b6d285d09ec054e8cd6a3814ce093"/>
</div>
<div>
<br/>
</div>
</en-note>
]]>
</content>
<created>20130730T205204Z</created>
<updated>20130815T100000Z</updated>
<tag>fake-tag</tag>
<note-attributes>
<latitude>33.88394692352314</latitude>
<longitude>-117.9191355110099</longitude>
<altitude>96</altitude>
<author>Brett Kelly</author>
</note-attributes>
<resource>
<data encoding="base64">/9j/4AAQSkZJRgABAQAAAQABAAD/4gxYSUNDX1BST0ZJTEUAAQEAAAxITGlubwIQAABtbnRyUkdCIFhZ
WiAHzgACAAkABgAxAABhY3NwTVNGVAAAAABJRUMgc1JHQgAAAAAAAAAAAAAAAAAA9tYAAQAAAADTLUhQ
kfeIGT/+uufk8DpM0gyVjGfmzkgetesnUoTHJ+5Cxn86zmv4/wB75EW+QHAPUH/P9Ky+s1rtrr/wfvOm
dBSamnq/xPKp/hpLKmS7x4OBjgn6elee6v4OuLJirRSHb/FtyG9s9u1fR0+oTiIRvGq7W4bpisfUGk1C
GVWtkIyM57n1rfDY+uqigtU76ffZkUsA6iajHZ6v/P8A4B//2Q==</data>
<mime>image/jpeg</mime>
<width>1280</width>
<height>720</height>
<resource-attributes>
<file-name>snapshot-DAE9FC15-88E3-46CF-B744-DA9B1B56EB57.jpg</file-name>
</resource-attributes>
</resource>
</note>
</en-export>

View File

@@ -105,11 +105,7 @@ describe('models_BaseItem', function() {
}));
it('should serialize and unserialize properties that contain new lines', asyncTest(async () => {
const sourceUrl = `
https://joplinapp.org/ \\n
`;
const note = await Note.save({ title: 'note', source_url: sourceUrl });
const note = await Note.save({ title: 'note', source_url: '\nhttps://joplinapp.org/\n' });
const noteBefore = await Note.load(note.id);
const serialized = await Note.serialize(noteBefore);
@@ -117,18 +113,4 @@ https://joplinapp.org/ \\n
expect(noteAfter).toEqual(noteBefore);
}));
it('should not serialize the note title and body', asyncTest(async () => {
const note = await Note.save({ title: 'my note', body: `one line
two line
three line \\n no escape` });
const noteBefore = await Note.load(note.id);
const serialized = await Note.serialize(noteBefore);
expect(serialized.indexOf(`my note
one line
two line
three line \\n no escape`)).toBe(0);
}));
});

View File

@@ -1,12 +1,13 @@
import Plugin from '../Plugin';
import Joplin from './Joplin';
import Logger from '../../../Logger';
/**
* @ignore
*/
export default class Global {
private joplin_;
private requireWhiteList_;
constructor(implementation: any, plugin: Plugin, store: any);
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
get joplin(): Joplin;
private requireWhiteList;
require(filePath: string): any;

View File

@@ -7,6 +7,7 @@ import JoplinCommands from './JoplinCommands';
import JoplinViews from './JoplinViews';
import JoplinInterop from './JoplinInterop';
import JoplinSettings from './JoplinSettings';
import Logger from '../../../Logger';
/**
* This is the main entry point to the Joplin API. You can access various services using the provided accessors.
*
@@ -31,7 +32,7 @@ export default class Joplin {
private views_;
private interop_;
private settings_;
constructor(implementation: any, plugin: Plugin, store: any);
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
get data(): JoplinData;
get plugins(): JoplinPlugins;
get workspace(): JoplinWorkspace;

View File

@@ -1,11 +1,13 @@
import Plugin from '../Plugin';
import Logger from '../../../Logger';
import { ContentScriptType, Script } from './types';
/**
* This class provides access to plugin-related features.
*/
export default class JoplinPlugins {
private logger;
private plugin;
constructor(plugin: Plugin);
constructor(logger: Logger, plugin: Plugin);
/**
* Registers a new plugin. This is the entry point when creating a plugin. You should pass a simple object with an `onStart` method to it.
* That `onStart` method will be executed as soon as the plugin is loaded.

View File

@@ -6,7 +6,7 @@
"dist": "webpack",
"postinstall": "npm run dist"
},
"keywords": {},
"keywords": [],
"license": "MIT",
"devDependencies": {
"@types/node": "^14.0.14",
@@ -20,4 +20,4 @@
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}
}

View File

@@ -16,13 +16,6 @@ function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`)
.map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) {
// Usually means there's an error, which is going to be printed by
// webpack
console.info('Plugin archive was not created because the "dist" directory is empty');
return;
}
fs.removeSync(destPath);
tar.create(
@@ -45,8 +38,6 @@ const manifestPath = `${srcDir}/manifest.json`;
const manifest = readManifest(manifestPath);
const archiveFilePath = path.resolve(__dirname, `${manifest.id}.jpl`);
fs.removeSync(distDir);
module.exports = {
mode: 'production',
entry: './src/index.ts',

View File

@@ -1,12 +1,13 @@
import Plugin from '../Plugin';
import Joplin from './Joplin';
import Logger from '../../../Logger';
/**
* @ignore
*/
export default class Global {
private joplin_;
private requireWhiteList_;
constructor(implementation: any, plugin: Plugin, store: any);
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
get joplin(): Joplin;
private requireWhiteList;
require(filePath: string): any;

View File

@@ -7,6 +7,7 @@ import JoplinCommands from './JoplinCommands';
import JoplinViews from './JoplinViews';
import JoplinInterop from './JoplinInterop';
import JoplinSettings from './JoplinSettings';
import Logger from '../../../Logger';
/**
* This is the main entry point to the Joplin API. You can access various services using the provided accessors.
*
@@ -31,7 +32,7 @@ export default class Joplin {
private views_;
private interop_;
private settings_;
constructor(implementation: any, plugin: Plugin, store: any);
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
get data(): JoplinData;
get plugins(): JoplinPlugins;
get workspace(): JoplinWorkspace;

View File

@@ -1,11 +1,13 @@
import Plugin from '../Plugin';
import Logger from '../../../Logger';
import { ContentScriptType, Script } from './types';
/**
* This class provides access to plugin-related features.
*/
export default class JoplinPlugins {
private logger;
private plugin;
constructor(plugin: Plugin);
constructor(logger: Logger, plugin: Plugin);
/**
* Registers a new plugin. This is the entry point when creating a plugin. You should pass a simple object with an `onStart` method to it.
* That `onStart` method will be executed as soon as the plugin is loaded.

View File

@@ -6,7 +6,7 @@
"dist": "webpack",
"postinstall": "npm run dist"
},
"keywords": {},
"keywords": [],
"license": "MIT",
"devDependencies": {
"@types/node": "^14.0.14",
@@ -20,4 +20,4 @@
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}
}

View File

@@ -16,13 +16,6 @@ function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`)
.map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) {
// Usually means there's an error, which is going to be printed by
// webpack
console.info('Plugin archive was not created because the "dist" directory is empty');
return;
}
fs.removeSync(destPath);
tar.create(
@@ -45,8 +38,6 @@ const manifestPath = `${srcDir}/manifest.json`;
const manifest = readManifest(manifestPath);
const archiveFilePath = path.resolve(__dirname, `${manifest.id}.jpl`);
fs.removeSync(distDir);
module.exports = {
mode: 'production',
entry: './src/index.ts',

View File

@@ -1,12 +1,13 @@
import Plugin from '../Plugin';
import Joplin from './Joplin';
import Logger from '../../../Logger';
/**
* @ignore
*/
export default class Global {
private joplin_;
private requireWhiteList_;
constructor(implementation: any, plugin: Plugin, store: any);
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
get joplin(): Joplin;
private requireWhiteList;
require(filePath: string): any;

View File

@@ -7,6 +7,7 @@ import JoplinCommands from './JoplinCommands';
import JoplinViews from './JoplinViews';
import JoplinInterop from './JoplinInterop';
import JoplinSettings from './JoplinSettings';
import Logger from '../../../Logger';
/**
* This is the main entry point to the Joplin API. You can access various services using the provided accessors.
*
@@ -31,7 +32,7 @@ export default class Joplin {
private views_;
private interop_;
private settings_;
constructor(implementation: any, plugin: Plugin, store: any);
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
get data(): JoplinData;
get plugins(): JoplinPlugins;
get workspace(): JoplinWorkspace;

View File

@@ -1,11 +1,13 @@
import Plugin from '../Plugin';
import Logger from '../../../Logger';
import { ContentScriptType, Script } from './types';
/**
* This class provides access to plugin-related features.
*/
export default class JoplinPlugins {
private logger;
private plugin;
constructor(plugin: Plugin);
constructor(logger: Logger, plugin: Plugin);
/**
* Registers a new plugin. This is the entry point when creating a plugin. You should pass a simple object with an `onStart` method to it.
* That `onStart` method will be executed as soon as the plugin is loaded.

View File

@@ -6,7 +6,7 @@
"dist": "webpack",
"postinstall": "npm run dist"
},
"keywords": {},
"keywords": [],
"license": "MIT",
"devDependencies": {
"@types/node": "^14.0.14",
@@ -20,4 +20,4 @@
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}
}

View File

@@ -16,13 +16,6 @@ function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`)
.map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) {
// Usually means there's an error, which is going to be printed by
// webpack
console.info('Plugin archive was not created because the "dist" directory is empty');
return;
}
fs.removeSync(destPath);
tar.create(
@@ -45,8 +38,6 @@ const manifestPath = `${srcDir}/manifest.json`;
const manifest = readManifest(manifestPath);
const archiveFilePath = path.resolve(__dirname, `${manifest.id}.jpl`);
fs.removeSync(distDir);
module.exports = {
mode: 'production',
entry: './src/index.ts',

View File

@@ -1,12 +1,13 @@
import Plugin from '../Plugin';
import Joplin from './Joplin';
import Logger from '../../../Logger';
/**
* @ignore
*/
export default class Global {
private joplin_;
private requireWhiteList_;
constructor(implementation: any, plugin: Plugin, store: any);
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
get joplin(): Joplin;
private requireWhiteList;
require(filePath: string): any;

View File

@@ -7,6 +7,7 @@ import JoplinCommands from './JoplinCommands';
import JoplinViews from './JoplinViews';
import JoplinInterop from './JoplinInterop';
import JoplinSettings from './JoplinSettings';
import Logger from '../../../Logger';
/**
* This is the main entry point to the Joplin API. You can access various services using the provided accessors.
*
@@ -31,7 +32,7 @@ export default class Joplin {
private views_;
private interop_;
private settings_;
constructor(implementation: any, plugin: Plugin, store: any);
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
get data(): JoplinData;
get plugins(): JoplinPlugins;
get workspace(): JoplinWorkspace;

View File

@@ -1,11 +1,13 @@
import Plugin from '../Plugin';
import Logger from '../../../Logger';
import { ContentScriptType, Script } from './types';
/**
* This class provides access to plugin-related features.
*/
export default class JoplinPlugins {
private logger;
private plugin;
constructor(plugin: Plugin);
constructor(logger: Logger, plugin: Plugin);
/**
* Registers a new plugin. This is the entry point when creating a plugin. You should pass a simple object with an `onStart` method to it.
* That `onStart` method will be executed as soon as the plugin is loaded.

View File

@@ -6,7 +6,7 @@
"dist": "webpack",
"postinstall": "npm run dist"
},
"keywords": {},
"keywords": [],
"license": "MIT",
"devDependencies": {
"@types/node": "^14.0.14",
@@ -20,4 +20,4 @@
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}
}

View File

@@ -16,13 +16,6 @@ function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`)
.map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) {
// Usually means there's an error, which is going to be printed by
// webpack
console.info('Plugin archive was not created because the "dist" directory is empty');
return;
}
fs.removeSync(destPath);
tar.create(
@@ -45,8 +38,6 @@ const manifestPath = `${srcDir}/manifest.json`;
const manifest = readManifest(manifestPath);
const archiveFilePath = path.resolve(__dirname, `${manifest.id}.jpl`);
fs.removeSync(distDir);
module.exports = {
mode: 'production',
entry: './src/index.ts',

View File

@@ -1,12 +1,13 @@
import Plugin from '../Plugin';
import Joplin from './Joplin';
import Logger from '../../../Logger';
/**
* @ignore
*/
export default class Global {
private joplin_;
private requireWhiteList_;
constructor(implementation: any, plugin: Plugin, store: any);
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
get joplin(): Joplin;
private requireWhiteList;
require(filePath: string): any;

View File

@@ -7,6 +7,7 @@ import JoplinCommands from './JoplinCommands';
import JoplinViews from './JoplinViews';
import JoplinInterop from './JoplinInterop';
import JoplinSettings from './JoplinSettings';
import Logger from '../../../Logger';
/**
* This is the main entry point to the Joplin API. You can access various services using the provided accessors.
*
@@ -31,7 +32,7 @@ export default class Joplin {
private views_;
private interop_;
private settings_;
constructor(implementation: any, plugin: Plugin, store: any);
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
get data(): JoplinData;
get plugins(): JoplinPlugins;
get workspace(): JoplinWorkspace;

View File

@@ -1,11 +1,13 @@
import Plugin from '../Plugin';
import Logger from '../../../Logger';
import { ContentScriptType, Script } from './types';
/**
* This class provides access to plugin-related features.
*/
export default class JoplinPlugins {
private logger;
private plugin;
constructor(plugin: Plugin);
constructor(logger: Logger, plugin: Plugin);
/**
* Registers a new plugin. This is the entry point when creating a plugin. You should pass a simple object with an `onStart` method to it.
* That `onStart` method will be executed as soon as the plugin is loaded.

View File

@@ -6,7 +6,7 @@
"dist": "webpack",
"postinstall": "npm run dist"
},
"keywords": {},
"keywords": [],
"license": "MIT",
"devDependencies": {
"@types/node": "^14.0.14",
@@ -20,4 +20,4 @@
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}
}

View File

@@ -16,13 +16,6 @@ function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`)
.map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) {
// Usually means there's an error, which is going to be printed by
// webpack
console.info('Plugin archive was not created because the "dist" directory is empty');
return;
}
fs.removeSync(destPath);
tar.create(
@@ -45,8 +38,6 @@ const manifestPath = `${srcDir}/manifest.json`;
const manifest = readManifest(manifestPath);
const archiveFilePath = path.resolve(__dirname, `${manifest.id}.jpl`);
fs.removeSync(distDir);
module.exports = {
mode: 'production',
entry: './src/index.ts',

View File

@@ -1,12 +1,13 @@
import Plugin from '../Plugin';
import Joplin from './Joplin';
import Logger from '../../../Logger';
/**
* @ignore
*/
export default class Global {
private joplin_;
private requireWhiteList_;
constructor(implementation: any, plugin: Plugin, store: any);
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
get joplin(): Joplin;
private requireWhiteList;
require(filePath: string): any;

View File

@@ -7,6 +7,7 @@ import JoplinCommands from './JoplinCommands';
import JoplinViews from './JoplinViews';
import JoplinInterop from './JoplinInterop';
import JoplinSettings from './JoplinSettings';
import Logger from '../../../Logger';
/**
* This is the main entry point to the Joplin API. You can access various services using the provided accessors.
*
@@ -31,7 +32,7 @@ export default class Joplin {
private views_;
private interop_;
private settings_;
constructor(implementation: any, plugin: Plugin, store: any);
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
get data(): JoplinData;
get plugins(): JoplinPlugins;
get workspace(): JoplinWorkspace;

View File

@@ -1,11 +1,13 @@
import Plugin from '../Plugin';
import Logger from '../../../Logger';
import { ContentScriptType, Script } from './types';
/**
* This class provides access to plugin-related features.
*/
export default class JoplinPlugins {
private logger;
private plugin;
constructor(plugin: Plugin);
constructor(logger: Logger, plugin: Plugin);
/**
* Registers a new plugin. This is the entry point when creating a plugin. You should pass a simple object with an `onStart` method to it.
* That `onStart` method will be executed as soon as the plugin is loaded.

View File

@@ -6,7 +6,7 @@
"dist": "webpack",
"postinstall": "npm run dist"
},
"keywords": {},
"keywords": [],
"license": "MIT",
"devDependencies": {
"@types/node": "^14.0.14",
@@ -20,4 +20,4 @@
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}
}

View File

@@ -16,13 +16,6 @@ function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`)
.map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) {
// Usually means there's an error, which is going to be printed by
// webpack
console.info('Plugin archive was not created because the "dist" directory is empty');
return;
}
fs.removeSync(destPath);
tar.create(
@@ -45,8 +38,6 @@ const manifestPath = `${srcDir}/manifest.json`;
const manifest = readManifest(manifestPath);
const archiveFilePath = path.resolve(__dirname, `${manifest.id}.jpl`);
fs.removeSync(distDir);
module.exports = {
mode: 'production',
entry: './src/index.ts',

View File

@@ -1,12 +1,13 @@
import Plugin from '../Plugin';
import Joplin from './Joplin';
import Logger from '../../../Logger';
/**
* @ignore
*/
export default class Global {
private joplin_;
private requireWhiteList_;
constructor(implementation: any, plugin: Plugin, store: any);
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
get joplin(): Joplin;
private requireWhiteList;
require(filePath: string): any;

View File

@@ -7,6 +7,7 @@ import JoplinCommands from './JoplinCommands';
import JoplinViews from './JoplinViews';
import JoplinInterop from './JoplinInterop';
import JoplinSettings from './JoplinSettings';
import Logger from '../../../Logger';
/**
* This is the main entry point to the Joplin API. You can access various services using the provided accessors.
*
@@ -31,7 +32,7 @@ export default class Joplin {
private views_;
private interop_;
private settings_;
constructor(implementation: any, plugin: Plugin, store: any);
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
get data(): JoplinData;
get plugins(): JoplinPlugins;
get workspace(): JoplinWorkspace;

View File

@@ -1,11 +1,13 @@
import Plugin from '../Plugin';
import Logger from '../../../Logger';
import { ContentScriptType, Script } from './types';
/**
* This class provides access to plugin-related features.
*/
export default class JoplinPlugins {
private logger;
private plugin;
constructor(plugin: Plugin);
constructor(logger: Logger, plugin: Plugin);
/**
* Registers a new plugin. This is the entry point when creating a plugin. You should pass a simple object with an `onStart` method to it.
* That `onStart` method will be executed as soon as the plugin is loaded.

View File

@@ -6,7 +6,7 @@
"dist": "webpack",
"postinstall": "npm run dist"
},
"keywords": {},
"keywords": [],
"license": "MIT",
"devDependencies": {
"@types/node": "^14.0.14",
@@ -20,4 +20,4 @@
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}
}

View File

@@ -16,13 +16,6 @@ function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`)
.map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) {
// Usually means there's an error, which is going to be printed by
// webpack
console.info('Plugin archive was not created because the "dist" directory is empty');
return;
}
fs.removeSync(destPath);
tar.create(
@@ -45,8 +38,6 @@ const manifestPath = `${srcDir}/manifest.json`;
const manifest = readManifest(manifestPath);
const archiveFilePath = path.resolve(__dirname, `${manifest.id}.jpl`);
fs.removeSync(distDir);
module.exports = {
mode: 'production',
entry: './src/index.ts',

View File

@@ -1,12 +1,13 @@
import Plugin from '../Plugin';
import Joplin from './Joplin';
import Logger from '../../../Logger';
/**
* @ignore
*/
export default class Global {
private joplin_;
private requireWhiteList_;
constructor(implementation: any, plugin: Plugin, store: any);
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
get joplin(): Joplin;
private requireWhiteList;
require(filePath: string): any;

View File

@@ -7,6 +7,7 @@ import JoplinCommands from './JoplinCommands';
import JoplinViews from './JoplinViews';
import JoplinInterop from './JoplinInterop';
import JoplinSettings from './JoplinSettings';
import Logger from '../../../Logger';
/**
* This is the main entry point to the Joplin API. You can access various services using the provided accessors.
*
@@ -31,7 +32,7 @@ export default class Joplin {
private views_;
private interop_;
private settings_;
constructor(implementation: any, plugin: Plugin, store: any);
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
get data(): JoplinData;
get plugins(): JoplinPlugins;
get workspace(): JoplinWorkspace;

View File

@@ -1,11 +1,13 @@
import Plugin from '../Plugin';
import Logger from '../../../Logger';
import { ContentScriptType, Script } from './types';
/**
* This class provides access to plugin-related features.
*/
export default class JoplinPlugins {
private logger;
private plugin;
constructor(plugin: Plugin);
constructor(logger: Logger, plugin: Plugin);
/**
* Registers a new plugin. This is the entry point when creating a plugin. You should pass a simple object with an `onStart` method to it.
* That `onStart` method will be executed as soon as the plugin is loaded.

View File

@@ -6,7 +6,7 @@
"dist": "webpack",
"postinstall": "npm run dist"
},
"keywords": {},
"keywords": [],
"license": "MIT",
"devDependencies": {
"@types/node": "^14.0.14",
@@ -20,4 +20,4 @@
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}
}

View File

@@ -16,13 +16,6 @@ function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`)
.map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) {
// Usually means there's an error, which is going to be printed by
// webpack
console.info('Plugin archive was not created because the "dist" directory is empty');
return;
}
fs.removeSync(destPath);
tar.create(
@@ -45,8 +38,6 @@ const manifestPath = `${srcDir}/manifest.json`;
const manifest = readManifest(manifestPath);
const archiveFilePath = path.resolve(__dirname, `${manifest.id}.jpl`);
fs.removeSync(distDir);
module.exports = {
mode: 'production',
entry: './src/index.ts',

View File

@@ -1,12 +1,13 @@
import Plugin from '../Plugin';
import Joplin from './Joplin';
import Logger from '../../../Logger';
/**
* @ignore
*/
export default class Global {
private joplin_;
private requireWhiteList_;
constructor(implementation: any, plugin: Plugin, store: any);
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
get joplin(): Joplin;
private requireWhiteList;
require(filePath: string): any;

View File

@@ -7,6 +7,7 @@ import JoplinCommands from './JoplinCommands';
import JoplinViews from './JoplinViews';
import JoplinInterop from './JoplinInterop';
import JoplinSettings from './JoplinSettings';
import Logger from '../../../Logger';
/**
* This is the main entry point to the Joplin API. You can access various services using the provided accessors.
*
@@ -31,7 +32,7 @@ export default class Joplin {
private views_;
private interop_;
private settings_;
constructor(implementation: any, plugin: Plugin, store: any);
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
get data(): JoplinData;
get plugins(): JoplinPlugins;
get workspace(): JoplinWorkspace;

View File

@@ -1,11 +1,13 @@
import Plugin from '../Plugin';
import Logger from '../../../Logger';
import { ContentScriptType, Script } from './types';
/**
* This class provides access to plugin-related features.
*/
export default class JoplinPlugins {
private logger;
private plugin;
constructor(plugin: Plugin);
constructor(logger: Logger, plugin: Plugin);
/**
* Registers a new plugin. This is the entry point when creating a plugin. You should pass a simple object with an `onStart` method to it.
* That `onStart` method will be executed as soon as the plugin is loaded.

View File

@@ -6,7 +6,7 @@
"dist": "webpack",
"postinstall": "npm run dist"
},
"keywords": {},
"keywords": [],
"license": "MIT",
"devDependencies": {
"@types/node": "^14.0.14",
@@ -20,4 +20,4 @@
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}
}

View File

@@ -16,13 +16,6 @@ function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`)
.map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) {
// Usually means there's an error, which is going to be printed by
// webpack
console.info('Plugin archive was not created because the "dist" directory is empty');
return;
}
fs.removeSync(destPath);
tar.create(
@@ -45,8 +38,6 @@ const manifestPath = `${srcDir}/manifest.json`;
const manifest = readManifest(manifestPath);
const archiveFilePath = path.resolve(__dirname, `${manifest.id}.jpl`);
fs.removeSync(distDir);
module.exports = {
mode: 'production',
entry: './src/index.ts',

View File

@@ -1,12 +1,13 @@
import Plugin from '../Plugin';
import Joplin from './Joplin';
import Logger from '../../../Logger';
/**
* @ignore
*/
export default class Global {
private joplin_;
private requireWhiteList_;
constructor(implementation: any, plugin: Plugin, store: any);
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
get joplin(): Joplin;
private requireWhiteList;
require(filePath: string): any;

View File

@@ -7,6 +7,7 @@ import JoplinCommands from './JoplinCommands';
import JoplinViews from './JoplinViews';
import JoplinInterop from './JoplinInterop';
import JoplinSettings from './JoplinSettings';
import Logger from '../../../Logger';
/**
* This is the main entry point to the Joplin API. You can access various services using the provided accessors.
*
@@ -31,7 +32,7 @@ export default class Joplin {
private views_;
private interop_;
private settings_;
constructor(implementation: any, plugin: Plugin, store: any);
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
get data(): JoplinData;
get plugins(): JoplinPlugins;
get workspace(): JoplinWorkspace;

View File

@@ -1,11 +1,13 @@
import Plugin from '../Plugin';
import Logger from '../../../Logger';
import { ContentScriptType, Script } from './types';
/**
* This class provides access to plugin-related features.
*/
export default class JoplinPlugins {
private logger;
private plugin;
constructor(plugin: Plugin);
constructor(logger: Logger, plugin: Plugin);
/**
* Registers a new plugin. This is the entry point when creating a plugin. You should pass a simple object with an `onStart` method to it.
* That `onStart` method will be executed as soon as the plugin is loaded.

View File

@@ -6,7 +6,7 @@
"dist": "webpack",
"postinstall": "npm run dist"
},
"keywords": {},
"keywords": [],
"license": "MIT",
"devDependencies": {
"@types/node": "^14.0.14",
@@ -20,4 +20,4 @@
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}
}

View File

@@ -21,20 +21,6 @@ joplin.plugins.register({
},
});
await joplin.commands.register({
name: 'contextMenuCommandExample',
label: 'My Context Menu command',
execute: async (noteIds:string[]) => {
const notes = [];
for (const noteId of noteIds) {
notes.push(await joplin.data.get(['notes', noteId]));
}
const noteTitles = notes.map((note:any) => note.title);
alert('The following notes will be processed:\n\n' + noteTitles.join(', '));
},
});
// Commands that return a result and take argument can only be used
// programmatically, so it's not necessary to set a label and icon.
await joplin.commands.register({
@@ -54,8 +40,6 @@ joplin.plugins.register({
await joplin.views.menuItems.create('myMenuItem1', 'testCommand1', MenuItemLocation.Tools, { accelerator: 'CmdOrCtrl+Alt+Shift+B' });
await joplin.views.menuItems.create('myMenuItem2', 'testCommand2', MenuItemLocation.Tools);
await joplin.views.menuItems.create('contextMenuItem1', 'contextMenuCommandExample', MenuItemLocation.NoteListContextMenu);
console.info('Running command with arguments...');
const result = await joplin.commands.execute('commandWithResult', 'abcd', 123);
console.info('Result was: ' + result);

View File

@@ -16,13 +16,6 @@ function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`)
.map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) {
// Usually means there's an error, which is going to be printed by
// webpack
console.info('Plugin archive was not created because the "dist" directory is empty');
return;
}
fs.removeSync(destPath);
tar.create(
@@ -45,8 +38,6 @@ const manifestPath = `${srcDir}/manifest.json`;
const manifest = readManifest(manifestPath);
const archiveFilePath = path.resolve(__dirname, `${manifest.id}.jpl`);
fs.removeSync(distDir);
module.exports = {
mode: 'production',
entry: './src/index.ts',

View File

@@ -1,12 +1,13 @@
import Plugin from '../Plugin';
import Joplin from './Joplin';
import Logger from '../../../Logger';
/**
* @ignore
*/
export default class Global {
private joplin_;
private requireWhiteList_;
constructor(implementation: any, plugin: Plugin, store: any);
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
get joplin(): Joplin;
private requireWhiteList;
require(filePath: string): any;

View File

@@ -7,6 +7,7 @@ import JoplinCommands from './JoplinCommands';
import JoplinViews from './JoplinViews';
import JoplinInterop from './JoplinInterop';
import JoplinSettings from './JoplinSettings';
import Logger from '../../../Logger';
/**
* This is the main entry point to the Joplin API. You can access various services using the provided accessors.
*
@@ -31,7 +32,7 @@ export default class Joplin {
private views_;
private interop_;
private settings_;
constructor(implementation: any, plugin: Plugin, store: any);
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
get data(): JoplinData;
get plugins(): JoplinPlugins;
get workspace(): JoplinWorkspace;

View File

@@ -1,11 +1,13 @@
import Plugin from '../Plugin';
import Logger from '../../../Logger';
import { ContentScriptType, Script } from './types';
/**
* This class provides access to plugin-related features.
*/
export default class JoplinPlugins {
private logger;
private plugin;
constructor(plugin: Plugin);
constructor(logger: Logger, plugin: Plugin);
/**
* Registers a new plugin. This is the entry point when creating a plugin. You should pass a simple object with an `onStart` method to it.
* That `onStart` method will be executed as soon as the plugin is loaded.

View File

@@ -6,7 +6,7 @@
"dist": "webpack",
"postinstall": "npm run dist"
},
"keywords": {},
"keywords": [],
"license": "MIT",
"devDependencies": {
"@types/node": "^14.0.14",
@@ -20,4 +20,4 @@
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}
}

View File

@@ -16,13 +16,6 @@ function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`)
.map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) {
// Usually means there's an error, which is going to be printed by
// webpack
console.info('Plugin archive was not created because the "dist" directory is empty');
return;
}
fs.removeSync(destPath);
tar.create(
@@ -45,8 +38,6 @@ const manifestPath = `${srcDir}/manifest.json`;
const manifest = readManifest(manifestPath);
const archiveFilePath = path.resolve(__dirname, `${manifest.id}.jpl`);
fs.removeSync(distDir);
module.exports = {
mode: 'production',
entry: './src/index.ts',

View File

@@ -1,12 +1,13 @@
import Plugin from '../Plugin';
import Joplin from './Joplin';
import Logger from '../../../Logger';
/**
* @ignore
*/
export default class Global {
private joplin_;
private requireWhiteList_;
constructor(implementation: any, plugin: Plugin, store: any);
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
get joplin(): Joplin;
private requireWhiteList;
require(filePath: string): any;

View File

@@ -7,6 +7,7 @@ import JoplinCommands from './JoplinCommands';
import JoplinViews from './JoplinViews';
import JoplinInterop from './JoplinInterop';
import JoplinSettings from './JoplinSettings';
import Logger from '../../../Logger';
/**
* This is the main entry point to the Joplin API. You can access various services using the provided accessors.
*
@@ -31,7 +32,7 @@ export default class Joplin {
private views_;
private interop_;
private settings_;
constructor(implementation: any, plugin: Plugin, store: any);
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
get data(): JoplinData;
get plugins(): JoplinPlugins;
get workspace(): JoplinWorkspace;

View File

@@ -1,11 +1,13 @@
import Plugin from '../Plugin';
import Logger from '../../../Logger';
import { ContentScriptType, Script } from './types';
/**
* This class provides access to plugin-related features.
*/
export default class JoplinPlugins {
private logger;
private plugin;
constructor(plugin: Plugin);
constructor(logger: Logger, plugin: Plugin);
/**
* Registers a new plugin. This is the entry point when creating a plugin. You should pass a simple object with an `onStart` method to it.
* That `onStart` method will be executed as soon as the plugin is loaded.

View File

@@ -6,7 +6,7 @@
"dist": "webpack",
"postinstall": "npm run dist"
},
"keywords": {},
"keywords": [],
"license": "MIT",
"devDependencies": {
"@types/node": "^14.0.14",
@@ -20,4 +20,4 @@
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}
}

View File

@@ -16,13 +16,6 @@ function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`)
.map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) {
// Usually means there's an error, which is going to be printed by
// webpack
console.info('Plugin archive was not created because the "dist" directory is empty');
return;
}
fs.removeSync(destPath);
tar.create(
@@ -45,8 +38,6 @@ const manifestPath = `${srcDir}/manifest.json`;
const manifest = readManifest(manifestPath);
const archiveFilePath = path.resolve(__dirname, `${manifest.id}.jpl`);
fs.removeSync(distDir);
module.exports = {
mode: 'production',
entry: './src/index.ts',

View File

@@ -1,12 +1,13 @@
import Plugin from '../Plugin';
import Joplin from './Joplin';
import Logger from '../../../Logger';
/**
* @ignore
*/
export default class Global {
private joplin_;
private requireWhiteList_;
constructor(implementation: any, plugin: Plugin, store: any);
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
get joplin(): Joplin;
private requireWhiteList;
require(filePath: string): any;

View File

@@ -7,6 +7,7 @@ import JoplinCommands from './JoplinCommands';
import JoplinViews from './JoplinViews';
import JoplinInterop from './JoplinInterop';
import JoplinSettings from './JoplinSettings';
import Logger from '../../../Logger';
/**
* This is the main entry point to the Joplin API. You can access various services using the provided accessors.
*
@@ -31,7 +32,7 @@ export default class Joplin {
private views_;
private interop_;
private settings_;
constructor(implementation: any, plugin: Plugin, store: any);
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
get data(): JoplinData;
get plugins(): JoplinPlugins;
get workspace(): JoplinWorkspace;

View File

@@ -1,11 +1,13 @@
import Plugin from '../Plugin';
import Logger from '../../../Logger';
import { ContentScriptType, Script } from './types';
/**
* This class provides access to plugin-related features.
*/
export default class JoplinPlugins {
private logger;
private plugin;
constructor(plugin: Plugin);
constructor(logger: Logger, plugin: Plugin);
/**
* Registers a new plugin. This is the entry point when creating a plugin. You should pass a simple object with an `onStart` method to it.
* That `onStart` method will be executed as soon as the plugin is loaded.

View File

@@ -6,7 +6,7 @@
"dist": "webpack",
"postinstall": "npm run dist"
},
"keywords": {},
"keywords": [],
"license": "MIT",
"devDependencies": {
"@types/node": "^14.0.14",
@@ -23,4 +23,4 @@
"dependencies": {
"uslug": "^1.0.4"
}
}
}

View File

@@ -1,7 +1,6 @@
document.addEventListener('click', event => {
const element = event.target;
if (element.className === 'toc-item-link') {
console.debug('TOC Plugin Webview: Sending scrollToHash message', element.dataset.slug);
webviewApi.postMessage({
name: 'scrollToHash',
hash: element.dataset.slug,

View File

@@ -16,13 +16,6 @@ function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`)
.map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) {
// Usually means there's an error, which is going to be printed by
// webpack
console.info('Plugin archive was not created because the "dist" directory is empty');
return;
}
fs.removeSync(destPath);
tar.create(
@@ -45,8 +38,6 @@ const manifestPath = `${srcDir}/manifest.json`;
const manifest = readManifest(manifestPath);
const archiveFilePath = path.resolve(__dirname, `${manifest.id}.jpl`);
fs.removeSync(distDir);
module.exports = {
mode: 'production',
entry: './src/index.ts',

View File

@@ -1,12 +1,13 @@
import Plugin from '../Plugin';
import Joplin from './Joplin';
import Logger from '../../../Logger';
/**
* @ignore
*/
export default class Global {
private joplin_;
private requireWhiteList_;
constructor(implementation: any, plugin: Plugin, store: any);
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
get joplin(): Joplin;
private requireWhiteList;
require(filePath: string): any;

View File

@@ -7,6 +7,7 @@ import JoplinCommands from './JoplinCommands';
import JoplinViews from './JoplinViews';
import JoplinInterop from './JoplinInterop';
import JoplinSettings from './JoplinSettings';
import Logger from '../../../Logger';
/**
* This is the main entry point to the Joplin API. You can access various services using the provided accessors.
*
@@ -31,7 +32,7 @@ export default class Joplin {
private views_;
private interop_;
private settings_;
constructor(implementation: any, plugin: Plugin, store: any);
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
get data(): JoplinData;
get plugins(): JoplinPlugins;
get workspace(): JoplinWorkspace;

View File

@@ -1,11 +1,13 @@
import Plugin from '../Plugin';
import Logger from '../../../Logger';
import { ContentScriptType, Script } from './types';
/**
* This class provides access to plugin-related features.
*/
export default class JoplinPlugins {
private logger;
private plugin;
constructor(plugin: Plugin);
constructor(logger: Logger, plugin: Plugin);
/**
* Registers a new plugin. This is the entry point when creating a plugin. You should pass a simple object with an `onStart` method to it.
* That `onStart` method will be executed as soon as the plugin is loaded.

View File

@@ -6,7 +6,7 @@
"dist": "webpack",
"postinstall": "npm run dist"
},
"keywords": {},
"keywords": [],
"license": "MIT",
"devDependencies": {
"@types/node": "^14.0.14",
@@ -23,4 +23,4 @@
"dependencies": {
"left-pad": "^1.3.0"
}
}
}

View File

@@ -16,13 +16,6 @@ function createPluginArchive(sourceDir, destPath) {
const distFiles = glob.sync(`${sourceDir}/**/*`)
.map(f => f.substr(sourceDir.length + 1));
if (!distFiles.length) {
// Usually means there's an error, which is going to be printed by
// webpack
console.info('Plugin archive was not created because the "dist" directory is empty');
return;
}
fs.removeSync(destPath);
tar.create(
@@ -45,8 +38,6 @@ const manifestPath = `${srcDir}/manifest.json`;
const manifest = readManifest(manifestPath);
const archiveFilePath = path.resolve(__dirname, `${manifest.id}.jpl`);
fs.removeSync(distDir);
module.exports = {
mode: 'production',
entry: './src/index.ts',

View File

@@ -150,16 +150,8 @@ class Bridge {
const folders = await this.folderTree();
this.dispatch({ type: 'FOLDERS_SET', folders: folders.items ? folders.items : folders });
let tags = [];
for (let page = 1; page < 10000; page++) {
const result = await this.clipperApiExec('GET', 'tags', { page: page, order_by: 'title', order_dir: 'ASC' });
const resultTags = result.items ? result.items : result;
const hasMore = ('has_more' in result) && result.has_more;
tags = tags.concat(resultTags);
if (!hasMore) break;
}
this.dispatch({ type: 'TAGS_SET', tags: tags });
const tags = await this.clipperApiExec('GET', 'tags');
this.dispatch({ type: 'TAGS_SET', tags: tags.items ? tags.items : tags });
bridge().restoreState();
return;

View File

@@ -30,7 +30,6 @@ import { themeStyle } from '@joplin/lib/theme';
import validateLayout from '../ResizableLayout/utils/validateLayout';
import iterateItems from '../ResizableLayout/utils/iterateItems';
import removeItem from '../ResizableLayout/utils/removeItem';
import Logger from '@joplin/lib/Logger';
const { connect } = require('react-redux');
const { PromptDialog } = require('../PromptDialog.min.js');
@@ -39,8 +38,6 @@ const PluginManager = require('@joplin/lib/services/PluginManager');
const EncryptionService = require('@joplin/lib/services/EncryptionService');
const ipcRenderer = require('electron').ipcRenderer;
const logger = Logger.create('MainScreen');
interface LayerModalState {
visible: boolean;
message: string;
@@ -567,7 +564,6 @@ class MainScreenComponent extends React.Component<Props, State> {
}
userWebview_message(event: any) {
logger.debug('Got message (WebView => Plugin) (2)', event);
PluginService.instance().pluginById(event.pluginId).viewController(event.viewId).emitMessage(event);
}

View File

@@ -186,7 +186,7 @@ export default class NoteListUtils {
if (location !== MenuItemLocation.Context && location !== MenuItemLocation.NoteListContextMenu) continue;
menu.append(
new MenuItem(menuUtils.commandToStatefulMenuItem(info.view.commandName, noteIds))
new MenuItem(menuUtils.commandToStatefulMenuItem(info.view.commandName))
);
}

View File

@@ -1,6 +1,6 @@
{
"name": "@joplin/app-desktop",
"version": "1.4.19",
"version": "1.4.11",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -8828,7 +8828,9 @@
"is-docker": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.1.1.tgz",
"integrity": "sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw=="
"integrity": "sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw==",
"dev": true,
"optional": true
},
"is-dotfile": {
"version": "1.0.3",
@@ -9019,12 +9021,9 @@
"dev": true
},
"is-wsl": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
"integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
"requires": {
"is-docker": "^2.0.0"
}
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.1.1.tgz",
"integrity": "sha512-umZHcSrwlDHo2TGMXv0DZ8dIUGunZ2Iv68YZnrmCiBPkZ4aaOhtv7pXJKeki9k3qJ3RJr0cDyitcl5wEH3AYog=="
},
"is-yarn-global": {
"version": "0.3.0",
@@ -11708,30 +11707,21 @@
"dev": true
},
"node-notifier": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-8.0.0.tgz",
"integrity": "sha512-46z7DUmcjoYdaWyXouuFNNfUo6eFa94t23c53c+lG/9Cvauk4a98rAUp9672X5dxGdQmLpPzTxzu8f/OeEPaFA==",
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-6.0.0.tgz",
"integrity": "sha512-SVfQ/wMw+DesunOm5cKqr6yDcvUTDl/yc97ybGHMrteNEY6oekXpNpS3lZwgLlwz0FLgHoiW28ZpmBHUDg37cw==",
"requires": {
"growly": "^1.3.0",
"is-wsl": "^2.2.0",
"semver": "^7.3.2",
"is-wsl": "^2.1.1",
"semver": "^6.3.0",
"shellwords": "^0.1.1",
"uuid": "^8.3.0",
"which": "^2.0.2"
"which": "^1.3.1"
},
"dependencies": {
"semver": {
"version": "7.3.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
"integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ=="
},
"which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"requires": {
"isexe": "^2.0.0"
}
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
}
}
},
@@ -14994,7 +14984,9 @@
"uuid": {
"version": "8.3.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.1.tgz",
"integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg=="
"integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==",
"dev": true,
"optional": true
},
"v8-to-istanbul": {
"version": "7.0.0",
@@ -15210,7 +15202,6 @@
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
"dev": true,
"requires": {
"isexe": "^2.0.0"
}

View File

@@ -1,6 +1,6 @@
{
"name": "@joplin/app-desktop",
"version": "1.4.19",
"version": "1.4.11",
"description": "Joplin for Desktop",
"main": "main.js",
"private": true,
@@ -72,8 +72,7 @@
"artifactName": "${productName}Portable.${ext}"
},
"mac": {
"icon": "../../Assets/macOs.icns",
"target": "dmg"
"icon": "../../Assets/macOs.icns"
},
"linux": {
"icon": "../../Assets/LinuxIcons",
@@ -137,7 +136,7 @@
"md5": "^2.2.1",
"moment": "^2.22.2",
"node-fetch": "^1.7.3",
"node-notifier": "^8.0.0",
"node-notifier": "^6.0.0",
"pretty-bytes": "^5.3.0",
"re-resizable": "^6.5.4",
"react": "16.13.1",

View File

@@ -6,11 +6,8 @@ import bridge from '../bridge';
import Setting from '@joplin/lib/models/Setting';
import { EventHandlers } from '@joplin/lib/services/plugins/utils/mapEventHandlersToIds';
import shim from '@joplin/lib/shim';
import Logger from '@joplin/lib/Logger';
const ipcRenderer = require('electron').ipcRenderer;
const logger = Logger.create('PluginRunner');
enum PluginMessageTarget {
MainWindow = 'mainWindow',
Plugin = 'plugin',
@@ -130,9 +127,7 @@ export default class PluginRunner extends BasePluginRunner {
const mappedArgs = mapEventIdsToHandlers(plugin.id, message.args);
const fullPath = `joplin.${message.path}`;
// Don't log complete HTML code, which can be long, for setHtml calls
const debugMappedArgs = fullPath.includes('setHtml') ? '<hidden>' : mappedArgs;
logger.debug(`Got message (3): ${fullPath}: ${debugMappedArgs}`);
this.logger().debug(`PluginRunner: execute call: ${fullPath}: ${mappedArgs}`);
let result: any = null;
let error: any = null;

View File

@@ -7,10 +7,7 @@ import useSubmitHandler from './hooks/useSubmitHandler';
import useHtmlLoader from './hooks/useHtmlLoader';
import useWebviewToPluginMessages from './hooks/useWebviewToPluginMessages';
import useScriptLoader from './hooks/useScriptLoader';
import Logger from '@joplin/lib/Logger';
import styled from 'styled-components';
const logger = Logger.create('UserWebview');
const styled = require('styled-components').default;
export interface Props {
html: string;
@@ -75,9 +72,6 @@ function UserWebview(props: Props, ref: any) {
function postMessage(name: string, args: any = null) {
const win = frameWindow();
if (!win) return;
logger.debug('Got message', name, args);
win.postMessage({ target: 'webview', name, args }, '*');
}
@@ -118,7 +112,6 @@ function UserWebview(props: Props, ref: any) {
useWebviewToPluginMessages(
frameWindow(),
isReady,
props.onMessage,
props.pluginId,
props.viewId

View File

@@ -58,10 +58,10 @@ const webviewApi = {
setHtml: (args) => {
contentElement.innerHTML = args.html;
// console.debug('UserWebviewIndex: setting html to', args.html);
console.debug('UserWebView frame: setting html to', args.html);
window.requestAnimationFrame(() => {
console.debug('UserWebviewIndex: setting html callback', args.hash);
console.debug('UserWebView frame: setting html callback', args.hash);
window.postMessage({ target: 'UserWebview', message: 'htmlIsSet', hash: args.hash }, '*');
});
},
@@ -105,7 +105,6 @@ const webviewApi = {
if (!ipc[callName]) {
console.warn('Missing IPC function:', event.data);
} else {
console.debug('UserWebviewIndex: Got message', callName, args);
ipc[callName](args);
}
}));
@@ -116,7 +115,7 @@ const webviewApi = {
// Need to send it with a delay to make sure all listeners are
// ready when the message is sent.
window.requestAnimationFrame(() => {
console.debug('UserWebViewIndex: calling isReady');
console.debug('UserWebView frame: calling isReady');
window.postMessage({ target: 'UserWebview', message: 'ready' }, '*');
});
});

View File

@@ -39,7 +39,7 @@ export default function(frameWindow: any, isReady: boolean, postMessage: Functio
if (!isReady) return;
console.info('useHtmlLoader: setHtml', htmlHash);
console.info('useHtmlLoader: setHtml', htmlHash, html);
postMessage('setHtml', {
hash: htmlHash,

View File

@@ -1,20 +1,11 @@
import Logger from '@joplin/lib/Logger';
import { useEffect } from 'react';
const logger = Logger.create('useWebviewToPluginMessages');
export default function(frameWindow: any, isReady: boolean, onMessage: Function, pluginId: string, viewId: string) {
export default function(frameWindow: any, onMessage: Function, pluginId: string, viewId: string) {
useEffect(() => {
if (!frameWindow) return () => {};
function onMessage_(event: any) {
function onMessage(event: any) {
if (!event.data || event.data.target !== 'plugin') return;
// The message is passed from one component or service to the next
// till it reaches its destination, so if something doesn't work
// follow the chain of messages searching for the string "Got message"
logger.debug('Got message (WebView => Plugin) (1)', pluginId, viewId, event.data.message);
onMessage({
pluginId: pluginId,
viewId: viewId,
@@ -22,10 +13,10 @@ export default function(frameWindow: any, isReady: boolean, onMessage: Function,
});
}
frameWindow.addEventListener('message', onMessage_);
frameWindow.addEventListener('message', onMessage);
return () => {
frameWindow.removeEventListener('message', onMessage_);
frameWindow.removeEventListener('message', onMessage);
};
}, [frameWindow, onMessage, isReady, pluginId, viewId]);
}, [onMessage, pluginId, viewId]);
}

View File

@@ -2,10 +2,6 @@
import SpellCheckerServiceDriverBase from '@joplin/lib/services/spellChecker/SpellCheckerServiceDriverBase';
import bridge from '../bridge';
import { languageCodeOnly, localesFromLanguageCode } from '@joplin/lib/locale';
import Logger from '@joplin/lib/Logger';
const logger = Logger.create('SpellCheckerServiceDriverNative');
export default class SpellCheckerServiceDriverNative extends SpellCheckerServiceDriverBase {
@@ -21,31 +17,7 @@ export default class SpellCheckerServiceDriverNative extends SpellCheckerService
public setLanguage(v: string) {
// If we pass an empty array, it disables spell checking
// https://github.com/electron/electron/issues/25228
if (!v) {
this.session().setSpellCheckerLanguages([]);
return;
}
// The below function will throw an error if the provided language is
// not supported, so we provide fallbacks.
// https://github.com/laurent22/joplin/issues/4146
const languagesToTry = [
v,
languageCodeOnly(v),
].concat(localesFromLanguageCode(languageCodeOnly(v), this.availableLanguages));
for (const toTry of languagesToTry) {
try {
this.session().setSpellCheckerLanguages([toTry]);
logger.info(`Set effective language from "${v}" to "${toTry}"`);
return;
} catch (error) {
logger.warn(`Failed to set language to "${toTry}". Will try the next one in this list: ${JSON.stringify(languagesToTry)}`);
logger.warn('Error was:', error);
}
}
logger.error(`Could not set language to: ${v}`);
this.session().setSpellCheckerLanguages(v ? [v] : []);
}
public get language(): string {

View File

@@ -6,6 +6,5 @@
],
"exclude": [
"**/node_modules",
"**/dist",
],
}

View File

@@ -1,12 +1,13 @@
import Plugin from '../Plugin';
import Joplin from './Joplin';
import Logger from '../../../Logger';
/**
* @ignore
*/
export default class Global {
private joplin_;
private requireWhiteList_;
constructor(implementation: any, plugin: Plugin, store: any);
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
get joplin(): Joplin;
private requireWhiteList;
require(filePath: string): any;

View File

@@ -7,6 +7,7 @@ import JoplinCommands from './JoplinCommands';
import JoplinViews from './JoplinViews';
import JoplinInterop from './JoplinInterop';
import JoplinSettings from './JoplinSettings';
import Logger from '../../../Logger';
/**
* This is the main entry point to the Joplin API. You can access various services using the provided accessors.
*
@@ -31,7 +32,7 @@ export default class Joplin {
private views_;
private interop_;
private settings_;
constructor(implementation: any, plugin: Plugin, store: any);
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
get data(): JoplinData;
get plugins(): JoplinPlugins;
get workspace(): JoplinWorkspace;

View File

@@ -1,11 +1,13 @@
import Plugin from '../Plugin';
import Logger from '../../../Logger';
import { ContentScriptType, Script } from './types';
/**
* This class provides access to plugin-related features.
*/
export default class JoplinPlugins {
private logger;
private plugin;
constructor(plugin: Plugin);
constructor(logger: Logger, plugin: Plugin);
/**
* Registers a new plugin. This is the entry point when creating a plugin. You should pass a simple object with an `onStart` method to it.
* That `onStart` method will be executed as soon as the plugin is loaded.

View File

@@ -1,5 +1,5 @@
import Setting from './models/Setting';
import Logger, { TargetType, LoggerWrapper } from './Logger';
import Logger, { TargetType } from './Logger';
import shim from './shim';
import BaseService from './services/BaseService';
import reducer from './reducer';
@@ -46,7 +46,7 @@ const MigrationService = require('./services/MigrationService');
const { toSystemSlashes } = require('./path-utils');
const { setAutoFreeze } = require('immer');
const appLogger: LoggerWrapper = Logger.create('App');
const appLogger = Logger.create('App');
// const ntpClient = require('./vendor/ntp-client');
// ntpClient.dgram = require('dgram');
@@ -103,7 +103,7 @@ export default class BaseApplication {
this.decryptionWorker_resourceMetadataButNotBlobDecrypted = null;
}
logger(): LoggerWrapper {
logger() {
return appLogger;
}

View File

@@ -255,6 +255,14 @@ class BaseModel {
if (!options) options = {};
if (options.order && options.order.length) {
// const items = [];
// for (let i = 0; i < options.order.length; i++) {
// const o = options.order[i];
// let item = `\`${o.by}\``;
// if (options.caseInsensitive === true) item += ' COLLATE NOCASE';
// if (o.dir) item += ` ${o.dir}`;
// items.push(item);
// }
sql += ` ORDER BY ${paginationToSql(options)}`;
}

View File

@@ -26,7 +26,7 @@ interface Target {
source?: string;
}
export interface LoggerWrapper {
interface LoggerWrapper {
debug: Function;
info: Function;
warn: Function;

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