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

Compare commits

...

7 Commits

Author SHA1 Message Date
Laurent Cozic
5eae378809 Merge branch 'dev' into dev_no_template 2021-08-06 10:49:28 +01:00
Abhinav Sharma
b0609319fd Doc: add mobile UI infographic to readme/mobile.md (#5252)
* Update mobile.md

Add mobile interface

* Update mobile.md

* Add joplin_mobile_ui.jpg

* Delete file

* Add JoplinMobileUI

* Delete file

* Add JoplinMobileUI

* Update mobile.md

* Add JoplinMobileUI.jpg

* Update mobile.md

* Delete Assets/JoplinMobileui.jpg

* Add JoplinMobileUI.jpg

* Update mobile.md

* Delete JoplinMobileUI.jpg
2021-08-05 18:18:27 -04:00
Laurent Cozic
fa9c08be06 Plugin Repo: Added plugin download links on README page 2021-08-05 17:32:00 +01:00
Laurent Cozic
b3ce5fbc48 Doc: Added debug info 2021-08-05 16:04:08 +01:00
Laurent Cozic
87298db0ec fix import 2021-08-05 16:01:46 +01:00
Nishant Mittal
13c6206624 Desktop: Add a banner asking users to install templates plugin (#5164) 2021-07-09 10:46:05 +01:00
Nishant Mittal
d13d5b4cc3 Desktop: Remove templates feature (#5115) 2021-06-25 17:49:36 +01:00
23 changed files with 159 additions and 232 deletions

View File

@@ -267,9 +267,6 @@ packages/app-desktop/gui/MainScreen/commands/renameTag.js.map
packages/app-desktop/gui/MainScreen/commands/search.d.ts
packages/app-desktop/gui/MainScreen/commands/search.js
packages/app-desktop/gui/MainScreen/commands/search.js.map
packages/app-desktop/gui/MainScreen/commands/selectTemplate.d.ts
packages/app-desktop/gui/MainScreen/commands/selectTemplate.js
packages/app-desktop/gui/MainScreen/commands/selectTemplate.js.map
packages/app-desktop/gui/MainScreen/commands/setTags.d.ts
packages/app-desktop/gui/MainScreen/commands/setTags.js
packages/app-desktop/gui/MainScreen/commands/setTags.js.map
@@ -1584,6 +1581,9 @@ packages/plugin-repo-cli/lib/types.js.map
packages/plugin-repo-cli/lib/updateReadme.d.ts
packages/plugin-repo-cli/lib/updateReadme.js
packages/plugin-repo-cli/lib/updateReadme.js.map
packages/plugin-repo-cli/lib/updateReadme.test.d.ts
packages/plugin-repo-cli/lib/updateReadme.test.js
packages/plugin-repo-cli/lib/updateReadme.test.js.map
packages/plugins/ToggleSidebars/api/index.d.ts
packages/plugins/ToggleSidebars/api/index.js
packages/plugins/ToggleSidebars/api/index.js.map

6
.gitignore vendored
View File

@@ -252,9 +252,6 @@ packages/app-desktop/gui/MainScreen/commands/renameTag.js.map
packages/app-desktop/gui/MainScreen/commands/search.d.ts
packages/app-desktop/gui/MainScreen/commands/search.js
packages/app-desktop/gui/MainScreen/commands/search.js.map
packages/app-desktop/gui/MainScreen/commands/selectTemplate.d.ts
packages/app-desktop/gui/MainScreen/commands/selectTemplate.js
packages/app-desktop/gui/MainScreen/commands/selectTemplate.js.map
packages/app-desktop/gui/MainScreen/commands/setTags.d.ts
packages/app-desktop/gui/MainScreen/commands/setTags.js
packages/app-desktop/gui/MainScreen/commands/setTags.js.map
@@ -1569,6 +1566,9 @@ packages/plugin-repo-cli/lib/types.js.map
packages/plugin-repo-cli/lib/updateReadme.d.ts
packages/plugin-repo-cli/lib/updateReadme.js
packages/plugin-repo-cli/lib/updateReadme.js.map
packages/plugin-repo-cli/lib/updateReadme.test.d.ts
packages/plugin-repo-cli/lib/updateReadme.test.js
packages/plugin-repo-cli/lib/updateReadme.test.js.map
packages/plugins/ToggleSidebars/api/index.d.ts
packages/plugins/ToggleSidebars/api/index.js
packages/plugins/ToggleSidebars/api/index.js.map

View File

@@ -165,7 +165,6 @@ The Web Clipper is a browser extension that allows you to save web pages and scr
- Supports multiple languages.
- External editor support - open notes in your favorite external editor with one click in Joplin.
- Extensible functionality through plugin and data APIs.
- Template support with data variables for auto creation of time & dates.
- Custom CSS support for customisation of both the rendered markdown and overall user interface.
- Customisable layout allows toggling, movement and sizing of various elements.
- Keyboard shortcuts are editable and allow binding of most Joplin commands with export/import functionality.
@@ -376,29 +375,6 @@ The whole UI can be customized by placing a custom editor style file in the prof
Important: userstyle.css and userchrome.css are provided for your convenience, but they are advanced settings, and styles you define may break from one version to the next. If you want to use them, please know that it might require regular development work from you to keep them working. The Joplin team cannot make a commitment to keep the application HTML structure stable.
# Note templates
In the **desktop app**, templates can be used to create new notes or to insert into existing ones by adding a template file to the `templates` directory (File > Templates). For example creating the file `hours.md` in the `templates` directory with the contents:
```markdown
Date: {{date}}
Hours:
Details:
```
Templates can then be inserted from the menu (File->Templates).
The currently supported template variables are:
| Variable | Description | Example |
| --- | --- | --- |
| `{{date}}` | Today's date formatted based on the settings format | 2019-01-01 |
| `{{time}}` | Current time formatted based on the settings format | 13:00 |
| `{{datetime}}` | Current date and time formatted based on the settings format | 01/01/19 1:00 PM |
| `{{#custom_datetime}}` | Current date and/or time formatted based on a supplied string (using [moment.js](https://momentjs.com/) formatting) | `{{#custom_datetime}}M d{{/custom_datetime}}` |
| `{{bowm}}` | Date of the beginning of the week (when week starts on Monday) based on the settings format | |
| `{{bows}}` | Date of the beginning of the week (when week starts on Sunday) based on the settings format | |
# Plugins
The **desktop app** has the ability to extend beyond its standard functionality by the way of plugins. These plugins adhere to the Joplin plugin API and can be installed & configured within the application via the `Plugins` page in the Configuration screen. This menu allows the manual installation of the plugin using the single 'Joplin Plugin Archive' (*.jpl) file. Once the application is reloaded the plugins will appear within the plugins menu where they can be toggled on/off or removed entirely.

Binary file not shown.

After

Width:  |  Height:  |  Size: 723 KiB

View File

@@ -41,7 +41,6 @@ const Menu = bridge().Menu;
const PluginManager = require('@joplin/lib/services/PluginManager');
import RevisionService from '@joplin/lib/services/RevisionService';
import MigrationService from '@joplin/lib/services/MigrationService';
const TemplateUtils = require('@joplin/lib/TemplateUtils');
import { loadCustomCss, injectCustomStyles } from '@joplin/lib/CssUtils';
// import populateDatabase from '@joplin/lib/services/debug/populateDatabase';
@@ -62,7 +61,6 @@ const commands = [
require('./gui/MainScreen/commands/renameFolder'),
require('./gui/MainScreen/commands/renameTag'),
require('./gui/MainScreen/commands/search'),
require('./gui/MainScreen/commands/selectTemplate'),
require('./gui/MainScreen/commands/setTags'),
require('./gui/MainScreen/commands/showModalMessage'),
require('./gui/MainScreen/commands/showNoteContentProperties'),
@@ -538,6 +536,26 @@ class Application extends BaseApplication {
return cssString;
}
private async checkForLegacyTemplates() {
const templatesDir = `${Setting.value('profileDir')}/templates`;
if (await shim.fsDriver().exists(templatesDir)) {
try {
const files = await shim.fsDriver().readDirStats(templatesDir);
for (const file of files) {
if (file.path.endsWith('.md')) {
// There is atleast one template.
this.store().dispatch({
type: 'CONTAINS_LEGACY_TEMPLATES',
});
break;
}
}
} catch (error) {
reg.logger().error(`Failed to read templates directory: ${error}`);
}
}
}
private async initPluginService() {
const service = PluginService.instance();
@@ -617,8 +635,6 @@ class Application extends BaseApplication {
argv = await super.start(argv);
await fs.mkdirp(Setting.value('templateDir'), 0o755);
await this.applySettingsSideEffects();
if (Setting.value('sync.upgradeState') === Setting.SYNC_UPGRADE_STATE_MUST_DO) {
@@ -715,18 +731,13 @@ class Application extends BaseApplication {
css: cssString,
});
const templates = await TemplateUtils.loadTemplates(Setting.value('templateDir'));
this.store().dispatch({
type: 'TEMPLATE_UPDATE_ALL',
templates: templates,
});
this.store().dispatch({
type: 'NOTE_DEVTOOLS_SET',
value: Setting.value('flagOpenDevTools'),
});
await this.checkForLegacyTemplates();
// Note: Auto-update currently doesn't work in Linux: it downloads the update
// but then doesn't install it on exit.
if (shim.isWindows() || shim.isMac()) {

View File

@@ -14,8 +14,6 @@ const getLabel = (commandName: string): string => {
switch (commandName) {
case 'quit':
return _('Quit');
case 'insertTemplate':
return _('Insert template');
case 'zoomActualSize':
return _('Actual Size');
case 'gotoAnything':

View File

@@ -63,6 +63,7 @@ interface Props {
showMissingMasterKeyMessage: boolean;
showNeedUpgradingMasterKeyMessage: boolean;
showShouldReencryptMessage: boolean;
showInstallTemplatesPlugin: boolean;
focusedField: string;
themeId: number;
settingEditorCodeView: boolean;
@@ -70,6 +71,7 @@ interface Props {
startupPluginsLoaded: boolean;
shareInvitations: ShareInvitation[];
isSafeMode: boolean;
needApiAuth: boolean;
}
interface ShareFolderDialogOptions {
@@ -123,7 +125,6 @@ const commands = [
require('./commands/renameFolder'),
require('./commands/renameTag'),
require('./commands/search'),
require('./commands/selectTemplate'),
require('./commands/setTags'),
require('./commands/showModalMessage'),
require('./commands/showNoteContentProperties'),
@@ -551,6 +552,16 @@ class MainScreenComponent extends React.Component<Props, State> {
});
};
const onViewPluginScreen = () => {
this.props.dispatch({
type: 'NAV_GO',
routeName: 'Config',
props: {
defaultSection: 'plugins',
},
});
};
const onRestartAndUpgrade = async () => {
Setting.setValue('sync.upgradeState', Setting.SYNC_UPGRADE_STATE_MUST_DO);
await Setting.saveAll();
@@ -627,6 +638,12 @@ class MainScreenComponent extends React.Component<Props, State> {
_('Set the password'),
onViewEncryptionConfigScreen
);
} else if (this.props.showInstallTemplatesPlugin) {
msg = this.renderNotificationMessage(
'The template feature has been moved to a plugin called "Templates".',
'Install plugin',
onViewPluginScreen
);
}
return (
@@ -638,7 +655,7 @@ class MainScreenComponent extends React.Component<Props, State> {
messageBoxVisible(props: Props = null) {
if (!props) props = this.props;
return props.hasDisabledSyncItems || props.showMissingMasterKeyMessage || props.showNeedUpgradingMasterKeyMessage || props.showShouldReencryptMessage || props.hasDisabledEncryptionItems || this.props.shouldUpgradeSyncTarget || props.isSafeMode || this.showShareInvitationNotification(props);
return props.hasDisabledSyncItems || props.showMissingMasterKeyMessage || props.showNeedUpgradingMasterKeyMessage || props.showShouldReencryptMessage || props.hasDisabledEncryptionItems || this.props.shouldUpgradeSyncTarget || props.isSafeMode || this.showShareInvitationNotification(props) || this.props.needApiAuth || this.props.showInstallTemplatesPlugin;
}
registerCommands() {
@@ -855,7 +872,6 @@ const mapStateToProps = (state: AppState) => {
selectedNoteId: state.selectedNoteIds.length === 1 ? state.selectedNoteIds[0] : null,
pluginsLegacy: state.pluginsLegacy,
plugins: state.pluginService.plugins,
templates: state.templates,
customCss: state.customCss,
editorNoteStatuses: state.editorNoteStatuses,
hasNotesBeingSaved: stateUtils.hasNotesBeingSaved(state),
@@ -865,6 +881,8 @@ const mapStateToProps = (state: AppState) => {
startupPluginsLoaded: state.startupPluginsLoaded,
shareInvitations: state.shareService.shareInvitations,
isSafeMode: state.settings.isSafeMode,
needApiAuth: state.needApiAuth,
showInstallTemplatesPlugin: state.hasLegacyTemplates && !state.pluginService.plugins['joplin.plugin.templates'],
};
};

View File

@@ -2,7 +2,6 @@ import { utils, CommandRuntime, CommandDeclaration, CommandContext } from '@jopl
import { _ } from '@joplin/lib/locale';
import Setting from '@joplin/lib/models/Setting';
import Note from '@joplin/lib/models/Note';
const TemplateUtils = require('@joplin/lib/TemplateUtils');
export const declaration: CommandDeclaration = {
name: 'newNote',
@@ -12,12 +11,10 @@ export const declaration: CommandDeclaration = {
export const runtime = (): CommandRuntime => {
return {
execute: async (_context: CommandContext, template: string = null, isTodo: boolean = false) => {
execute: async (_context: CommandContext, body: string = '', isTodo: boolean = false) => {
const folderId = Setting.value('activeFolderId');
if (!folderId) return;
const body = template ? TemplateUtils.render(template) : '';
const defaultValues = Note.previewFieldsWithDefaultValues({ includeTimestamps: false });
let newNote = Object.assign({}, defaultValues, {

View File

@@ -9,8 +9,8 @@ export const declaration: CommandDeclaration = {
export const runtime = (): CommandRuntime => {
return {
execute: async (_context: CommandContext, template: string = null) => {
return CommandService.instance().execute('newNote', template, true);
execute: async (_context: CommandContext, body: string = '') => {
return CommandService.instance().execute('newNote', body, true);
},
enabledCondition: 'oneFolderSelected && !inConflictFolder',
};

View File

@@ -1,33 +0,0 @@
import CommandService, { CommandRuntime, CommandDeclaration, CommandContext } from '@joplin/lib/services/CommandService';
import { _ } from '@joplin/lib/locale';
const TemplateUtils = require('@joplin/lib/TemplateUtils');
export const declaration: CommandDeclaration = {
name: 'selectTemplate',
};
export const runtime = (comp: any): CommandRuntime => {
return {
execute: async (_context: CommandContext, noteType: string) => {
comp.setState({
promptOptions: {
label: _('Template file:'),
inputType: 'dropdown',
value: comp.props.templates[0], // Need to start with some value
autocomplete: comp.props.templates,
onClose: async (answer: any) => {
if (answer) {
if (noteType === 'note' || noteType === 'todo') {
void CommandService.instance().execute('newNote', answer.value, noteType === 'todo');
} else {
void CommandService.instance().execute('insertText', TemplateUtils.render(answer.value));
}
}
comp.setState({ promptOptions: null });
},
},
});
},
};
};

View File

@@ -25,7 +25,6 @@ const packageInfo = require('../packageInfo.js');
const { clipboard } = require('electron');
const Menu = bridge().Menu;
const PluginManager = require('@joplin/lib/services/PluginManager');
const TemplateUtils = require('@joplin/lib/TemplateUtils');
const menuUtils = new MenuUtils(CommandService.instance());
@@ -301,7 +300,6 @@ function useMenu(props: Props) {
const importItems = [];
const exportItems = [];
const templateItems: any[] = [];
const ioService = InteropService.instance();
const ioModules = ioService.modules();
for (let i = 0; i < ioModules.length; i++) {
@@ -366,39 +364,6 @@ function useMenu(props: Props) {
const newSubFolderItem = menuItemDic.newSubFolder;
const printItem = menuItemDic.print;
templateItems.push({
label: _('Create note from template'),
click: () => {
void CommandService.instance().execute('selectTemplate', 'note');
},
}, {
label: _('Create to-do from template'),
click: () => {
void CommandService.instance().execute('selectTemplate', 'todo');
},
}, {
label: _('Insert template'),
accelerator: keymapService.getAccelerator('insertTemplate'),
click: () => {
void CommandService.instance().execute('selectTemplate');
},
}, {
label: _('Open template directory'),
click: () => {
void bridge().openItem(Setting.value('templateDir'));
},
}, {
label: _('Refresh templates'),
click: async () => {
const templates = await TemplateUtils.loadTemplates(Setting.value('templateDir'));
props.dispatch({
type: 'TEMPLATE_UPDATE_ALL',
templates: templates,
});
},
});
let toolsItems: any[] = [];
// we need this workaround, because on macOS the menu is different
@@ -493,13 +458,6 @@ function useMenu(props: Props) {
{
type: 'separator',
visible: shim.isMac() ? false : true,
}, {
label: _('Templates'),
visible: shim.isMac() ? false : true,
submenu: templateItems,
}, {
type: 'separator',
visible: shim.isMac() ? false : true,
}, {
label: _('Import'),
visible: shim.isMac() ? false : true,
@@ -555,11 +513,6 @@ function useMenu(props: Props) {
selector: 'performClose:',
}, {
type: 'separator',
}, {
label: _('Templates'),
submenu: templateItems,
}, {
type: 'separator',
}, {
label: _('Import'),
submenu: importItems,

View File

@@ -18,7 +18,7 @@ const { surroundKeywords, nextWhitespaceIndex, removeDiacritics } = require('@jo
const { mergeOverlappingIntervals } = require('@joplin/lib/ArrayUtils.js');
import markupLanguageUtils from '../utils/markupLanguageUtils';
import focusEditorIfEditorCommand from '@joplin/lib/services/commands/focusEditorIfEditorCommand';
import Logger from '../../lib/Logger';
import Logger from '@joplin/lib/Logger';
const logger = Logger.create('GotoAnything');

View File

@@ -677,7 +677,6 @@ export default class BaseApplication {
Setting.setConstant('env', initArgs.env);
Setting.setConstant('profileDir', profileDir);
Setting.setConstant('templateDir', `${profileDir}/templates`);
Setting.setConstant('resourceDirName', resourceDirName);
Setting.setConstant('resourceDir', resourceDir);
Setting.setConstant('tempDir', tempDir);

View File

@@ -1,79 +0,0 @@
const shim = require('./shim').default;
const time = require('./time').default;
const Mustache = require('mustache');
const TemplateUtils = {};
// Mustache escapes strings (including /) with the html code by default
// This isn't useful for markdown so it's disabled
Mustache.escape = text => {
return text;
};
function beginningOfWeek(index) {
// index: 0 for Sunday, 1 for Monday
const thisDate = new Date();
const day = thisDate.getDay(),
diff = day >= index ? day - index : 6 - day;
return new Date().setDate(thisDate.getDate() - diff);
}
TemplateUtils.render = function(input) {
// new template variables can be added here
// If there are too many, this should be moved to a new file
// view needs to be set in this function so that the formats reflect settings
const view = {
date: time.formatMsToLocal(new Date().getTime(), time.dateFormat()),
time: time.formatMsToLocal(new Date().getTime(), time.timeFormat()),
datetime: time.formatMsToLocal(new Date().getTime()),
custom_datetime: () => {
return (text, render) => {
return render(time.formatMsToLocal(new Date().getTime(), text));
};
},
bowm: time.formatMsToLocal(beginningOfWeek(1), time.dateFormat()),
bows: time.formatMsToLocal(beginningOfWeek(0), time.dateFormat()),
};
return Mustache.render(input, view);
};
TemplateUtils.loadTemplates = async function(filePath) {
const templates = [];
let files = [];
if (await shim.fsDriver().exists(filePath)) {
try {
files = await shim.fsDriver().readDirStats(filePath);
} catch (error) {
let msg = error.message ? error.message : '';
msg = `Could not read template names from ${filePath}\n${msg}`;
error.message = msg;
throw error;
}
// Make sure templates are always in the same order
// sensitivity ensures that the sort will ignore case
files.sort((a, b) => { return a.path.localeCompare(b.path, undefined, { sensitivity: 'accent' }); });
for (const file of files) {
if (file.path.endsWith('.md')) {
try {
const fileString = await shim.fsDriver().readFile(`${filePath}/${file.path}`, 'utf-8');
templates.push({ label: file.path, value: fileString });
} catch (error) {
let msg = error.message ? error.message : '';
msg = `Could not load template ${file.path}\n${msg}`;
error.message = msg;
throw error;
}
}
}
}
return templates;
};
module.exports = TemplateUtils;

View File

@@ -108,7 +108,6 @@ export interface Constants {
resourceDirName: string;
resourceDir: string;
profileDir: string;
templateDir: string;
tempDir: string;
pluginDataDir: string;
cacheDir: string;
@@ -190,7 +189,6 @@ class Setting extends BaseModel {
resourceDirName: '',
resourceDir: '',
profileDir: '',
templateDir: '',
tempDir: '',
pluginDataDir: '',
cacheDir: '',

View File

@@ -78,7 +78,7 @@ export interface State {
hasDisabledSyncItems: boolean;
hasDisabledEncryptionItems: boolean;
customCss: string;
templates: any[];
hasLegacyTemplates: boolean;
collapsedFolderIds: string[];
clipperServer: StateClipperServer;
decryptionWorker: StateDecryptionWorker;
@@ -132,7 +132,7 @@ export const defaultState: State = {
hasDisabledSyncItems: false,
hasDisabledEncryptionItems: false,
customCss: '',
templates: [],
hasLegacyTemplates: false,
collapsedFolderIds: [],
clipperServer: {
startState: 'idle',
@@ -1016,6 +1016,10 @@ const reducer = produce((draft: Draft<State> = defaultState, action: any) => {
}
break;
case 'CONTAINS_LEGACY_TEMPLATES':
draft.hasLegacyTemplates = true;
break;
case 'SYNC_STARTED':
draft.syncStarted = true;
break;
@@ -1120,10 +1124,6 @@ const reducer = produce((draft: Draft<State> = defaultState, action: any) => {
draft.customCss += action.css;
break;
case 'TEMPLATE_UPDATE_ALL':
draft.templates = action.templates;
break;
case 'SET_NOTE_TAGS':
draft.selectedNoteTags = action.items;
break;

View File

@@ -20,7 +20,6 @@ const defaultKeymapItems = {
{ accelerator: 'Cmd+Q', command: 'quit' },
{ accelerator: 'Cmd+,', command: 'config' },
{ accelerator: 'Cmd+W', command: 'closeWindow' },
{ accelerator: 'Option+Cmd+I', command: 'insertTemplate' },
{ accelerator: 'Cmd+C', command: 'textCopy' },
{ accelerator: 'Cmd+X', command: 'textCut' },
{ accelerator: 'Cmd+V', command: 'textPaste' },
@@ -61,7 +60,6 @@ const defaultKeymapItems = {
{ accelerator: 'Ctrl+T', command: 'newTodo' },
{ accelerator: 'Ctrl+S', command: 'synchronize' },
{ accelerator: 'Ctrl+Q', command: 'quit' },
{ accelerator: 'Ctrl+Alt+I', command: 'insertTemplate' },
{ accelerator: 'Ctrl+C', command: 'textCopy' },
{ accelerator: 'Ctrl+X', command: 'textCut' },
{ accelerator: 'Ctrl+V', command: 'textPaste' },

View File

@@ -2,6 +2,14 @@
This tool is used to build the plugin repository at https://github.com/joplin/plugins
# Publishing
## Testing
To test the tool with existing packages, the best is to:
- Create a separate copy of the plugin repo
- Reset back a few commits
- Run with the --dry-run option: `plugin-repo-cli build ~/src/joplin-plugins-test/ --dry-run`
## Publishing
To publish it, run `npm run publishAll` from the root.

View File

@@ -1,11 +1,5 @@
#!/usr/bin/env node
// To test the tool with existing packages, the best is to:
//
// - Create a separate copy of the plugin repo
// - Reset back a few commits
// - Run with the --dry-run option: `plugin-repo-cli build ~/src/joplin-plugins-test/ --dry-run`
import * as fs from 'fs-extra';
import * as path from 'path';
import * as process from 'process';

View File

@@ -0,0 +1,68 @@
import * as fs from 'fs-extra';
import updateReadme from './updateReadme';
describe('updateReadme', () => {
test('should update the README file', async () => {
const manifests: any = {
'io.github.jackgruber.copytags': {
'manifest_version': 1,
'id': 'io.github.jackgruber.copytags',
'app_min_version': '1.6.2',
'version': '1.0.1',
'name': 'Tagging',
'description': 'Plugin to extend the Joplin tagging menu with a coppy all tags and a tagging dialog with more control. (Formerly Copy Tags).',
'author': 'JackGruber',
'homepage_url': 'https://github.com/JackGruber/joplin-plugin-tagging/blob/master/README.md',
'repository_url': 'https://github.com/JackGruber/joplin-plugin-tagging',
'keywords': [
'duplicate',
'copy',
'tags',
'tagging',
'tag',
],
'_publish_hash': 'sha256:88daaf234a9b47e5644a8de6f830a801d12edbe41ea5364d994773e89eeafeef',
'_publish_commit': 'master:64c0510e3236df7788a8d10ec28dcfbb4c2bdbb7',
'_npm_package_name': 'joplin-plugin-copytags',
},
'joplin.plugin.ambrt.backlinksToNote': {
'manifest_version': 1,
'id': 'joplin.plugin.ambrt.backlinksToNote',
'app_min_version': '1.7',
'version': '2.0.10',
'name': 'Automatic Backlinks to note',
'description': 'Creates backlinks to opened note, also in automatic way',
'author': 'ambrt',
'homepage_url': 'https://discourse.joplinapp.org/t/insert-referencing-notes-backlinks-plugin/13632',
'_publish_hash': 'sha256:b5dec8d00f19e34c4fe1dc0ed380b6743aa7debfd8f600ead0d6866ba21466f1',
'_publish_commit': 'master:05020664a6a7f567c466e3fbad1d7e7ec64dc369',
'_npm_package_name': 'joplin-plugin-backlinks',
},
};
const tempFilePath = `${__dirname}/test_README.md`;
await fs.writeFile(tempFilePath, '<!-- PLUGIN_LIST -->\n<!-- PLUGIN_LIST -->');
await updateReadme(tempFilePath, manifests);
const content = await fs.readFile(tempFilePath, 'utf8');
// Check header
expect(content.includes('| &nbsp; | &nbsp; | Name | Version | Description | Author |')).toBe(true);
// Check plugin content
expect(content.includes('https://github.com/JackGruber/joplin-plugin-tagging/blob/master/README.md')).toBe(true);
expect(content.includes('https://github.com/joplin/plugins/raw/master/plugins/joplin.plugin.ambrt.backlinksToNote/plugin.jpl')).toBe(true);
expect(content.includes('Automatic Backlinks to note')).toBe(true);
expect(content.includes('2.0.10')).toBe(true);
expect(content.includes('Creates backlinks to opened note, also in automatic way')).toBe(true);
expect(content.includes('ambrt')).toBe(true);
// Check that it keeps the markers
expect(content.split('<!-- PLUGIN_LIST -->').length - 1).toBe(2);
await fs.remove(tempFilePath);
});
});

View File

@@ -2,20 +2,36 @@ import * as fs from 'fs-extra';
import markdownUtils, { MarkdownTableHeader, MarkdownTableRow } from '@joplin/lib/markdownUtils';
export default async function(readmePath: string, manifests: any) {
const rows: MarkdownTableRow[] = [];
let rows: MarkdownTableRow[] = [];
for (const pluginId in manifests) {
rows.push(manifests[pluginId]);
}
rows = rows.map(row => {
return {
...row,
download_url: `https://github.com/joplin/plugins/raw/master/plugins/${row.id}/plugin.jpl`,
};
});
const headers: MarkdownTableHeader[] = [
{
name: 'homepage_url',
label: '&nbsp;',
filter: (value: string) => {
if (!value) return '-';
return `[🏠](${markdownUtils.escapeLinkUrl(value)})`;
},
},
{
name: 'download_url',
label: '&nbsp;',
filter: (value: string) => {
if (!value) return '-';
return `[⬇️](${markdownUtils.escapeLinkUrl(value)})`;
},
},
{
name: 'name',
label: 'Name',

View File

@@ -4,6 +4,10 @@ It is possible to get the apps to display or log more information that might hel
## Desktop application
If the application starts with a white screen, open **View &gt; Toggle Developer Tools** in the menu. Then check in the console if there is any error or warning and please let us know about it.
Otherwise, follow these instructions:
- Click on menu **Help &gt; Open Profile Directory** and add a file named "flags.txt" in your directory with the following content: `--open-dev-tools --debug --log-level debug`
- Restart the application
- The development tools should now be opened. Click the "Console" tab

View File

@@ -1,3 +1,4 @@
# Mobile app
<img src="https://joplinapp.org/images/JoplinMobileUI.jpg" style="max-width=100%"/>
An Android and iOS (iPhone/iPad) applications are available from the [Joplin home page](https://joplinapp.org).
An Android and iOS (iPhone/iPad) applications are available from the [Joplin home page](https://joplinapp.org).