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

Compare commits

..

7 Commits

Author SHA1 Message Date
Laurent Cozic
05be96e0a6 Make sure old softbreaks setting default is set too, so that it is used in 27.js migration 2020-10-31 23:41:00 +00:00
Laurent Cozic
351ae3d47f Merge branch 'dev' into commonmark 2020-10-31 23:31:00 +00:00
Laurent Cozic
db7d467ddc Merge branch 'dev' into commonmark 2020-10-29 17:16:45 +00:00
Laurent Cozic
5f2d90b7e4 Enable softbreaks by default 2020-10-29 17:09:41 +00:00
Laurent Cozic
9491d81f5c Merge branch 'dev' into commonmark 2020-10-26 23:20:51 +00:00
Laurent Cozic
6bdeddaa1d Merge branch 'dev' into commonmark 2020-10-24 00:15:28 +01:00
Laurent Cozic
301adaa7d0 Made handling of links more standard 2020-10-24 00:00:56 +01:00
20 changed files with 118 additions and 87 deletions

View File

@@ -867,8 +867,9 @@ msgid "New version: %s"
msgstr "새 버전: %s"
#: ElectronClient/checkForUpdates.js:154
#, fuzzy
msgid "Download"
msgstr "다운로드"
msgstr "다운로드"
#: ElectronClient/checkForUpdates.js:154
msgid "Full Release Notes"
@@ -2247,8 +2248,9 @@ msgid "Error opening note in editor: %s"
msgstr "편집기에서 노트를 열 수 없는 오류가 발생하였습니다: %s"
#: ElectronClient/commands/openProfileDirectory.js:18
#, fuzzy
msgid "Open profile directory"
msgstr "프로필 디렉터리 열기"
msgstr "템플릿 디렉터리 열기"
#: ElectronClient/app.js:345
#, javascript-format

View File

