mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
Merge branch 'release-1.7' into dev
This commit is contained in:
commit
dadec484e9
@ -106,6 +106,9 @@ packages/app-cli/tests/Synchronizer.tags.js.map
|
||||
packages/app-cli/tests/fsDriver.d.ts
|
||||
packages/app-cli/tests/fsDriver.js
|
||||
packages/app-cli/tests/fsDriver.js.map
|
||||
packages/app-cli/tests/htmlUtils.d.ts
|
||||
packages/app-cli/tests/htmlUtils.js
|
||||
packages/app-cli/tests/htmlUtils.js.map
|
||||
packages/app-cli/tests/models_Folder.d.ts
|
||||
packages/app-cli/tests/models_Folder.js
|
||||
packages/app-cli/tests/models_Folder.js.map
|
||||
@ -847,6 +850,9 @@ packages/lib/fs-driver-base.js.map
|
||||
packages/lib/fs-driver-node.d.ts
|
||||
packages/lib/fs-driver-node.js
|
||||
packages/lib/fs-driver-node.js.map
|
||||
packages/lib/htmlUtils.d.ts
|
||||
packages/lib/htmlUtils.js
|
||||
packages/lib/htmlUtils.js.map
|
||||
packages/lib/import-enex-md-gen.d.ts
|
||||
packages/lib/import-enex-md-gen.js
|
||||
packages/lib/import-enex-md-gen.js.map
|
||||
|
6
.gitignore
vendored
6
.gitignore
vendored
@ -93,6 +93,9 @@ packages/app-cli/tests/Synchronizer.tags.js.map
|
||||
packages/app-cli/tests/fsDriver.d.ts
|
||||
packages/app-cli/tests/fsDriver.js
|
||||
packages/app-cli/tests/fsDriver.js.map
|
||||
packages/app-cli/tests/htmlUtils.d.ts
|
||||
packages/app-cli/tests/htmlUtils.js
|
||||
packages/app-cli/tests/htmlUtils.js.map
|
||||
packages/app-cli/tests/models_Folder.d.ts
|
||||
packages/app-cli/tests/models_Folder.js
|
||||
packages/app-cli/tests/models_Folder.js.map
|
||||
@ -834,6 +837,9 @@ packages/lib/fs-driver-base.js.map
|
||||
packages/lib/fs-driver-node.d.ts
|
||||
packages/lib/fs-driver-node.js
|
||||
packages/lib/fs-driver-node.js.map
|
||||
packages/lib/htmlUtils.d.ts
|
||||
packages/lib/htmlUtils.js
|
||||
packages/lib/htmlUtils.js.map
|
||||
packages/lib/import-enex-md-gen.d.ts
|
||||
packages/lib/import-enex-md-gen.js
|
||||
packages/lib/import-enex-md-gen.js.map
|
||||
|
@ -1,6 +1,4 @@
|
||||
/* eslint-disable no-unused-vars */
|
||||
|
||||
const htmlUtils = require('@joplin/lib/htmlUtils.js');
|
||||
import htmlUtils from '@joplin/lib/htmlUtils';
|
||||
|
||||
describe('htmlUtils', function() {
|
||||
|
||||
@ -19,8 +17,8 @@ describe('htmlUtils', function() {
|
||||
];
|
||||
|
||||
for (let i = 0; i < testCases.length; i++) {
|
||||
const md = testCases[i][0];
|
||||
const expected = testCases[i][1];
|
||||
const md = testCases[i][0] as string;
|
||||
const expected = testCases[i][1] as string[];
|
||||
|
||||
expect(htmlUtils.extractImageUrls(md).join(' ')).toBe(expected.join(' '));
|
||||
}
|
||||
@ -33,19 +31,19 @@ describe('htmlUtils', function() {
|
||||
['<img src="http://test.com/img.png" alt="testing" >', ['http://other.com/img.png'], '<img src="http://other.com/img.png" alt="testing" >'],
|
||||
];
|
||||
|
||||
const callback = (urls) => {
|
||||
const callback = (urls: string[]) => {
|
||||
let i = -1;
|
||||
|
||||
return function(src) {
|
||||
return function(_src: string) {
|
||||
i++;
|
||||
return urls[i];
|
||||
};
|
||||
};
|
||||
|
||||
for (let i = 0; i < testCases.length; i++) {
|
||||
const md = testCases[i][0];
|
||||
const r = htmlUtils.replaceImageUrls(md, callback(testCases[i][1]));
|
||||
expect(r.trim()).toBe(testCases[i][2].trim());
|
||||
const md = testCases[i][0] as string;
|
||||
const r = htmlUtils.replaceImageUrls(md, callback(testCases[i][1] as string[]));
|
||||
expect(r.trim()).toBe((testCases[i][2] as string).trim());
|
||||
}
|
||||
}));
|
||||
|
@ -114,7 +114,7 @@ export default function(props: Props) {
|
||||
let cancelled = false;
|
||||
|
||||
async function fetchPluginIds() {
|
||||
const pluginIds = await repoApi().canBeUpdatedPlugins(pluginItems as any);
|
||||
const pluginIds = await repoApi().canBeUpdatedPlugins(pluginItems.map(p => p.manifest));
|
||||
if (cancelled) return;
|
||||
const conv: Record<string, boolean> = {};
|
||||
pluginIds.forEach(id => conv[id] = true);
|
||||
|
@ -5,6 +5,7 @@ const bridge = require('electron').remote.require('./bridge').default;
|
||||
const Menu = bridge().Menu;
|
||||
const MenuItem = bridge().MenuItem;
|
||||
import Resource from '@joplin/lib/models/Resource';
|
||||
import htmlUtils from '@joplin/lib/htmlUtils';
|
||||
const fs = require('fs-extra');
|
||||
const { clipboard } = require('electron');
|
||||
const { toSystemSlashes } = require('@joplin/lib/path-utils');
|
||||
@ -47,7 +48,13 @@ function handleCopyToClipboard(options: ContextMenuOptions) {
|
||||
if (options.textToCopy) {
|
||||
clipboard.writeText(options.textToCopy);
|
||||
} else if (options.htmlToCopy) {
|
||||
clipboard.writeHTML(options.htmlToCopy);
|
||||
// In that case we need to set both HTML and Text context, otherwise it
|
||||
// won't be possible to paste the text in, for example, a text editor.
|
||||
// https://github.com/laurent22/joplin/issues/4441
|
||||
clipboard.write({
|
||||
text: htmlUtils.stripHtml(options.htmlToCopy),
|
||||
html: options.htmlToCopy,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
2
packages/app-desktop/package-lock.json
generated
2
packages/app-desktop/package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/app-desktop",
|
||||
"version": "1.7.9",
|
||||
"version": "1.7.10",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@joplin/app-desktop",
|
||||
"version": "1.7.9",
|
||||
"version": "1.7.10",
|
||||
"description": "Joplin for Desktop",
|
||||
"main": "main.js",
|
||||
"private": true,
|
||||
|
@ -31,19 +31,20 @@ const selfClosingElements = [
|
||||
];
|
||||
|
||||
class HtmlUtils {
|
||||
headAndBodyHtml(doc) {
|
||||
|
||||
public headAndBodyHtml(doc: any) {
|
||||
const output = [];
|
||||
if (doc.head) output.push(doc.head.innerHTML);
|
||||
if (doc.body) output.push(doc.body.innerHTML);
|
||||
return output.join('\n');
|
||||
}
|
||||
|
||||
isSelfClosingTag(tagName) {
|
||||
public isSelfClosingTag(tagName: string) {
|
||||
return selfClosingElements.includes(tagName.toLowerCase());
|
||||
}
|
||||
|
||||
// Returns the **encoded** URLs, so to be useful they should be decoded again before use.
|
||||
extractImageUrls(html) {
|
||||
public extractImageUrls(html: string) {
|
||||
if (!html) return [];
|
||||
|
||||
const output = [];
|
||||
@ -55,8 +56,8 @@ class HtmlUtils {
|
||||
return output.filter(url => !!url);
|
||||
}
|
||||
|
||||
replaceImageUrls(html, callback) {
|
||||
return this.processImageTags(html, data => {
|
||||
public replaceImageUrls(html: string, callback: Function) {
|
||||
return this.processImageTags(html, (data: any) => {
|
||||
const newSrc = callback(data.src);
|
||||
return {
|
||||
type: 'replaceSource',
|
||||
@ -65,10 +66,10 @@ class HtmlUtils {
|
||||
});
|
||||
}
|
||||
|
||||
processImageTags(html, callback) {
|
||||
public processImageTags(html: string, callback: Function) {
|
||||
if (!html) return '';
|
||||
|
||||
return html.replace(imageRegex, (v, before, src, after) => {
|
||||
return html.replace(imageRegex, (_v: string, before: string, src: string, after: string) => {
|
||||
const action = callback({ src: src });
|
||||
|
||||
if (!action) return `<img${before}src="${src}"${after}>`;
|
||||
@ -90,16 +91,16 @@ class HtmlUtils {
|
||||
});
|
||||
}
|
||||
|
||||
prependBaseUrl(html, baseUrl) {
|
||||
public prependBaseUrl(html: string, baseUrl: string) {
|
||||
if (!html) return '';
|
||||
|
||||
return html.replace(anchorRegex, (v, before, href, after) => {
|
||||
return html.replace(anchorRegex, (_v: string, before: string, href: string, after: string) => {
|
||||
const newHref = urlUtils.prependBaseUrl(href, baseUrl);
|
||||
return `<a${before}href="${newHref}"${after}>`;
|
||||
});
|
||||
}
|
||||
|
||||
attributesHtml(attr) {
|
||||
public attributesHtml(attr: any) {
|
||||
const output = [];
|
||||
|
||||
for (const n in attr) {
|
||||
@ -110,10 +111,10 @@ class HtmlUtils {
|
||||
return output.join(' ');
|
||||
}
|
||||
|
||||
stripHtml(html) {
|
||||
const output = [];
|
||||
public stripHtml(html: string) {
|
||||
const output: string[] = [];
|
||||
|
||||
const tagStack = [];
|
||||
const tagStack: any[] = [];
|
||||
|
||||
const currentTag = () => {
|
||||
if (!tagStack.length) return '';
|
||||
@ -124,16 +125,16 @@ class HtmlUtils {
|
||||
|
||||
const parser = new htmlparser2.Parser({
|
||||
|
||||
onopentag: (name) => {
|
||||
onopentag: (name: string) => {
|
||||
tagStack.push(name.toLowerCase());
|
||||
},
|
||||
|
||||
ontext: (decodedText) => {
|
||||
ontext: (decodedText: string) => {
|
||||
if (disallowedTags.includes(currentTag())) return;
|
||||
output.push(decodedText);
|
||||
},
|
||||
|
||||
onclosetag: (name) => {
|
||||
onclosetag: (name: string) => {
|
||||
if (currentTag() === name.toLowerCase()) tagStack.pop();
|
||||
},
|
||||
|
||||
@ -146,6 +147,4 @@ class HtmlUtils {
|
||||
}
|
||||
}
|
||||
|
||||
const htmlUtils = new HtmlUtils();
|
||||
|
||||
module.exports = htmlUtils;
|
||||
export default new HtmlUtils();
|
@ -1,7 +1,7 @@
|
||||
const stringToStream = require('string-to-stream');
|
||||
// const cleanHtml = require('clean-html');
|
||||
const resourceUtils = require('./resourceUtils.js');
|
||||
const { isSelfClosingTag } = require('./htmlUtils');
|
||||
const htmlUtils = require('./htmlUtils').default;
|
||||
const Entities = require('html-entities').AllHtmlEntities;
|
||||
const htmlentities = new Entities().encode;
|
||||
|
||||
@ -126,7 +126,7 @@ function enexXmlToHtml_(stream, resources) {
|
||||
const nodeAttributes = attributeToLowerCase(node);
|
||||
const checkedHtml = nodeAttributes.checked && nodeAttributes.checked.toLowerCase() == 'true' ? ' checked="checked" ' : ' ';
|
||||
section.lines.push(`<input${checkedHtml}type="checkbox" onclick="return false;" />`);
|
||||
} else if (isSelfClosingTag(tagName)) {
|
||||
} else if (htmlUtils.isSelfClosingTag(tagName)) {
|
||||
section.lines.push(`<${tagName}${attributesStr}/>`);
|
||||
} else {
|
||||
section.lines.push(`<${tagName}${attributesStr}>`);
|
||||
@ -135,7 +135,7 @@ function enexXmlToHtml_(stream, resources) {
|
||||
|
||||
saxStream.on('closetag', function(node) {
|
||||
const tagName = node ? node.toLowerCase() : node;
|
||||
if (!isSelfClosingTag(tagName)) section.lines.push(`</${tagName}>`);
|
||||
if (!htmlUtils.isSelfClosingTag(tagName)) section.lines.push(`</${tagName}>`);
|
||||
});
|
||||
|
||||
saxStream.on('attribute', function() {});
|
||||
|
@ -3,7 +3,7 @@ import Setting from './models/Setting';
|
||||
import shim from './shim';
|
||||
import MarkupToHtml, { MarkupLanguage } from '@joplin/renderer/MarkupToHtml';
|
||||
|
||||
const htmlUtils = require('./htmlUtils');
|
||||
import htmlUtils from './htmlUtils';
|
||||
import Resource from './models/Resource';
|
||||
|
||||
export class MarkupLanguageUtils {
|
||||
|
@ -16,7 +16,7 @@ import Folder from '../../../models/Folder';
|
||||
import Note from '../../../models/Note';
|
||||
import Tag from '../../../models/Tag';
|
||||
import Resource from '../../../models/Resource';
|
||||
const htmlUtils = require('../../../htmlUtils');
|
||||
import htmlUtils from '../../../htmlUtils';
|
||||
import markupLanguageUtils from '../../../markupLanguageUtils';
|
||||
const mimeUtils = require('../../../mime-utils.js').mime;
|
||||
const md5 = require('md5');
|
||||
|
Loading…
Reference in New Issue
Block a user