1
0
mirror of https://github.com/laurent22/joplin.git synced 2026-02-25 09:18:58 +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
107 changed files with 376 additions and 611 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

@@ -28,7 +28,7 @@ Linux | <a href='https://github.com/laurent22/joplin/releases/download/
Operating System | Download | Alt. Download
-----------------|----------|----------------
Android | <a href='https://play.google.com/store/apps/details?id=net.cozic.joplin&utm_source=GitHub&utm_campaign=README&pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1'><img alt='Get it on Google Play' height="40px" src='https://joplinapp.org/images/BadgeAndroid.png'/></a> | or download the APK file: [64-bit](https://github.com/laurent22/joplin-android/releases/download/android-v1.4.11/joplin-v1.4.11.apk) [32-bit](https://github.com/laurent22/joplin-android/releases/download/android-v1.4.11/joplin-v1.4.11-32bit.apk)
Android | <a href='https://play.google.com/store/apps/details?id=net.cozic.joplin&utm_source=GitHub&utm_campaign=README&pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1'><img alt='Get it on Google Play' height="40px" src='https://joplinapp.org/images/BadgeAndroid.png'/></a> | or download the APK file: [64-bit](https://github.com/laurent22/joplin-android/releases/download/android-v1.3.13/joplin-v1.3.13.apk) [32-bit](https://github.com/laurent22/joplin-android/releases/download/android-v1.3.13/joplin-v1.3.13-32bit.apk)
iOS | <a href='https://itunes.apple.com/us/app/joplin/id1315599797'><img alt='Get it on the App Store' height="40px" src='https://joplinapp.org/images/BadgeIOS.png'/></a> | -
## Terminal application

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.7",
"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

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

@@ -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.12",
"version": "1.4.11",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@@ -1,6 +1,6 @@
{
"name": "@joplin/app-desktop",
"version": "1.4.12",
"version": "1.4.11",
"description": "Joplin for Desktop",
"main": "main.js",
"private": true,

View File

@@ -138,8 +138,8 @@ android {
applicationId "net.cozic.joplin"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 2097613
versionName "1.4.11"
versionCode 2097608
versionName "1.4.6"
ndk {
abiFilters "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
}

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

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

View File

@@ -18,7 +18,7 @@ const shim = require('./shim').default;
// const Promise = require('promise');
const fs = require('fs-extra');
function dateToTimestamp(s, defaultValue = null) {
function dateToTimestamp(s, zeroIfInvalid = false) {
// Most dates seem to be in this format
let m = moment(s, 'YYYYMMDDTHHmmssZ');
@@ -27,7 +27,7 @@ function dateToTimestamp(s, defaultValue = null) {
if (!m.isValid()) m = moment(s, 'YYYYMMDDThmmss AZ');
if (!m.isValid()) {
if (defaultValue !== null) return defaultValue;
if (zeroIfInvalid) return 0;
throw new Error(`Invalid date: ${s}`);
}
@@ -258,20 +258,6 @@ function importEnex(parentFolderId, filePath, importOptions = null) {
if (!('onProgress' in importOptions)) importOptions.onProgress = function() {};
if (!('onError' in importOptions)) importOptions.onError = function() {};
const handleSaxStreamEvent = (fn) => {
return function(...args) {
try {
fn(...args);
} catch (error) {
if (importOptions.onError) {
importOptions.onError(error);
} else {
console.error(error);
}
}
};
};
return new Promise((resolve, reject) => {
const progressState = {
loaded: 0,
@@ -351,15 +337,9 @@ function importEnex(parentFolderId, filePath, importOptions = null) {
note.parent_id = parentFolderId;
note.body = body;
// If the created timestamp was invalid, it would be
// set to zero, so set it to the current date here
if (!note.created_time) note.created_time = Date.now();
// Notes in enex files always have a created timestamp
// but not always an updated timestamp (it the note has
// never been modified). For sync we require an
// updated_time property, so set it to create_time in
// that case
// Notes in enex files always have a created timestamp but not always an
// updated timestamp (it the note has never been modified). For sync
// we require an updated_time property, so set it to create_time in that case
if (!note.updated_time) note.updated_time = note.created_time;
const result = await saveNoteToStorage(note, importOptions);
@@ -388,7 +368,7 @@ function importEnex(parentFolderId, filePath, importOptions = null) {
importOptions.onError(error);
});
saxStream.on('text', handleSaxStreamEvent(function(text) {
saxStream.on('text', function(text) {
const n = currentNodeName();
if (noteAttributes) {
@@ -415,9 +395,9 @@ function importEnex(parentFolderId, filePath, importOptions = null) {
if (n == 'title') {
note.title = text;
} else if (n == 'created') {
note.created_time = dateToTimestamp(text, 0);
note.created_time = dateToTimestamp(text);
} else if (n == 'updated') {
note.updated_time = dateToTimestamp(text, 0);
note.updated_time = dateToTimestamp(text);
} else if (n == 'tag') {
note.tags.push(text);
} else if (n == 'note') {
@@ -428,9 +408,9 @@ function importEnex(parentFolderId, filePath, importOptions = null) {
console.warn(`Unsupported note tag: ${n}`);
}
}
}));
});
saxStream.on('opentag', handleSaxStreamEvent(function(node) {
saxStream.on('opentag', function(node) {
const n = node.name.toLowerCase();
nodes.push(node);
@@ -448,9 +428,9 @@ function importEnex(parentFolderId, filePath, importOptions = null) {
} else if (n == 'resource') {
noteResource = {};
}
}));
});
saxStream.on('cdata', handleSaxStreamEvent(function(data) {
saxStream.on('cdata', function(data) {
const n = currentNodeName();
if (noteResourceRecognition) {
@@ -464,9 +444,9 @@ function importEnex(parentFolderId, filePath, importOptions = null) {
}
}
}
}));
});
saxStream.on('closetag', handleSaxStreamEvent(function(n) {
saxStream.on('closetag', async function(n) {
nodes.pop();
if (n == 'note') {
@@ -496,9 +476,9 @@ function importEnex(parentFolderId, filePath, importOptions = null) {
note.altitude = noteAttributes.altitude;
note.author = noteAttributes.author ? noteAttributes.author.trim() : '';
note.is_todo = noteAttributes['reminder-order'] !== '0' && !!noteAttributes['reminder-order'];
note.todo_due = dateToTimestamp(noteAttributes['reminder-time'], 0);
note.todo_completed = dateToTimestamp(noteAttributes['reminder-done-time'], 0);
note.order = dateToTimestamp(noteAttributes['reminder-order'], 0);
note.todo_due = dateToTimestamp(noteAttributes['reminder-time'], true);
note.todo_completed = dateToTimestamp(noteAttributes['reminder-done-time'], true);
note.order = dateToTimestamp(noteAttributes['reminder-order'], true);
note.source = noteAttributes.source ? `evernote.${noteAttributes.source.trim()}` : 'evernote';
note.source_url = noteAttributes['source-url'] ? noteAttributes['source-url'].trim() : '';
@@ -515,9 +495,9 @@ function importEnex(parentFolderId, filePath, importOptions = null) {
noteResource = null;
}
}));
});
saxStream.on('end', handleSaxStreamEvent(function() {
saxStream.on('end', function() {
// Wait till there is no more notes to process.
const iid = shim.setInterval(() => {
processNotes().then(allDone => {
@@ -527,7 +507,7 @@ function importEnex(parentFolderId, filePath, importOptions = null) {
}
});
}, 500);
}));
});
stream.pipe(saxStream);
});

View File

@@ -260,13 +260,7 @@ class BaseItem extends BaseModel {
propValue = `${propValue}`;
}
if (propName === 'body') return propValue;
return propValue
.replace(/\\n/g, '\\\\n')
.replace(/\\r/g, '\\\\r')
.replace(/\n/g, '\\n')
.replace(/\r/g, '\\r');
return propValue.replace(/\n/g, '\\n').replace(/\r/g, '\\r');
}
static unserialize_format(type, propName, propValue) {
@@ -287,14 +281,7 @@ class BaseItem extends BaseModel {
propValue = Database.formatValue(ItemClass.fieldType(propName), propValue);
}
if (propName === 'body') return propValue;
return typeof propValue === 'string' ? propValue
.replace(/\\n/g, '\n')
.replace(/\\r/g, '\r')
.replace(/\\\n/g, '\\n')
.replace(/\\\r/g, '\\r')
: propValue;
return typeof propValue === 'string' ? propValue.replace(/\\n/g, '\n').replace(/\\r/g, '\r') : propValue;
}
static async serialize(item, shownKeys = null) {

View File

@@ -1,7 +1,6 @@
import AsyncActionQueue from '../../AsyncActionQueue';
import shim from '../../shim';
import { _ } from '../../locale';
import { toSystemSlashes } from '../../path-utils';
const Logger = require('../../Logger').default;
const Setting = require('../../models/Setting').default;
const Resource = require('../../models/Resource');
@@ -158,8 +157,6 @@ export default class ResourceEditWatcher {
if (!this.watcher_) {
this.watcher_ = this.chokidar_.watch(fileToWatch);
this.watcher_.on('all', async (event: any, path: string) => {
path = toSystemSlashes(path, 'linux');
this.logger().info(`ResourceEditWatcher: Event: ${event}: ${path}`);
if (event === 'unlink') {
@@ -186,13 +183,11 @@ export default class ResourceEditWatcher {
//
// @ts-ignore Leave unused path variable
this.watcher_.on('raw', async (event: string, path: string, options: any) => {
const watchedPath = toSystemSlashes(options.watchedPath, 'linux');
this.logger().debug(`ResourceEditWatcher: Raw event: ${event}: ${watchedPath}`);
this.logger().debug(`ResourceEditWatcher: Raw event: ${event}: ${options.watchedPath}`);
if (event === 'rename') {
this.watcher_.unwatch(watchedPath);
this.watcher_.add(watchedPath);
handleChangeEvent(watchedPath);
this.watcher_.unwatch(options.watchedPath);
this.watcher_.add(options.watchedPath);
handleChangeEvent(options.watchedPath);
}
});
} else {
@@ -223,7 +218,7 @@ export default class ResourceEditWatcher {
if (!(await Resource.isReady(resource))) throw new Error(_('This attachment is not downloaded or not decrypted yet'));
const sourceFilePath = Resource.fullPath(resource);
const tempDir = await this.tempDir();
const editFilePath = toSystemSlashes(await shim.fsDriver().findUniqueFilename(`${tempDir}/${Resource.friendlySafeFilename(resource)}`), 'linux');
const editFilePath = await shim.fsDriver().findUniqueFilename(`${tempDir}/${Resource.friendlySafeFilename(resource)}`);
await shim.fsDriver().copy(sourceFilePath, editFilePath);
const stat = await shim.fsDriver().stat(editFilePath);

File diff suppressed because one or more lines are too long

View File

@@ -44,12 +44,12 @@ export default class HtmlToHtml {
private resourceBaseUrl_;
private ResourceModel_;
private cache_;
private fsDriver_: any;
private fsDriver_:any;
constructor(options: Options = null) {
constructor(options:Options = null) {
options = {
ResourceModel: null,
...options,
...options
};
this.resourceBaseUrl_ = 'resourceBaseUrl' in options ? options.resourceBaseUrl : null;
@@ -72,7 +72,7 @@ export default class HtmlToHtml {
return this.fsDriver_;
}
splitHtml(html: string) {
splitHtml(html:string) {
const trimmedHtml = html.trimStart();
if (trimmedHtml.indexOf('<style>') !== 0) return { html: html, css: '' };
@@ -85,14 +85,14 @@ export default class HtmlToHtml {
};
}
async allAssets(/* theme*/): Promise<any[]> {
async allAssets(/* theme*/):Promise<any[]> {
return []; // TODO
}
// Note: the "theme" variable is ignored and instead the light theme is
// always used for HTML notes.
// See: https://github.com/laurent22/joplin/issues/3698
async render(markup: string, _theme: any, options: RenderOptions): Promise<RenderResult> {
async render(markup:string, _theme:any, options:RenderOptions):Promise<RenderResult> {
options = {
splitted: false,
postMessageSyntax: 'postMessage',
@@ -106,7 +106,7 @@ export default class HtmlToHtml {
if (!html) {
html = htmlUtils.sanitizeHtml(markup);
html = htmlUtils.processImageTags(html, (data: any) => {
html = htmlUtils.processImageTags(html, (data:any) => {
if (!data.src) return null;
const r = utils.imageReplacement(this.ResourceModel_, data.src, options.resources, this.resourceBaseUrl_);
@@ -125,7 +125,7 @@ export default class HtmlToHtml {
}
});
html = htmlUtils.processAnchorTags(html, (data: any) => {
html = htmlUtils.processAnchorTags(html, (data:any) => {
if (!data.href) return null;
const r = linkReplacement(data.href, {
@@ -134,7 +134,7 @@ export default class HtmlToHtml {
postMessageSyntax: options.postMessageSyntax,
enableLongPress: options.enableLongPress,
});
if (!r) return null;
return {
@@ -155,13 +155,13 @@ export default class HtmlToHtml {
// const lightTheme = themeStyle(Setting.THEME_LIGHT);
// let cssStrings = noteStyle(lightTheme);
let cssStrings: string[] = [];
let cssStrings:string[] = [];
if (options.splitted) {
const splitted = this.splitHtml(html);
cssStrings = [splitted.css].concat(cssStrings);
const output: RenderResult = {
const output:RenderResult = {
html: splitted.html,
pluginAssets: [],
};

View File

@@ -378,7 +378,7 @@ export default class MdToHtml {
const markdownIt = new MarkdownIt({
breaks: !this.pluginEnabled('softbreaks'),
typographer: this.pluginEnabled('typographer'),
linkify: true,
// linkify: true,
html: true,
highlight: (str: string, lang: string) => {
let outputCodeHtml = '';
@@ -409,16 +409,10 @@ export default class MdToHtml {
outputCodeHtml = markdownIt.utils.escapeHtml(trimmedStr);
}
const html = `<div class="joplin-editable">${sourceBlockHtml}<pre class="hljs"><code>${outputCodeHtml}</code></pre></div>`;
if (rules.fence) {
return {
wrapCode: false,
html: html,
};
} else {
return html;
}
return {
wrapCode: false,
html: `<div class="joplin-editable">${sourceBlockHtml}<pre class="hljs"><code>${outputCodeHtml}</code></pre></div>`,
};
},
});

View File

@@ -4,18 +4,18 @@ describe('linkReplacement', () => {
test('should handle non-resource links', () => {
const r = linkReplacement('https://example.com/test');
expect(r).toBe('<a data-from-md href=\'https://example.com/test\' onclick=\'postMessage("https://example.com/test", { resourceId: "" }); return false;\'>');
expect(r).toBe(`<a data-from-md href='https://example.com/test' onclick='postMessage("https://example.com/test", { resourceId: "" }); return false;'>`);
});
test('should handle non-resource links - simple rendering', () => {
const r = linkReplacement('https://example.com/test', { linkRenderingType: 2 });
expect(r).toBe('<a data-from-md href=\'https://example.com/test\'>');
expect(r).toBe(`<a data-from-md href='https://example.com/test'>`);
});
test('should handle resource links - downloaded status', () => {
const resourceId = 'f6afba55bdf74568ac94f8d1e3578d2c';
const r = linkReplacement(`:/${resourceId}`, {
const r = linkReplacement(':/' + resourceId, {
ResourceModel: {},
resources: {
[resourceId]: {
@@ -33,7 +33,7 @@ describe('linkReplacement', () => {
test('should handle resource links - idle status', () => {
const resourceId = 'f6afba55bdf74568ac94f8d1e3578d2c';
const r = linkReplacement(`:/${resourceId}`, {
const r = linkReplacement(':/' + resourceId, {
ResourceModel: {},
resources: {
[resourceId]: {
@@ -46,8 +46,8 @@ describe('linkReplacement', () => {
});
// Since the icon is embedded as SVG, we only check for the prefix
const expectedPrefix = `<a class="not-loaded-resource resource-status-notDownloaded" data-resource-id="${resourceId}"><img src="data:image/svg+xml;utf8`;
const expectedPrefix = `<a class="not-loaded-resource resource-status-notDownloaded" data-resource-id="${resourceId}"><img src="data:image/svg+xml;utf8`
expect(r.indexOf(expectedPrefix)).toBe(0);
});
});

View File

@@ -5,16 +5,16 @@ const urlUtils = require('../urlUtils.js');
const { getClassNameForMimeType } = require('font-awesome-filetypes');
export interface Options {
title?: string;
resources?: any;
ResourceModel?: any;
linkRenderingType?: number;
plainResourceRendering?: boolean;
postMessageSyntax?: string;
enableLongPress?: boolean;
title?:string,
resources?:any,
ResourceModel?:any,
linkRenderingType?:number,
plainResourceRendering?:boolean,
postMessageSyntax?:string,
enableLongPress?:boolean,
}
export default function(href: string, options: Options = null) {
export default function(href:string, options:Options = null) {
options = {
title: '',
resources: {},
@@ -29,7 +29,7 @@ export default function(href: string, options: Options = null) {
const resourceHrefInfo = urlUtils.parseResourceUrl(href);
const isResourceUrl = options.resources && !!resourceHrefInfo;
let title = options.title;
let resourceIdAttr = '';
let icon = '';
let hrefAttr = '#';
@@ -54,8 +54,8 @@ export default function(href: string, options: Options = null) {
if (resourceHrefInfo.hash) href += `#${resourceHrefInfo.hash}`;
resourceIdAttr = `data-resource-id='${resourceId}'`;
const iconType = mime ? getClassNameForMimeType(mime) : 'fa-joplin';
let iconType = mime ? getClassNameForMimeType(mime) : 'fa-joplin';
// Icons are defined in lib/renderers/noteStyle using inline svg
// The icons are taken from fork-awesome but use the font-awesome naming scheme in order
// to be more compatible with the getClass library
@@ -101,4 +101,4 @@ export default function(href: string, options: Options = null) {
}
return `<a ${attrHtml.join(' ')}>${icon}`;
}
}

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