@@ -1,8 +1,8 @@
import MdToHtml from 'lib/joplin-renderer/MdToHtml';
const os = require('os');
const { filename } = require('lib/path-utils');
const { asyncTest, setupDatabaseAndSynchronizer, switchClient } = require('test-utils.js');
const shim = require('lib/shim').default;
const MdToHtml = require('lib/joplin-renderer/MdToHtml').default;
const { themeStyle } = require('lib/theme');
function newTestMdToHtml(options:any = null) {
@@ -120,23 +120,54 @@ describe('MdToHtml', function() {
it('should return the rendered body only', asyncTest(async () => {
const mdToHtml = newTestMdToHtml();
// In this case, the HTML contains only the rendered markdown,
// with no wrapper and no style.
// The style is instead in the cssStrings property.
const result = await mdToHtml.render('just **testing**', null, { bodyOnly: true });
expect(result.cssStrings.length).toBeGreaterThan(0);
expect(result.html.trim()).toBe('just <strong>testing</strong>');
// In this case, the HTML contains only the rendered markdown, with
// no wrapper and no style. The style is instead in the cssStrings
// property.
{
const result = await mdToHtml.render('just **testing**', null, { bodyOnly: true });
expect(result.cssStrings.length).toBeGreaterThan(0);
expect(result.html.trim()).toBe('just <strong>testing</strong>');
}
// But it should not remove the wrapping <p> tags if there's more
// than one line
{
const result = await mdToHtml.render('one\n\ntwo', null, { bodyOnly: true });
expect(result.html.trim()).toBe('<p>one</p>\n<p>two</p>');
}
}));
it('should split HTML and CSS', asyncTest(async () => {
const mdToHtml = newTestMdToHtml();
// It is similar to the bodyOnly option, excepts that
// the rendered Markdown is wrapped in a DIV
// It is similar to the bodyOnly option, excepts that the rendered
// Markdown is wrapped in a DIV
const result = await mdToHtml.render('just **testing**', null, { splitted: true });
expect(result.cssStrings.length).toBeGreaterThan(0);
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();
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>'],
];
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

@@ -30,14 +30,9 @@ const getLabel = (commandName: string):string => {
return _('Command palette');
case 'config':
return shim.isMac() ? _('Preferences') : _('Options');
default:
throw new Error(`Command: ${commandName} is unknown`);
}
// We don't throw an error if a command is not found because if for
// example a command is removed from one version to the next, or a
// command is renamed, we still want the keymap editor to work. So in
// that case, we simply display the command name and it is up to the
// user to fix the shortcut if needed.
return `${commandName} (${_('Invalid')})`;
};
export default getLabel;

View File

@@ -1,6 +1,6 @@
{
"name": "Joplin",
"version": "1.3.18",
"version": "1.3.11",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@@ -1,6 +1,6 @@
{
"name": "Joplin",
"version": "1.3.18",
"version": "1.3.11",
"description": "Joplin for Desktop",
"main": "main.js",
"scripts": {

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.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)
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.10/joplin-v1.3.10.apk) [32-bit](https://github.com/laurent22/joplin-android/releases/download/android-v1.3.10/joplin-v1.3.10-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

@@ -132,8 +132,8 @@ android {
applicationId "net.cozic.joplin"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 2097602
versionName "1.3.13"
versionCode 2097598
versionName "1.3.10"
ndk {
abiFilters "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
}

View File

@@ -338,13 +338,13 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 56;
CURRENT_PROJECT_VERSION = 55;
DEVELOPMENT_TEAM = A9BXAFS6CT;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Joplin/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 10.3.1;
MARKETING_VERSION = 10.3.0;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@@ -365,12 +365,12 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 56;
CURRENT_PROJECT_VERSION = 55;
DEVELOPMENT_TEAM = A9BXAFS6CT;
INFOPLIST_FILE = Joplin/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 10.3.1;
MARKETING_VERSION = 10.3.0;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",

View File

@@ -3,9 +3,6 @@
#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import <UserNotifications/UserNotifications.h>
#import <RNCPushNotificationIOS.h>
#import "RNQuickActionManager.h"
#ifdef FB_SONARKIT_ENABLED
#import <FlipperKit/FlipperClient.h>
@@ -14,6 +11,9 @@
#import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h>
#import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h>
#import <FlipperKitReactPlugin/FlipperKitReactPlugin.h>
#import "RNQuickActionManager.h"
#import <UserNotifications/UserNotifications.h>
#import <RNCPushNotificationIOS.h>
static void InitializeFlipper(UIApplication *application) {
FlipperClient *client = [FlipperClient sharedClient];

View File

@@ -45,29 +45,12 @@
<string>To add geo-location information to a note. Can be disabled in app.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>To add geo-location information to a note. Can be disabled in app.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>The images will be displayed on your notes.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>To allow attaching images to a note</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>The images will be displayed on your notes.</string>
<key>UIAppFonts</key>
<array>
<string>AntDesign.ttf</string>
<string>Entypo.ttf</string>
<string>EvilIcons.ttf</string>
<string>Feather.ttf</string>
<string>FontAwesome.ttf</string>
<string>FontAwesome5_Brands.ttf</string>
<string>FontAwesome5_Regular.ttf</string>
<string>FontAwesome5_Solid.ttf</string>
<string>Foundation.ttf</string>
<string>Ionicons.ttf</string>
<string>MaterialIcons.ttf</string>
<string>MaterialCommunityIcons.ttf</string>
<string>SimpleLineIcons.ttf</string>
<string>Octicons.ttf</string>
<string>Zocial.ttf</string>
<string>Fontisto.ttf</string>
</array>
<array/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
@@ -91,5 +74,24 @@
<string>Light</string>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>UIAppFonts</key>
<array>
<string>AntDesign.ttf</string>
<string>Entypo.ttf</string>
<string>EvilIcons.ttf</string>
<string>Feather.ttf</string>
<string>FontAwesome.ttf</string>
<string>FontAwesome5_Brands.ttf</string>
<string>FontAwesome5_Regular.ttf</string>
<string>FontAwesome5_Solid.ttf</string>
<string>Foundation.ttf</string>
<string>Ionicons.ttf</string>
<string>MaterialIcons.ttf</string>
<string>MaterialCommunityIcons.ttf</string>
<string>SimpleLineIcons.ttf</string>
<string>Octicons.ttf</string>
<string>Zocial.ttf</string>
<string>Fontisto.ttf</string>
</array>
</dict>
</plist>

View File

@@ -21,8 +21,6 @@ export default function useOnMessage(onCheckboxChange:Function, noteBody:string,
onJoplinLinkClick(msg);
} else if (msg.startsWith('error:')) {
console.error(`Webview injected script error: ${msg}`);
} else {
onJoplinLinkClick(msg);
}
}, [onCheckboxChange, noteBody, onMarkForDownload, onJoplinLinkClick, onResourceLongPress]);
}

View File

@@ -116,7 +116,6 @@ export default function useSource(noteBody:string, noteMarkupLanguage:number, th
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
${assetsToHeaders(result.pluginAssets, { asHtml: true })}
</head>

View File

@@ -51,13 +51,6 @@ shared.renderFolders = function(props, renderItem) {
shared.renderTags = function(props, renderItem) {
const tags = props.tags.slice();
tags.sort((a, b) => {
// It seems title can sometimes be undefined (perhaps when syncing
// and before tag has been decrypted?). It would be best to find
// the root cause but for now that will do.
//
// Fixes https://github.com/laurent22/joplin/issues/4051
if (!a || !a.title || !b || !b.title) return 0;
// Note: while newly created tags are normalized and lowercase
// imported tags might be any case, so we need to do case-insensitive
// sort.

View File

@@ -318,9 +318,14 @@ export default class MdToHtml {
return output;
}
// The string we are looking for is: <p></p>\n
private removeMarkdownItWrappingParagraph_(html:string) {
// <p></p>\n
if (html.length < 8) return html;
// If there are multiple <p> tags, we keep them because it's multiple lines
// and removing the first and last tag will result in invalid HTML.
if ((html.match(/<\/p>/g) || []).length > 1) return html;
if (html.substr(0, 3) !== '<p>') return html;
if (html.slice(-5) !== '</p>\n') return html;
return html.substring(3, html.length - 5);
@@ -376,7 +381,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 = '';

View File

@@ -72,11 +72,24 @@ function plugin(markdownIt:any, ruleOptions:RuleOptions) {
if (hrefAttr.indexOf('#') === 0 && href.indexOf('#') === 0) js = ''; // If it's an internal anchor, don't add any JS since the webview is going to handle navigating to the right place
const attrHtml = [];
attrHtml.push('data-from-md');
if (resourceIdAttr) attrHtml.push(resourceIdAttr);
if (title) attrHtml.push(`title='${htmlentities(title)}'`);
if (mime) attrHtml.push(`type='${htmlentities(mime)}'`);
if (ruleOptions.plainResourceRendering || ruleOptions.linkRenderingType === 2) {
return `<a data-from-md ${resourceIdAttr} title='${htmlentities(title)}' href='${htmlentities(href)}' type='${htmlentities(mime)}'>`;
icon = '';
attrHtml.push(`href='${htmlentities(href)}'`);
// return `<a data-from-md ${resourceIdAttr} title='${htmlentities(title)}' href='${htmlentities(href)}' type='${htmlentities(mime)}'>`;
} else {
return `<a data-from-md ${resourceIdAttr} title='${htmlentities(title)}' href='${hrefAttr}' ${js} type='${htmlentities(mime)}'>${icon}`;
attrHtml.push(`href='${hrefAttr}'`);
if (js) attrHtml.push(js);
// return `<a data-from-md ${resourceIdAttr} title='${htmlentities(title)}' href='${hrefAttr}' ${js} type='${htmlentities(mime)}'>${icon}`;
}
return `<a ${attrHtml.join(' ')}>${icon}`;
};
}

View File

@@ -565,11 +565,11 @@ class Setting extends BaseModel {
},
// Deprecated - use markdown.plugin.*
'markdown.softbreaks': { value: false, type: SettingItemType.Bool, public: false, appTypes: ['mobile', 'desktop'] },
'markdown.softbreaks': { value: true, type: SettingItemType.Bool, public: false, appTypes: ['mobile', 'desktop'] },
'markdown.typographer': { value: false, type: SettingItemType.Bool, public: false, appTypes: ['mobile', 'desktop'] },
// Deprecated
'markdown.plugin.softbreaks': { value: false, type: SettingItemType.Bool, section: 'markdownPlugins', public: true, appTypes: ['mobile', 'desktop'], label: () => `${_('Enable soft breaks')}${wysiwygYes}` },
'markdown.plugin.softbreaks': { value: true, type: SettingItemType.Bool, section: 'markdownPlugins', public: true, appTypes: ['mobile', 'desktop'], label: () => `${_('Enable soft breaks')}${wysiwygYes}` },
'markdown.plugin.typographer': { value: false, type: SettingItemType.Bool, section: 'markdownPlugins', public: true, appTypes: ['mobile', 'desktop'], label: () => `${_('Enable typographer support')}${wysiwygYes}` },
'markdown.plugin.katex': { value: true, type: SettingItemType.Bool, section: 'markdownPlugins', public: true, appTypes: ['mobile', 'desktop'], label: () => `${_('Enable math expressions')}${wysiwygYes}` },
'markdown.plugin.fountain': { value: false, type: SettingItemType.Bool, section: 'markdownPlugins', public: true, appTypes: ['mobile', 'desktop'], label: () => `${_('Enable Fountain syntax support')}${wysiwygYes}` },

View File

@@ -352,7 +352,10 @@ export default class KeymapService extends BaseService {
public domToElectronAccelerator(event: KeyboardEvent<HTMLDivElement>) {
const parts = [];
const { key, ctrlKey, metaKey, altKey, shiftKey } = event;
// We use the "keyCode" and not "key" because the modifier keys
// would change the "key" value. eg "Option+U" would give "º" as a key instead of "U"
const { keyCode, ctrlKey, metaKey, altKey, shiftKey } = event;
// First, the modifiers
if (ctrlKey) parts.push('Ctrl');
@@ -368,7 +371,7 @@ export default class KeymapService extends BaseService {
}
// Finally, the key
const electronKey = KeymapService.domToElectronKey(key);
const electronKey = KeymapService.domToElectronKey(String.fromCharCode(keyCode));
if (electronKey) parts.push(electronKey);
return parts.join('+');

View File

@@ -2,37 +2,27 @@ import CommandService, { CommandContext, CommandDeclaration, CommandRuntime } fr
import { Command } from './types';
/**
* This class allows executing or registering new Joplin commands. Commands
* can be executed or associated with
* {@link JoplinViewsToolbarButtons | toolbar buttons} or
* {@link JoplinViewsMenuItems | menu items}.
* This class allows executing or registering new Joplin commands. Commands can be executed or associated with
* {@link JoplinViewsToolbarButtons | toolbar buttons} or {@link JoplinViewsMenuItems | menu items}.
*
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/CliClient/tests/support/plugins/register_command)
*
* ## Executing Joplin's internal commands
*
* It is also possible to execute internal Joplin's commands which, as of
* now, are not well documented. You can find the list directly on GitHub
* though at the following locations:
* It is also possible to execute internal Joplin's commands which, as of now, are not well documented.
* You can find the list directly on GitHub though at the following locations:
*
* * [Main screen commands](https://github.com/laurent22/joplin/tree/dev/ElectronClient/gui/MainScreen/commands)
* * [Global commands](https://github.com/laurent22/joplin/tree/dev/ElectronClient/commands)
* * [Editor commands](https://github.com/laurent22/joplin/tree/dev/ElectronClient/gui/NoteEditor/commands/editorCommandDeclarations.ts)
*
* To view what arguments are supported, you can open any of these files
* and look at the `execute()` command.
* To view what arguments are supported, you can open any of these files and look at the `execute()` command.
*/
export default class JoplinCommands {
/**
* <span class="platform-desktop">desktop</span> Executes the given
* command.
*
* The command can take any number of arguments, and the supported
* arguments will vary based on the command. For custom commands, this
* is the `args` passed to the `execute()` function. For built-in
* commands, you can find the supported arguments by checking the links
* above.
* <span class="platform-desktop">desktop</span> Executes the given command.
* The `props` are the arguments passed to the command, and they vary based on the command
*
* ```typescript
* // Create a new note in the current notebook:

View File

@@ -12,6 +12,6 @@
"**/node_modules",
"ElectronClient/dist/**/*",
"CliClient/tests/support/**/*",
"CliClient/tests-build/support/**/*",
"CliClient/tests-build/**/*",
],
}

View File

@@ -31,6 +31,6 @@
"**/node_modules",
"ElectronClient/dist/**/*",
"CliClient/tests/support/**/*",
"CliClient/tests-build/support/**/*",
"CliClient/tests-build/**/*",
],
}