You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-08-24 20:19:10 +02:00
Compare commits
6 Commits
ios-v13.3.
...
mobile_plu
Author | SHA1 | Date | |
---|---|---|---|
|
6001e07cbc | ||
|
6210d85192 | ||
|
0c981ae4a7 | ||
|
401eee568a | ||
|
0b85e16125 | ||
|
0368c26ead |
@@ -76,6 +76,7 @@ plugin_types/
|
||||
readme/
|
||||
packages/react-native-vosk/lib/
|
||||
packages/lib/countable/Countable.js
|
||||
packages/app-mobile/plugins
|
||||
|
||||
# AUTO-GENERATED - EXCLUDED TYPESCRIPT BUILD
|
||||
packages/app-cli/app/LinkSelector.js
|
||||
@@ -443,6 +444,7 @@ packages/app-mobile/root.js
|
||||
packages/app-mobile/services/AlarmServiceDriver.android.js
|
||||
packages/app-mobile/services/AlarmServiceDriver.ios.js
|
||||
packages/app-mobile/services/e2ee/RSA.react-native.js
|
||||
packages/app-mobile/services/plugins/PluginRunner.js
|
||||
packages/app-mobile/services/profiles/index.js
|
||||
packages/app-mobile/services/voiceTyping/vosk.android.js
|
||||
packages/app-mobile/services/voiceTyping/vosk.ios.js
|
||||
@@ -456,6 +458,7 @@ packages/app-mobile/utils/checkPermissions.js
|
||||
packages/app-mobile/utils/createRootStyle.js
|
||||
packages/app-mobile/utils/debounce.js
|
||||
packages/app-mobile/utils/fs-driver-rn.js
|
||||
packages/app-mobile/utils/markupLanguageUtils.js
|
||||
packages/app-mobile/utils/setupNotifications.js
|
||||
packages/app-mobile/utils/shareHandler.js
|
||||
packages/app-mobile/utils/types.js
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@@ -428,6 +428,7 @@ packages/app-mobile/root.js
|
||||
packages/app-mobile/services/AlarmServiceDriver.android.js
|
||||
packages/app-mobile/services/AlarmServiceDriver.ios.js
|
||||
packages/app-mobile/services/e2ee/RSA.react-native.js
|
||||
packages/app-mobile/services/plugins/PluginRunner.js
|
||||
packages/app-mobile/services/profiles/index.js
|
||||
packages/app-mobile/services/voiceTyping/vosk.android.js
|
||||
packages/app-mobile/services/voiceTyping/vosk.ios.js
|
||||
@@ -441,6 +442,7 @@ packages/app-mobile/utils/checkPermissions.js
|
||||
packages/app-mobile/utils/createRootStyle.js
|
||||
packages/app-mobile/utils/debounce.js
|
||||
packages/app-mobile/utils/fs-driver-rn.js
|
||||
packages/app-mobile/utils/markupLanguageUtils.js
|
||||
packages/app-mobile/utils/setupNotifications.js
|
||||
packages/app-mobile/utils/shareHandler.js
|
||||
packages/app-mobile/utils/types.js
|
||||
|
@@ -262,6 +262,8 @@ class Application extends BaseApplication {
|
||||
if (this.initPluginServiceDone_) return;
|
||||
this.initPluginServiceDone_ = true;
|
||||
|
||||
PlatformImplementation.instance().initialize((action: any) => this.dispatch(action));
|
||||
|
||||
const service = PluginService.instance();
|
||||
|
||||
const pluginRunner = new PluginRunner();
|
||||
|
@@ -5,6 +5,8 @@ import { VersionInfo } from '@joplin/lib/services/plugins/api/types';
|
||||
import Setting from '@joplin/lib/models/Setting';
|
||||
import { reg } from '@joplin/lib/registry';
|
||||
import BasePlatformImplementation, { Joplin } from '@joplin/lib/services/plugins/BasePlatformImplementation';
|
||||
import { Dispatch } from 'redux';
|
||||
import { readFile } from 'fs-extra';
|
||||
const { clipboard, nativeImage } = require('electron');
|
||||
const packageInfo = require('../../packageInfo');
|
||||
|
||||
@@ -20,12 +22,17 @@ export default class PlatformImplementation extends BasePlatformImplementation {
|
||||
private static instance_: PlatformImplementation;
|
||||
private joplin_: Joplin;
|
||||
private components_: Components;
|
||||
private dispatch_: Dispatch|null = null;
|
||||
|
||||
public static instance(): PlatformImplementation {
|
||||
if (!this.instance_) this.instance_ = new PlatformImplementation();
|
||||
return this.instance_;
|
||||
}
|
||||
|
||||
public initialize(dispatch: Dispatch) {
|
||||
this.dispatch_ = dispatch;
|
||||
}
|
||||
|
||||
public get versionInfo(): VersionInfo {
|
||||
return {
|
||||
version: packageInfo.version,
|
||||
@@ -45,6 +52,14 @@ export default class PlatformImplementation extends BasePlatformImplementation {
|
||||
public get window(): WindowImplementation {
|
||||
return {
|
||||
injectCustomStyles: injectCustomStyles,
|
||||
loadNoteCssFile: async (filePath) => {
|
||||
const cssString = await readFile(filePath, 'utf8');
|
||||
|
||||
this.dispatch_({
|
||||
type: 'CUSTOM_CSS_APPEND',
|
||||
css: cssString,
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -47,7 +47,7 @@ react {
|
||||
// hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc"
|
||||
//
|
||||
// The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map"
|
||||
// hermesFlags = ["-O", "-output-source-map"]
|
||||
hermesFlags = ["-O", "-output-source-map"]
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -2,7 +2,7 @@ import { useEffect, useState, useMemo, useRef } from 'react';
|
||||
import shim from '@joplin/lib/shim';
|
||||
import Setting from '@joplin/lib/models/Setting';
|
||||
const { themeStyle } = require('../../global-style.js');
|
||||
import markupLanguageUtils from '@joplin/lib/markupLanguageUtils';
|
||||
import markupLanguageUtils from '../../../utils/markupLanguageUtils';
|
||||
import Logger from '@joplin/utils/Logger';
|
||||
const { assetsToHeaders } = require('@joplin/renderer');
|
||||
|
||||
|
@@ -328,7 +328,7 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "export NODE_BINARY=/usr/local/bin/node\n../node_modules/react-native/scripts/react-native-xcode.sh\n";
|
||||
shellScript = "export NODE_BINARY=/usr/local/bin/node\nexport SOURCEMAP_FILE=\"$(pwd)/../main.jsbundle.map\";\n../node_modules/react-native/scripts/react-native-xcode.sh\n";
|
||||
};
|
||||
027E2AA6B101F8CFCA582EC1 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
|
@@ -13,15 +13,17 @@
|
||||
const path = require('path');
|
||||
|
||||
const localPackages = {
|
||||
'@joplin/fork-htmlparser2': path.resolve(__dirname, '../fork-htmlparser2/'),
|
||||
'@joplin/fork-sax': path.resolve(__dirname, '../fork-sax/'),
|
||||
'@joplin/fork-uslug': path.resolve(__dirname, '../fork-uslug/'),
|
||||
'@joplin/lib': path.resolve(__dirname, '../lib/'),
|
||||
'@joplin/react-native-alarm-notification': path.resolve(__dirname, '../react-native-alarm-notification/'),
|
||||
'@joplin/react-native-saf-x': path.resolve(__dirname, '../react-native-saf-x/'),
|
||||
'@joplin/renderer': path.resolve(__dirname, '../renderer/'),
|
||||
'@joplin/tools': path.resolve(__dirname, '../tools/'),
|
||||
'@joplin/turndown-plugin-gfm': path.resolve(__dirname, '../turndown-plugin-gfm/'),
|
||||
'@joplin/turndown': path.resolve(__dirname, '../turndown/'),
|
||||
'@joplin/utils': path.resolve(__dirname, '../utils/'),
|
||||
'@joplin/fork-htmlparser2': path.resolve(__dirname, '../fork-htmlparser2/'),
|
||||
'@joplin/fork-uslug': path.resolve(__dirname, '../fork-uslug/'),
|
||||
'@joplin/react-native-saf-x': path.resolve(__dirname, '../react-native-saf-x/'),
|
||||
'@joplin/react-native-alarm-notification': path.resolve(__dirname, '../react-native-alarm-notification/'),
|
||||
'@joplin/fork-sax': path.resolve(__dirname, '../fork-sax/'),
|
||||
};
|
||||
|
||||
const remappedPackages = {
|
||||
@@ -32,7 +34,12 @@ const remappedPackages = {
|
||||
// versions. For example, this allows us to `import {resolve} from 'path'` rather than
|
||||
// `const { resolve } = require('path-browserify')` ('path-browerify' doesn't have its own type
|
||||
// definitions).
|
||||
const browserifiedPackages = ['path'];
|
||||
const browserifiedPackages = [
|
||||
'http',
|
||||
'https',
|
||||
'os',
|
||||
'path',
|
||||
];
|
||||
for (const package of browserifiedPackages) {
|
||||
remappedPackages[package] = path.resolve(__dirname, `./node_modules/${package}-browserify/`);
|
||||
}
|
||||
@@ -74,6 +81,30 @@ module.exports = {
|
||||
},
|
||||
}
|
||||
),
|
||||
|
||||
// Documentation at https://facebook.github.io/metro/docs/configuration/
|
||||
resolveRequest: (context, moduleName, platform) => {
|
||||
// console.info('Module: ' + moduleName + ' / ' + context.originModulePath);
|
||||
|
||||
// This can be used to allow importing a module that requires `fs`
|
||||
// somewhere. For example, the `css` package which is used to parse
|
||||
// CSS strings has a `loadFile()` function that we don't need, but
|
||||
// that makes it import the `fs` package.
|
||||
//
|
||||
// So by having this here, we can use those packages as long as we
|
||||
// don't use the specific methods that require `fs`. It's something
|
||||
// to keep in mind if we get weird-related fs errors - it may be
|
||||
// because the package is trying to access the mocked `fs` package.
|
||||
if (moduleName === 'fs') {
|
||||
return {
|
||||
filePath: path.resolve(__dirname, 'mock-fs.js'),
|
||||
type: 'sourceFile',
|
||||
};
|
||||
}
|
||||
|
||||
// Default resolver
|
||||
return context.resolveRequest(context, moduleName, platform);
|
||||
},
|
||||
},
|
||||
projectRoot: path.resolve(__dirname),
|
||||
watchFolders: watchedFolders,
|
||||
|
13
packages/app-mobile/mock-fs.js
Normal file
13
packages/app-mobile/mock-fs.js
Normal file
@@ -0,0 +1,13 @@
|
||||
function traceMethodCalls(obj) {
|
||||
const handler = {
|
||||
get(_target, propKey, _receiver) {
|
||||
if (propKey === '$$typeof') return 'object';
|
||||
throw new Error(`Trying to access member of mocked fs package: \`fs.${propKey}\``);
|
||||
},
|
||||
};
|
||||
return new Proxy(obj, handler);
|
||||
}
|
||||
|
||||
const mockFs = {};
|
||||
|
||||
module.exports = traceMethodCalls(mockFs);
|
@@ -35,9 +35,12 @@
|
||||
"crypto-browserify": "3.12.0",
|
||||
"deprecated-react-native-prop-types": "4.0.0",
|
||||
"events": "3.3.0",
|
||||
"http-browserify": "1.7.0",
|
||||
"https-browserify": "1.0.0",
|
||||
"jsc-android": "241213.1.0",
|
||||
"lodash": "4.17.21",
|
||||
"md5": "2.3.0",
|
||||
"os-browserify": "0.3.0",
|
||||
"path-browserify": "1.0.1",
|
||||
"prop-types": "15.8.1",
|
||||
"punycode": "2.3.0",
|
||||
|
@@ -0,0 +1,7 @@
|
||||
const initPlugin = joplin => {
|
||||
|
||||
!function(t){var e={};function o(n){if(e[n])return e[n].exports;var r=e[n]={i:n,l:!1,exports:{}};return t[n].call(r.exports,r,r.exports,o),r.l=!0,r.exports}o.m=t,o.c=e,o.d=function(t,e,n){o.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},o.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},o.t=function(t,e){if(1&e&&(t=o(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(o.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var r in t)o.d(n,r,function(e){return t[e]}.bind(null,r));return n},o.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return o.d(e,"a",e),e},o.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},o.p="",o(o.s=0)}([function(t,e,o){"use strict";var n=this&&this.__awaiter||function(t,e,o,n){return new(o||(o=Promise))((function(r,i){function u(t){try{c(n.next(t))}catch(t){i(t)}}function l(t){try{c(n.throw(t))}catch(t){i(t)}}function c(t){var e;t.done?r(t.value):(e=t.value,e instanceof o?e:new o((function(t){t(e)}))).then(u,l)}c((n=n.apply(t,e||[])).next())}))};Object.defineProperty(e,"__esModule",{value:!0});const r=o(1),i=o(2);r.default.plugins.register({onStart:function(){return n(this,void 0,void 0,(function*(){yield r.default.contentScripts.register(i.ContentScriptType.MarkdownItPlugin,"todoTxtMd","./todoTxtMdRule.js"),yield r.default.contentScripts.register(i.ContentScriptType.CodeMirrorPlugin,"todoTxtMdCtrl","./todoTxtMdCtrl.js"),yield r.default.contentScripts.onMessage("todoTxtMd",t=>{r.default.commands.execute("editor.execCommand",{name:"todoTxtAction",args:[t]}),r.default.commands.execute("editor.focus")})}))}})},function(t,e,o){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.default=joplin},function(t,e,o){"use strict";var n;Object.defineProperty(e,"__esModule",{value:!0}),e.ContentScriptType=e.SettingStorage=e.AppType=e.SettingItemType=e.ToolbarButtonLocation=e.isContextMenuItemLocation=e.MenuItemLocation=e.ImportModuleOutputFormat=e.FileSystemItem=void 0,function(t){t.File="file",t.Directory="directory"}(e.FileSystemItem||(e.FileSystemItem={})),function(t){t.Markdown="md",t.Html="html"}(e.ImportModuleOutputFormat||(e.ImportModuleOutputFormat={})),function(t){t.File="file",t.Edit="edit",t.View="view",t.Note="note",t.Tools="tools",t.Help="help",t.Context="context",t.NoteListContextMenu="noteListContextMenu",t.EditorContextMenu="editorContextMenu",t.FolderContextMenu="folderContextMenu",t.TagContextMenu="tagContextMenu"}(n=e.MenuItemLocation||(e.MenuItemLocation={})),e.isContextMenuItemLocation=function(t){return[n.Context,n.NoteListContextMenu,n.EditorContextMenu,n.FolderContextMenu,n.TagContextMenu].includes(t)},function(t){t.NoteToolbar="noteToolbar",t.EditorToolbar="editorToolbar"}(e.ToolbarButtonLocation||(e.ToolbarButtonLocation={})),function(t){t[t.Int=1]="Int",t[t.String=2]="String",t[t.Bool=3]="Bool",t[t.Array=4]="Array",t[t.Object=5]="Object",t[t.Button=6]="Button"}(e.SettingItemType||(e.SettingItemType={})),function(t){t.Desktop="desktop",t.Mobile="mobile",t.Cli="cli"}(e.AppType||(e.AppType={})),function(t){t[t.Database=1]="Database",t[t.File=2]="File"}(e.SettingStorage||(e.SettingStorage={})),function(t){t.MarkdownItPlugin="markdownItPlugin",t.CodeMirrorPlugin="codeMirrorPlugin"}(e.ContentScriptType||(e.ContentScriptType={}))}]);
|
||||
|
||||
}
|
||||
|
||||
module.exports = { initPlugin };
|
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"manifest_version": 1,
|
||||
"id": "com.hieuthi.joplin.metis",
|
||||
"app_min_version": "2.2",
|
||||
"version": "0.1.5",
|
||||
"name": "Metis",
|
||||
"description": "A Simple Task Manager Plugin for Joplin based on Todo.txt Specification",
|
||||
"author": "Hieu-Thi Luong",
|
||||
"homepage_url": "https://github.com/hieuthi/joplin-plugin-metis",
|
||||
"repository_url": "https://github.com/hieuthi/joplin-plugin-metis",
|
||||
"keywords": ["joplin-plugin","todo","todotxt","task management"]
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,163 @@
|
||||
ul.todotxt {
|
||||
--color-default: #999;
|
||||
--color-faded: #999;
|
||||
--color-A: rgb(247, 210, 110); /* yellow* */
|
||||
--color-B: rgb(152, 104, 1); /* red */
|
||||
--color-C: rgb(80, 161, 79); /* green */
|
||||
--color-D: rgb(21, 91, 218); /* blue */
|
||||
--project-background-color: rgb(247, 210, 110);
|
||||
--project-color: black;
|
||||
--context-color: rgb(152, 104, 1);
|
||||
--transition-duration: 0.15s;
|
||||
}
|
||||
|
||||
ul.todotxt { list-style:none; }
|
||||
ul.todotxt li {
|
||||
list-style-type:none;
|
||||
border-bottom: dashed 1px;
|
||||
margin-bottom: 4px;
|
||||
line-height: 1.2em;
|
||||
}
|
||||
ul.todotxt li.todotxt-header {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.todo-priority {
|
||||
display: inline-block;
|
||||
width: 1.2em;
|
||||
overflow: hidden;
|
||||
color: var(--color-default);
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
.todo-priority select {
|
||||
appearance: none;
|
||||
background-color: transparent;
|
||||
border-color: transparent;
|
||||
color: inherit;
|
||||
font-size: inherit;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
}
|
||||
.todo-priority select:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
.todo-priority select:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.todo-panel {
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
line-height: 1em;
|
||||
text-align: right;
|
||||
margin: 2px 0 4px 0;
|
||||
color: var(--color-faded);
|
||||
}
|
||||
.todo-completion, .todo-creation {
|
||||
display: inline-block;
|
||||
min-width: 6em;
|
||||
}
|
||||
.todo-project {
|
||||
background-color: var(--project-background-color);
|
||||
color: var(--project-color);
|
||||
border-radius: 2px;
|
||||
}
|
||||
.todo-context {
|
||||
color: var(--context-color);
|
||||
}
|
||||
.todo-count {
|
||||
color: var(--color-faded);
|
||||
}
|
||||
.todo-count::before{
|
||||
content: '/';
|
||||
}
|
||||
.todo-meta {
|
||||
color: var(--color-faded);
|
||||
}
|
||||
.todo-select {
|
||||
display: inline-block;
|
||||
min-width: 3em;
|
||||
text-decoration: none;
|
||||
}
|
||||
.todo-checkbox {
|
||||
margin-left: -1.9em;
|
||||
margin-right: 0.5em;
|
||||
display: inline-block;
|
||||
vertical-align: text-top;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.todo-checkbox input {
|
||||
position: absolute;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.todo-checkbox .todo-checkmark {
|
||||
width : 1.2em;
|
||||
height: 1.2em;
|
||||
position: relative;
|
||||
display : inline-block;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
color: white;
|
||||
border: solid 1px var(--color-default);
|
||||
border-radius: 100%;
|
||||
transition: background-color var(--transition-duration) ease-in;
|
||||
}
|
||||
.todo-checkbox input:checked ~ .todo-checkmark {
|
||||
background-color: var(--color-default);
|
||||
}
|
||||
.todo-checkbox .todo-checkmark:after {
|
||||
content: '×';
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
transition: opacity var(--transition-duration);
|
||||
opacity: 0;
|
||||
}
|
||||
.todo-checkbox input:checked ~ .todo-checkmark:after {
|
||||
opacity: 1.0;
|
||||
}
|
||||
|
||||
/* Color scheme */
|
||||
.prior-A .todo-priority {
|
||||
color: var(--color-A);
|
||||
}
|
||||
.prior-A .todo-checkbox .todo-checkmark {
|
||||
border-color: var(--color-A);
|
||||
color: black;
|
||||
}
|
||||
.prior-A .todo-checkbox input:checked ~ .todo-checkmark {
|
||||
background-color: var(--color-A);
|
||||
}
|
||||
|
||||
.prior-B .todo-priority {
|
||||
color: var(--color-B);
|
||||
}
|
||||
.prior-B .todo-checkbox .todo-checkmark {
|
||||
border-color: var(--color-B);
|
||||
}
|
||||
.prior-B .todo-checkbox input:checked ~ .todo-checkmark {
|
||||
background-color: var(--color-B);
|
||||
}
|
||||
|
||||
.prior-C .todo-priority {
|
||||
color: var(--color-C);
|
||||
}
|
||||
.prior-C .todo-checkbox .todo-checkmark {
|
||||
border-color: var(--color-C);
|
||||
}
|
||||
.prior-C .todo-checkbox input:checked ~ .todo-checkmark {
|
||||
background-color: var(--color-C);
|
||||
}
|
||||
|
||||
.prior-D .todo-priority {
|
||||
color: var(--color-D);
|
||||
}
|
||||
.prior-D .todo-checkbox .todo-checkmark {
|
||||
border-color: var(--color-D);
|
||||
}
|
||||
.prior-D .todo-checkbox input:checked ~ .todo-checkmark {
|
||||
background-color: var(--color-D);
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
document.addEventListener('joplin-noteDidUpdate', makeTodoViewActionable );
|
||||
|
||||
if (/WebKit/i.test(navigator.userAgent)) { // sniff
|
||||
var _timer_todotxt = setInterval(function() {
|
||||
if (/loaded|complete/.test(document.readyState)) {
|
||||
makeTodoViewActionable()
|
||||
}
|
||||
}, 10);
|
||||
}
|
||||
|
||||
function makeTodoViewActionable() {
|
||||
if (_timer_todotxt) clearInterval(_timer_todotxt);
|
||||
|
||||
const todoTxts = document.getElementsByClassName('todotxt');
|
||||
for (var i=0; i<todoTxts.length; i++){
|
||||
const todoTxt = todoTxts[i];
|
||||
const todos = todoTxt.getElementsByClassName('todo');
|
||||
for (var j=0; j<todos.length; j++){
|
||||
const todo = todos[j];
|
||||
const lineIdx = todo.getAttribute("data-lineIdx");
|
||||
|
||||
const checkbox = todo.getElementsByClassName('todo-checkbox')[0].getElementsByTagName('input')[0];
|
||||
const priority = todo.getElementsByClassName('todo-priority')[0].getElementsByTagName('select')[0];
|
||||
const selectButton = todo.getElementsByClassName('todo-select')[0];
|
||||
|
||||
checkbox.onclick = function (){
|
||||
setTimeout(()=> {webviewApi.postMessage('todoTxtMd', `toggleStatus:${lineIdx}`)}, 170);
|
||||
}
|
||||
priority.onchange = function(option) {
|
||||
var value = option.target.value;
|
||||
webviewApi.postMessage('todoTxtMd', `changePriority:${lineIdx}:${value}`);
|
||||
}
|
||||
selectButton.onclick = function () {
|
||||
webviewApi.postMessage('todoTxtMd', `selectLine:${lineIdx}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,17 @@
|
||||
const initPlugin = joplin => {
|
||||
|
||||
joplin.plugins.register({
|
||||
onStart: async function() {
|
||||
await joplin.contentScripts.register(
|
||||
'markdownItPlugin',
|
||||
'abc_music_sheet',
|
||||
'./markdownItPlugin.js'
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
//!function(t){var e={};function n(o){if(e[o])return e[o].exports;var r=e[o]={i:o,l:!1,exports:{}};return t[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=t,n.c=e,n.d=function(t,e,o){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:o})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var r in t)n.d(o,r,function(e){return t[e]}.bind(null,r));return o},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=0)}([function(t,e,n){"use strict";var o=this&&this.__awaiter||function(t,e,n,o){return new(n||(n=Promise))((function(r,i){function u(t){try{c(o.next(t))}catch(t){i(t)}}function l(t){try{c(o.throw(t))}catch(t){i(t)}}function c(t){var e;t.done?r(t.value):(e=t.value,e instanceof n?e:new n((function(t){t(e)}))).then(u,l)}c((o=o.apply(t,e||[])).next())}))};Object.defineProperty(e,"__esModule",{value:!0});const r=n(1),i=n(2);r.default.plugins.register({onStart:function(){return o(this,void 0,void 0,(function*(){yield r.default.contentScripts.register(i.ContentScriptType.MarkdownItPlugin,"abc_music_sheet","./markdownItPlugin.js"),setInterval(()=>{console.log("AAAAAAAAAAAAAAA")},1e3)}))}})},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.default=joplin},function(t,e,n){"use strict";var o;Object.defineProperty(e,"__esModule",{value:!0}),e.ContentScriptType=e.SettingStorage=e.AppType=e.SettingItemType=e.ToolbarButtonLocation=e.isContextMenuItemLocation=e.MenuItemLocation=e.ImportModuleOutputFormat=e.FileSystemItem=void 0,function(t){t.File="file",t.Directory="directory"}(e.FileSystemItem||(e.FileSystemItem={})),function(t){t.Markdown="md",t.Html="html"}(e.ImportModuleOutputFormat||(e.ImportModuleOutputFormat={})),function(t){t.File="file",t.Edit="edit",t.View="view",t.Note="note",t.Tools="tools",t.Help="help",t.Context="context",t.NoteListContextMenu="noteListContextMenu",t.EditorContextMenu="editorContextMenu",t.FolderContextMenu="folderContextMenu",t.TagContextMenu="tagContextMenu"}(o=e.MenuItemLocation||(e.MenuItemLocation={})),e.isContextMenuItemLocation=function(t){return[o.Context,o.NoteListContextMenu,o.EditorContextMenu,o.FolderContextMenu,o.TagContextMenu].includes(t)},function(t){t.NoteToolbar="noteToolbar",t.EditorToolbar="editorToolbar"}(e.ToolbarButtonLocation||(e.ToolbarButtonLocation={})),function(t){t[t.Int=1]="Int",t[t.String=2]="String",t[t.Bool=3]="Bool",t[t.Array=4]="Array",t[t.Object=5]="Object",t[t.Button=6]="Button"}(e.SettingItemType||(e.SettingItemType={})),function(t){t.Desktop="desktop",t.Mobile="mobile",t.Cli="cli"}(e.AppType||(e.AppType={})),function(t){t[t.Database=1]="Database",t[t.File=2]="File"}(e.SettingStorage||(e.SettingStorage={})),function(t){t.MarkdownItPlugin="markdownItPlugin",t.CodeMirrorPlugin="codeMirrorPlugin"}(e.ContentScriptType||(e.ContentScriptType={}))}]);
|
||||
|
||||
}
|
||||
|
||||
module.exports = { initPlugin };
|
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"manifest_version": 1,
|
||||
"id": "org.joplinapp.plugins.AbcSheetMusic",
|
||||
"app_min_version": "2.2",
|
||||
"version": "1.0.2",
|
||||
"name": "ABC Sheet Music Plugin",
|
||||
"description": "Turns ABC text notation into sheet music",
|
||||
"author": "Laurent Cozic",
|
||||
"homepage_url": "https://github.com/joplin/plugin-abc-sheet-music",
|
||||
"repository_url": "https://github.com/joplin/plugin-abc-sheet-music",
|
||||
"keywords": [
|
||||
"sheet music",
|
||||
"abc",
|
||||
"notation"
|
||||
]
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,14 @@
|
||||
const initPlugin = joplin => {
|
||||
|
||||
joplin.plugins.register({
|
||||
onStart: async function() {
|
||||
// eslint-disable-next-line no-console
|
||||
console.info('RUNNING AS PLUGIN 1: ', await joplin.plugins.id()); // await joplin.plugins.id());
|
||||
// const folder = await joplin.data.post(['folders'], null, { title: "my plugin folder" });
|
||||
// await joplin.data.post(['notes'], null, { parent_id: folder.id, title: "testing plugin!" });
|
||||
},
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
module.exports = { initPlugin };
|
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"id": "org.joplinapp.plugins.Simple",
|
||||
"manifest_version": 1,
|
||||
"app_min_version": "1.4",
|
||||
"name": "Joplin Simple Plugin",
|
||||
"version": "1.0.0",
|
||||
"description": "To test loading and running a plugin",
|
||||
"homepage_url": "https://joplinapp.org",
|
||||
"permissions": [
|
||||
"model"
|
||||
]
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
const initPlugin = joplin => {
|
||||
|
||||
joplin.plugins.register({
|
||||
onStart: async function() {
|
||||
// eslint-disable-next-line no-console
|
||||
console.info('RUNNING AS PLUGIN 2: ', await joplin.plugins.id());
|
||||
// const folder = await joplin.data.post(['folders'], null, { title: "my plugin folder" });
|
||||
// await joplin.data.post(['notes'], null, { parent_id: folder.id, title: "testing plugin!" });
|
||||
},
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
module.exports = { initPlugin };
|
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"id": "org.joplinapp.plugins.Simple2",
|
||||
"manifest_version": 1,
|
||||
"app_min_version": "1.4",
|
||||
"name": "Joplin Simple Plugin",
|
||||
"version": "1.0.0",
|
||||
"description": "To test loading and running a plugin",
|
||||
"homepage_url": "https://joplinapp.org",
|
||||
"permissions": [
|
||||
"model"
|
||||
]
|
||||
}
|
@@ -85,6 +85,7 @@ const SyncTargetWebDAV = require('@joplin/lib/SyncTargetWebDAV.js');
|
||||
const SyncTargetDropbox = require('@joplin/lib/SyncTargetDropbox.js');
|
||||
const SyncTargetAmazonS3 = require('@joplin/lib/SyncTargetAmazonS3.js');
|
||||
import BiometricPopup from './components/biometrics/BiometricPopup';
|
||||
import PluginService from '@joplin/lib/services/plugins/PluginService';
|
||||
|
||||
SyncTargetRegistry.addClass(SyncTargetNone);
|
||||
SyncTargetRegistry.addClass(SyncTargetOneDrive);
|
||||
@@ -120,6 +121,7 @@ import { ReactNode } from 'react';
|
||||
import userFetcher, { initializeUserFetcher } from '@joplin/lib/utils/userFetcher';
|
||||
import { parseShareCache } from '@joplin/lib/services/share/reducer';
|
||||
import autodetectTheme, { onSystemColorSchemeChange } from './utils/autodetectTheme';
|
||||
import PluginRunner from './services/plugins/PluginRunner';
|
||||
|
||||
type SideMenuPosition = 'left' | 'right';
|
||||
|
||||
@@ -438,6 +440,97 @@ const initializeTempDir = async () => {
|
||||
return tempDir;
|
||||
};
|
||||
|
||||
const simplePlugin1 = require('./plugins/org.joplinapp.plugins.Simple/index.js');
|
||||
const simplePluginManifest1 = `{
|
||||
"id": "org.joplinapp.plugins.Simple",
|
||||
"manifest_version": 1,
|
||||
"app_min_version": "1.4",
|
||||
"name": "Joplin Simple Plugin",
|
||||
"version": "1.0.0",
|
||||
"description": "To test loading and running a plugin",
|
||||
"homepage_url": "https://joplinapp.org",
|
||||
"permissions": [
|
||||
"model"
|
||||
]
|
||||
}`;
|
||||
|
||||
const simplePlugin2 = require('./plugins/org.joplinapp.plugins.Simple2/index.js');
|
||||
const simplePluginManifest2 = `{
|
||||
"id": "org.joplinapp.plugins.Simple2",
|
||||
"manifest_version": 1,
|
||||
"app_min_version": "1.4",
|
||||
"name": "Joplin Simple Plugin",
|
||||
"version": "1.0.0",
|
||||
"description": "To test loading and running a plugin",
|
||||
"homepage_url": "https://joplinapp.org",
|
||||
"permissions": [
|
||||
"model"
|
||||
]
|
||||
}`;
|
||||
|
||||
// const abcPlugin = require('./plugins/org.joplinapp.plugins.AbcSheetMusic/index.js');
|
||||
// const abcPluginManifest = `{
|
||||
// "manifest_version": 1,
|
||||
// "id": "org.joplinapp.plugins.AbcSheetMusic",
|
||||
// "app_min_version": "2.2",
|
||||
// "version": "1.0.2",
|
||||
// "name": "ABC Sheet Music Plugin",
|
||||
// "description": "Turns ABC text notation into sheet music",
|
||||
// "author": "Laurent Cozic",
|
||||
// "homepage_url": "https://github.com/joplin/plugin-abc-sheet-music",
|
||||
// "repository_url": "https://github.com/joplin/plugin-abc-sheet-music",
|
||||
// "keywords": [
|
||||
// "sheet music",
|
||||
// "abc",
|
||||
// "notation"
|
||||
// ]
|
||||
// }`;
|
||||
|
||||
// const abcPluginContentScript = require('./plugins/org.joplinapp.plugins.AbcSheetMusic/markdownItPlugin.js');
|
||||
|
||||
const metisPlugin = require('./plugins/com.hieuthi.joplin.metis/index.js');
|
||||
const metisManifest = `{
|
||||
"manifest_version": 1,
|
||||
"id": "com.hieuthi.joplin.metis",
|
||||
"app_min_version": "2.2",
|
||||
"version": "0.1.5",
|
||||
"name": "Metis",
|
||||
"description": "A Simple Task Manager Plugin for Joplin based on Todo.txt Specification",
|
||||
"author": "Hieu-Thi Luong",
|
||||
"homepage_url": "https://github.com/hieuthi/joplin-plugin-metis",
|
||||
"repository_url": "https://github.com/hieuthi/joplin-plugin-metis",
|
||||
"keywords": ["joplin-plugin","todo","todotxt","task management"]
|
||||
}`;
|
||||
const metisContentScript = require('./plugins/com.hieuthi.joplin.metis/todoTxtMdRule.js');
|
||||
|
||||
const initPluginService = async () => {
|
||||
const service = PluginService.instance();
|
||||
const runner = new PluginRunner();
|
||||
service.initialize(
|
||||
'2.12.1',
|
||||
{
|
||||
joplin: {},
|
||||
},
|
||||
runner,
|
||||
{
|
||||
dispatch: () => {},
|
||||
getState: () => {},
|
||||
}
|
||||
);
|
||||
|
||||
const plugin1 = await PluginService.instance().loadPluginFromModule({ main: simplePlugin1 }, simplePluginManifest1);
|
||||
await PluginService.instance().runPlugin(plugin1);
|
||||
|
||||
const plugin2 = await PluginService.instance().loadPluginFromModule({ main: simplePlugin2 }, simplePluginManifest2);
|
||||
await PluginService.instance().runPlugin(plugin2);
|
||||
|
||||
// const plugin3 = await PluginService.instance().loadPluginFromModule({ main: abcPlugin, contentScripts: { ['markdownItPlugin.js']: abcPluginContentScript } }, abcPluginManifest);
|
||||
// await PluginService.instance().runPlugin(plugin3);
|
||||
|
||||
const plugin4 = await PluginService.instance().loadPluginFromModule({ main: metisPlugin, contentScripts: { ['todoTxtMdView.js']: metisContentScript } }, metisManifest);
|
||||
await PluginService.instance().runPlugin(plugin4);
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied
|
||||
async function initialize(dispatch: Function) {
|
||||
shimInit();
|
||||
@@ -705,6 +798,8 @@ async function initialize(dispatch: Function) {
|
||||
// and it cannot collect anything when the app is not active.
|
||||
RevisionService.instance().runInBackground(1000 * 30);
|
||||
|
||||
await initPluginService();
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Keep this below to test react-native-rsa-native
|
||||
// ----------------------------------------------------------------------------
|
||||
|
15
packages/app-mobile/services/plugins/PluginRunner.ts
Normal file
15
packages/app-mobile/services/plugins/PluginRunner.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import Global from '@joplin/lib/services/plugins/api/Global';
|
||||
import BasePluginRunner from '@joplin/lib/services/plugins/BasePluginRunner';
|
||||
import Plugin from '@joplin/lib/services/plugins/Plugin';
|
||||
import Logger from '@joplin/utils/Logger';
|
||||
|
||||
const logger = Logger.create('PluginRunner');
|
||||
|
||||
export default class PluginRunner extends BasePluginRunner {
|
||||
|
||||
public async run(plugin: Plugin, sandbox: Global): Promise<void> {
|
||||
logger.info(`Run plugin: ${plugin.id}`);
|
||||
plugin.module.main.initPlugin(sandbox.joplin);
|
||||
}
|
||||
|
||||
}
|
@@ -256,12 +256,8 @@ export default class FsDriverRN extends FsDriverBase {
|
||||
return output ? output : null;
|
||||
}
|
||||
|
||||
public resolve(path: string) {
|
||||
throw new Error(`Not implemented: resolve(): ${path}`);
|
||||
}
|
||||
|
||||
public resolveRelativePathWithinDir(_baseDir: string, relativePath: string) {
|
||||
throw new Error(`Not implemented: resolveRelativePathWithinDir(): ${relativePath}`);
|
||||
public resolve(...pathSegments: string[]) {
|
||||
return resolve(...pathSegments);
|
||||
}
|
||||
|
||||
public async md5File(path: string): Promise<string> {
|
||||
|
21
packages/app-mobile/utils/markupLanguageUtils.ts
Normal file
21
packages/app-mobile/utils/markupLanguageUtils.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { MarkupLanguageUtils as BaseMarkupLanguageUtils } from '@joplin/lib/markupLanguageUtils';
|
||||
import { PluginStates } from '@joplin/lib/services/plugins/reducer';
|
||||
import { contentScriptsToRendererRules } from '@joplin/lib/services/plugins/utils/loadContentScripts';
|
||||
import { Options } from '@joplin/renderer/MarkupToHtml';
|
||||
|
||||
class MarkupLanguageUtils extends BaseMarkupLanguageUtils {
|
||||
|
||||
public newMarkupToHtml(plugins: PluginStates = null, options: Options = null) {
|
||||
plugins = plugins || {};
|
||||
|
||||
return super.newMarkupToHtml(null, {
|
||||
extraRendererRules: contentScriptsToRendererRules(plugins),
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const markupLanguageUtils = new MarkupLanguageUtils();
|
||||
|
||||
export default markupLanguageUtils;
|
@@ -158,6 +158,20 @@ export default class FsDriverBase {
|
||||
};
|
||||
}
|
||||
|
||||
public resolve(..._pathSegments: string[]): string {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
// Resolves the provided relative path to an absolute path within baseDir. The function
|
||||
// also checks that the absolute path is within baseDir, to avoid security issues.
|
||||
// It is expected that baseDir is a safe path (not user-provided).
|
||||
public resolveRelativePathWithinDir(baseDir: string, relativePath: string) {
|
||||
const resolvedBaseDir = this.resolve(baseDir);
|
||||
const resolvedPath = this.resolve(baseDir, relativePath);
|
||||
if (resolvedPath.indexOf(resolvedBaseDir) !== 0) throw new Error(`Resolved path for relative path "${relativePath}" is not within base directory "${baseDir}" (Was resolved to ${resolvedPath})`);
|
||||
return resolvedPath;
|
||||
}
|
||||
|
||||
public async tarExtract(_options: any) {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
@@ -186,18 +186,8 @@ export default class FsDriverNode extends FsDriverBase {
|
||||
throw new Error(`Unsupported encoding: ${encoding}`);
|
||||
}
|
||||
|
||||
public resolve(path: string) {
|
||||
return require('path').resolve(path);
|
||||
}
|
||||
|
||||
// Resolves the provided relative path to an absolute path within baseDir. The function
|
||||
// also checks that the absolute path is within baseDir, to avoid security issues.
|
||||
// It is expected that baseDir is a safe path (not user-provided).
|
||||
public resolveRelativePathWithinDir(baseDir: string, relativePath: string) {
|
||||
const resolvedBaseDir = nodeResolve(baseDir);
|
||||
const resolvedPath = nodeResolve(baseDir, relativePath);
|
||||
if (resolvedPath.indexOf(resolvedBaseDir) !== 0) throw new Error(`Resolved path for relative path "${relativePath}" is not within base directory "${baseDir}" (Was resolved to ${resolvedPath})`);
|
||||
return resolvedPath;
|
||||
public resolve(...pathSegments: string[]) {
|
||||
return nodeResolve(...pathSegments);
|
||||
}
|
||||
|
||||
public async md5File(path: string): Promise<string> {
|
||||
|
@@ -4,6 +4,7 @@ import shim from '../../shim';
|
||||
import { ViewHandle } from './utils/createViewHandle';
|
||||
import { ContentScriptType } from './api/types';
|
||||
import Logger from '@joplin/utils/Logger';
|
||||
import Joplin from './api/Joplin';
|
||||
const EventEmitter = require('events');
|
||||
|
||||
const logger = Logger.create('Plugin');
|
||||
@@ -15,12 +16,20 @@ interface ViewControllers {
|
||||
export interface ContentScript {
|
||||
id: string;
|
||||
path: string;
|
||||
module?: any;
|
||||
}
|
||||
|
||||
interface ContentScripts {
|
||||
[type: string]: ContentScript[];
|
||||
}
|
||||
|
||||
export interface Module {
|
||||
main: {
|
||||
initPlugin: (joplin: Joplin)=> void;
|
||||
};
|
||||
contentScripts?: Record<string, any>;
|
||||
}
|
||||
|
||||
export default class Plugin {
|
||||
|
||||
private baseDir_: string;
|
||||
@@ -38,14 +47,16 @@ export default class Plugin {
|
||||
private contentScriptMessageListeners_: Record<string, Function> = {};
|
||||
private dataDir_: string;
|
||||
private dataDirCreated_ = false;
|
||||
private module_: Module|null = null;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied
|
||||
public constructor(baseDir: string, manifest: PluginManifest, scriptText: string, dispatch: Function, dataDir: string) {
|
||||
this.baseDir_ = shim.fsDriver().resolve(baseDir);
|
||||
public constructor(baseDir: string, manifest: PluginManifest, scriptText: string, dispatch: Function, dataDir: string, module: Module|null = null) {
|
||||
this.baseDir_ = baseDir ? shim.fsDriver().resolve(baseDir) : '';
|
||||
this.manifest_ = manifest;
|
||||
this.scriptText_ = scriptText;
|
||||
this.dispatch_ = dispatch;
|
||||
this.dataDir_ = dataDir;
|
||||
this.module_ = module;
|
||||
this.eventEmitter_ = new EventEmitter();
|
||||
}
|
||||
|
||||
@@ -73,6 +84,10 @@ export default class Plugin {
|
||||
return this.baseDir_;
|
||||
}
|
||||
|
||||
public get module(): Module|null {
|
||||
return this.module_;
|
||||
}
|
||||
|
||||
public async dataDir(): Promise<string> {
|
||||
if (this.dataDirCreated_) return this.dataDir_;
|
||||
|
||||
@@ -105,13 +120,25 @@ export default class Plugin {
|
||||
public async registerContentScript(type: ContentScriptType, id: string, path: string) {
|
||||
if (!this.contentScripts_[type]) this.contentScripts_[type] = [];
|
||||
|
||||
const absolutePath = shim.fsDriver().resolveRelativePathWithinDir(this.baseDir, path);
|
||||
let absolutePath = '';
|
||||
let scriptModule: any = null;
|
||||
|
||||
if (!(await shim.fsDriver().exists(absolutePath))) throw new Error(`Could not find content script at path ${absolutePath}`);
|
||||
if (this.module) {
|
||||
const normalizePath = (p: string) => {
|
||||
if (p.startsWith('./')) return p.substring(2);
|
||||
return p;
|
||||
};
|
||||
|
||||
this.contentScripts_[type].push({ id, path: absolutePath });
|
||||
const moduleKey = normalizePath(path);
|
||||
scriptModule = this.module.contentScripts[moduleKey];
|
||||
logger.debug(`"${this.id}": Registered content script: ${type}: ${id}: ${moduleKey}`);
|
||||
} else {
|
||||
absolutePath = shim.fsDriver().resolveRelativePathWithinDir(this.baseDir, path);
|
||||
if (!(await shim.fsDriver().exists(absolutePath))) throw new Error(`Could not find content script at path ${absolutePath}`);
|
||||
logger.debug(`"${this.id}": Registered content script: ${type}: ${id}: ${absolutePath}`);
|
||||
}
|
||||
|
||||
logger.debug(`"${this.id}": Registered content script: ${type}: ${id}: ${absolutePath}`);
|
||||
this.contentScripts_[type].push({ id, path: absolutePath, module: scriptModule });
|
||||
|
||||
this.dispatch_({
|
||||
type: 'PLUGIN_CONTENT_SCRIPTS_ADD',
|
||||
@@ -120,6 +147,7 @@ export default class Plugin {
|
||||
type: type,
|
||||
id: id,
|
||||
path: absolutePath,
|
||||
module: scriptModule,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import Plugin from './Plugin';
|
||||
import Plugin, { Module } from './Plugin';
|
||||
import manifestFromObject from './utils/manifestFromObject';
|
||||
import Global from './api/Global';
|
||||
import BasePluginRunner from './BasePluginRunner';
|
||||
@@ -28,6 +28,10 @@ export interface Plugins {
|
||||
[key: string]: Plugin;
|
||||
}
|
||||
|
||||
export interface PluginModule {
|
||||
|
||||
}
|
||||
|
||||
export interface SettingAndValue {
|
||||
[settingName: string]: string;
|
||||
}
|
||||
@@ -283,7 +287,17 @@ export default class PluginService extends BaseService {
|
||||
}
|
||||
}
|
||||
|
||||
private async loadPlugin(baseDir: string, manifestText: string, scriptText: string, pluginIdIfNotSpecified: string): Promise<Plugin> {
|
||||
public async loadPluginFromModule(module: Module, manifestText: string): Promise<Plugin> {
|
||||
return this.loadPlugin(
|
||||
'',
|
||||
manifestText,
|
||||
'',
|
||||
'',
|
||||
module
|
||||
);
|
||||
}
|
||||
|
||||
private async loadPlugin(baseDir: string, manifestText: string, scriptText: string, pluginIdIfNotSpecified: string, module: Module|null = null): Promise<Plugin> {
|
||||
baseDir = rtrimSlashes(baseDir);
|
||||
|
||||
const manifestObj = JSON.parse(manifestText);
|
||||
@@ -318,7 +332,7 @@ export default class PluginService extends BaseService {
|
||||
|
||||
const dataDir = `${Setting.value('pluginDataDir')}/${manifest.id}`;
|
||||
|
||||
const plugin = new Plugin(baseDir, manifest, scriptText, (action: any) => this.store_.dispatch(action), dataDir);
|
||||
const plugin = new Plugin(baseDir, manifest, scriptText, (action: any) => this.store_.dispatch(action), dataDir, module);
|
||||
|
||||
for (const notice of deprecationNotices) {
|
||||
plugin.deprecationNotice(notice.goneInVersion, notice.message, notice.isError);
|
||||
|
@@ -71,6 +71,10 @@ export default class JoplinPlugins {
|
||||
return this.plugin.dataDir();
|
||||
}
|
||||
|
||||
public async id(): Promise<string> {
|
||||
return this.plugin.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the plugin installation directory. This can be used to access any
|
||||
* asset that was packaged with the plugin. This directory should be
|
||||
|
@@ -1,22 +1,20 @@
|
||||
/* eslint-disable multiline-comment-style */
|
||||
|
||||
import Plugin from '../Plugin';
|
||||
import * as fs from 'fs-extra';
|
||||
|
||||
export interface Implementation {
|
||||
injectCustomStyles(elementId: string, cssFilePath: string): Promise<void>;
|
||||
loadNoteCssFile(filePath: string): Promise<void>;
|
||||
}
|
||||
|
||||
export default class JoplinWindow {
|
||||
|
||||
private plugin_: Plugin;
|
||||
private store_: any;
|
||||
private implementation_: Implementation;
|
||||
|
||||
public constructor(implementation: Implementation, plugin: Plugin, store: any) {
|
||||
public constructor(implementation: Implementation, plugin: Plugin, _store: any) {
|
||||
this.implementation_ = implementation;
|
||||
this.plugin_ = plugin;
|
||||
this.store_ = store;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,12 +34,7 @@ export default class JoplinWindow {
|
||||
* for an example.
|
||||
*/
|
||||
public async loadNoteCssFile(filePath: string) {
|
||||
const cssString = await fs.readFile(filePath, 'utf8');
|
||||
|
||||
this.store_.dispatch({
|
||||
type: 'CUSTOM_CSS_APPEND',
|
||||
css: cssString,
|
||||
});
|
||||
await this.implementation_.loadNoteCssFile(filePath);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -17,6 +17,7 @@ interface PluginViewStates {
|
||||
interface PluginContentScriptState {
|
||||
id: string;
|
||||
path: string;
|
||||
module?: any;
|
||||
}
|
||||
|
||||
interface PluginContentScriptStates {
|
||||
@@ -170,6 +171,7 @@ const reducer = (draftRoot: Draft<any>, action: any) => {
|
||||
draft.plugins[action.pluginId].contentScripts[type].push({
|
||||
id: action.contentScript.id,
|
||||
path: action.contentScript.path,
|
||||
module: action.contentScript.module,
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
@@ -27,6 +27,7 @@ const { fileExtension, safeFileExtension, safeFilename, filename } = require('..
|
||||
const { fileUriToPath } = require('../../../urlUtils');
|
||||
const { MarkupToHtml } = require('@joplin/renderer');
|
||||
const { ErrorNotFound } = require('../utils/errors');
|
||||
const minify = require('html-minifier').minify;
|
||||
|
||||
const logger = Logger.create('routes/notes');
|
||||
|
||||
@@ -51,7 +52,6 @@ async function requestNoteToNote(requestNote: any) {
|
||||
if (requestNote.body_html) {
|
||||
if (requestNote.convert_to === 'html') {
|
||||
const style = await buildNoteStyleSheet(requestNote.stylesheets);
|
||||
const minify = require('html-minifier').minify;
|
||||
|
||||
const minifyOptions = {
|
||||
// Remove all spaces and, especially, newlines from tag attributes, as that would
|
||||
|
24
yarn.lock
24
yarn.lock
@@ -4559,6 +4559,8 @@ __metadata:
|
||||
execa: 4.1.0
|
||||
fs-extra: 11.1.1
|
||||
gulp: 4.0.2
|
||||
http-browserify: 1.7.0
|
||||
https-browserify: 1.0.0
|
||||
jest: 29.5.0
|
||||
jest-environment-jsdom: 29.5.0
|
||||
jetifier: 2.0.0
|
||||
@@ -4569,6 +4571,7 @@ __metadata:
|
||||
md5-file: 5.0.0
|
||||
metro-react-native-babel-preset: 0.73.9
|
||||
nodemon: 2.0.22
|
||||
os-browserify: 0.3.0
|
||||
path-browserify: 1.0.1
|
||||
prop-types: 15.8.1
|
||||
punycode: 2.3.0
|
||||
@@ -8824,6 +8827,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"Base64@npm:~0.2.0":
|
||||
version: 0.2.1
|
||||
resolution: "Base64@npm:0.2.1"
|
||||
checksum: 7c47e801b52cb9c963ee2cfb9284fbef8a6a34d3bbc5f7503b186ab5fb3a77e3f4a321f14ef20a6b2270d6cc3c89a2a349a538c4690abd2077bbe7caef10272d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"JSONStream@npm:^1.0.3, JSONStream@npm:^1.0.4, JSONStream@npm:^1.3.4":
|
||||
version: 1.3.5
|
||||
resolution: "JSONStream@npm:1.3.5"
|
||||
@@ -18634,6 +18644,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"http-browserify@npm:1.7.0":
|
||||
version: 1.7.0
|
||||
resolution: "http-browserify@npm:1.7.0"
|
||||
dependencies:
|
||||
Base64: ~0.2.0
|
||||
inherits: ~2.0.1
|
||||
checksum: 7891aee4a55a0182bcdd8cd59f1d154a8f9b284e006bced7fbf5e9ae2e6762ec6c7ade7742952c509503f23b2b9b94c791a14a77fc85881aa2c51b3b010d029b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"http-cache-semantics@npm:^3.8.1":
|
||||
version: 3.8.1
|
||||
resolution: "http-cache-semantics@npm:3.8.1"
|
||||
@@ -18781,7 +18801,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"https-browserify@npm:^1.0.0":
|
||||
"https-browserify@npm:1.0.0, https-browserify@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "https-browserify@npm:1.0.0"
|
||||
checksum: 09b35353e42069fde2435760d13f8a3fb7dd9105e358270e2e225b8a94f811b461edd17cb57594e5f36ec1218f121c160ddceeec6e8be2d55e01dcbbbed8cbae
|
||||
@@ -25680,7 +25700,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"os-browserify@npm:~0.3.0":
|
||||
"os-browserify@npm:0.3.0, os-browserify@npm:~0.3.0":
|
||||
version: 0.3.0
|
||||
resolution: "os-browserify@npm:0.3.0"
|
||||
checksum: 16e37ba3c0e6a4c63443c7b55799ce4066d59104143cb637ecb9fce586d5da319cdca786ba1c867abbe3890d2cbf37953f2d51eea85e20dd6c4570d6c54bfebf
|
||||
|
Reference in New Issue
Block a user