mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-21 09:38:01 +02:00
Desktop, Mobile: Fixed issue where file:// URLs would not be rendered correctly
This commit is contained in:
parent
34c1096307
commit
491714cde6
@ -1388,6 +1388,12 @@ packages/renderer/MdToHtml/rules/mermaid.js.map
|
||||
packages/renderer/MdToHtml/rules/sanitize_html.d.ts
|
||||
packages/renderer/MdToHtml/rules/sanitize_html.js
|
||||
packages/renderer/MdToHtml/rules/sanitize_html.js.map
|
||||
packages/renderer/MdToHtml/setupLinkify.d.ts
|
||||
packages/renderer/MdToHtml/setupLinkify.js
|
||||
packages/renderer/MdToHtml/setupLinkify.js.map
|
||||
packages/renderer/MdToHtml/validateLinks.d.ts
|
||||
packages/renderer/MdToHtml/validateLinks.js
|
||||
packages/renderer/MdToHtml/validateLinks.js.map
|
||||
packages/renderer/htmlUtils.d.ts
|
||||
packages/renderer/htmlUtils.js
|
||||
packages/renderer/htmlUtils.js.map
|
||||
|
6
.gitignore
vendored
6
.gitignore
vendored
@ -1377,6 +1377,12 @@ packages/renderer/MdToHtml/rules/mermaid.js.map
|
||||
packages/renderer/MdToHtml/rules/sanitize_html.d.ts
|
||||
packages/renderer/MdToHtml/rules/sanitize_html.js
|
||||
packages/renderer/MdToHtml/rules/sanitize_html.js.map
|
||||
packages/renderer/MdToHtml/setupLinkify.d.ts
|
||||
packages/renderer/MdToHtml/setupLinkify.js
|
||||
packages/renderer/MdToHtml/setupLinkify.js.map
|
||||
packages/renderer/MdToHtml/validateLinks.d.ts
|
||||
packages/renderer/MdToHtml/validateLinks.js
|
||||
packages/renderer/MdToHtml/validateLinks.js.map
|
||||
packages/renderer/htmlUtils.d.ts
|
||||
packages/renderer/htmlUtils.js
|
||||
packages/renderer/htmlUtils.js.map
|
||||
|
@ -54,5 +54,5 @@ module.exports = {
|
||||
|
||||
testEnvironment: 'node',
|
||||
setupFilesAfterEnv: [`${__dirname}/jest.setup.js`],
|
||||
slowTestThreshold: 20,
|
||||
slowTestThreshold: 40,
|
||||
};
|
||||
|
@ -147,27 +147,86 @@ describe('MdToHtml', function() {
|
||||
expect(result.html.trim()).toBe('<div id="rendered-md"><p>just <strong>testing</strong></p>\n</div>');
|
||||
}));
|
||||
|
||||
// it('should render links correctly', (async () => {
|
||||
// const mdToHtml = newTestMdToHtml();
|
||||
it('should render links correctly', (async () => {
|
||||
const testCases = [
|
||||
// 0: input
|
||||
// 1: output with linkify = off
|
||||
// 2: output with linkify = on
|
||||
[
|
||||
'https://example.com',
|
||||
'https://example.com',
|
||||
'<a data-from-md title=\'https://example.com\' href=\'https://example.com\'>https://example.com</a>',
|
||||
],
|
||||
[
|
||||
'file://C:\\AUTOEXEC.BAT',
|
||||
'file://C:\\AUTOEXEC.BAT',
|
||||
'<a data-from-md title=\'file://C:%5CAUTOEXEC.BAT\' href=\'file://C:%5CAUTOEXEC.BAT\'>file://C:\\AUTOEXEC.BAT</a>',
|
||||
],
|
||||
[
|
||||
'example.com',
|
||||
'example.com',
|
||||
'example.com',
|
||||
],
|
||||
[
|
||||
'oo.ps',
|
||||
'oo.ps',
|
||||
'oo.ps',
|
||||
],
|
||||
[
|
||||
'test@example.com',
|
||||
'test@example.com',
|
||||
'test@example.com',
|
||||
],
|
||||
[
|
||||
'<https://example.com>',
|
||||
'<a data-from-md title=\'https://example.com\' href=\'https://example.com\'>https://example.com</a>',
|
||||
'<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>',
|
||||
'<a data-from-md title=\'https://example.com\' href=\'https://example.com\'>ok</a>',
|
||||
],
|
||||
[
|
||||
'[bla.pdf](file:///Users/tessus/Downloads/bla.pdf)',
|
||||
'<a data-from-md title=\'file:///Users/tessus/Downloads/bla.pdf\' href=\'file:///Users/tessus/Downloads/bla.pdf\'>bla.pdf</a>',
|
||||
'<a data-from-md title=\'file:///Users/tessus/Downloads/bla.pdf\' href=\'file:///Users/tessus/Downloads/bla.pdf\'>bla.pdf</a>',
|
||||
],
|
||||
];
|
||||
|
||||
// const testCases = [
|
||||
// // None of these should result in a link
|
||||
// ['https://example.com', 'https://example.com'],
|
||||
// ['file://C:\\AUTOEXEC.BAT', 'file://C:\\AUTOEXEC.BAT'],
|
||||
// ['example.com', 'example.com'],
|
||||
// ['oo.ps', 'oo.ps'],
|
||||
// ['test@example.com', 'test@example.com'],
|
||||
const mdToHtmlLinkifyOn = newTestMdToHtml({
|
||||
pluginOptions: {
|
||||
linkify: { enabled: true },
|
||||
},
|
||||
});
|
||||
|
||||
// // 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>'],
|
||||
// ];
|
||||
const mdToHtmlLinkifyOff = newTestMdToHtml({
|
||||
pluginOptions: {
|
||||
linkify: { enabled: false },
|
||||
},
|
||||
});
|
||||
|
||||
// for (const testCase of testCases) {
|
||||
// const [input, expected] = testCase;
|
||||
// const actual = await mdToHtml.render(input, null, { bodyOnly: true, plainResourceRendering: true });
|
||||
// expect(actual.html).toBe(expected);
|
||||
// }
|
||||
// }));
|
||||
for (const testCase of testCases) {
|
||||
const [input, expectedLinkifyOff, expectedLinkifyOn] = testCase;
|
||||
|
||||
{
|
||||
const actual = await mdToHtmlLinkifyOn.render(input, null, {
|
||||
bodyOnly: true,
|
||||
plainResourceRendering: true,
|
||||
});
|
||||
|
||||
expect(actual.html).toBe(expectedLinkifyOn);
|
||||
}
|
||||
|
||||
{
|
||||
const actual = await mdToHtmlLinkifyOff.render(input, null, {
|
||||
bodyOnly: true,
|
||||
plainResourceRendering: true,
|
||||
});
|
||||
|
||||
expect(actual.html).toBe(expectedLinkifyOff);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { validateLinks } from '@joplin/renderer';
|
||||
const stringPadding = require('string-padding');
|
||||
const urlUtils = require('./urlUtils');
|
||||
const MarkdownIt = require('markdown-it');
|
||||
const { setupLinkify } = require('@joplin/renderer');
|
||||
|
||||
// Taken from codemirror/addon/edit/continuelist.js
|
||||
const listRegex = /^(\s*)([*+-] \[[x ]\]\s|[*+-]\s|(\d+)([.)]\s))(\s*)/;
|
||||
@ -47,7 +47,7 @@ const markdownUtils = {
|
||||
// Returns the **encoded** URLs, so to be useful they should be decoded again before use.
|
||||
extractImageUrls(md: string) {
|
||||
const markdownIt = new MarkdownIt();
|
||||
setupLinkify(markdownIt); // Necessary to support file:/// links
|
||||
markdownIt.validateLink = validateLinks; // Necessary to support file:/// links
|
||||
|
||||
const env = {};
|
||||
const tokens = markdownIt.parse(md, env);
|
||||
|
@ -1,6 +1,8 @@
|
||||
import InMemoryCache from './InMemoryCache';
|
||||
import noteStyle from './noteStyle';
|
||||
import { fileExtension } from './pathUtils';
|
||||
import setupLinkify from './MdToHtml/setupLinkify';
|
||||
import validateLinks from './MdToHtml/validateLinks';
|
||||
|
||||
const MarkdownIt = require('markdown-it');
|
||||
const md5 = require('md5');
|
||||
@ -41,7 +43,6 @@ const rules: RendererRules = {
|
||||
mermaid: require('./MdToHtml/rules/mermaid').default,
|
||||
};
|
||||
|
||||
const setupLinkify = require('./MdToHtml/setupLinkify');
|
||||
const hljs = require('highlight.js');
|
||||
const uslug = require('uslug');
|
||||
const markdownItAnchor = require('markdown-it-anchor');
|
||||
@ -517,6 +518,8 @@ export default class MdToHtml {
|
||||
}
|
||||
}
|
||||
|
||||
markdownIt.validateLink = validateLinks;
|
||||
|
||||
if (this.pluginEnabled('linkify')) setupLinkify(markdownIt);
|
||||
|
||||
const renderedBody = markdownIt.render(body, context);
|
||||
|
@ -1,39 +0,0 @@
|
||||
module.exports = function(markdownIt) {
|
||||
// Add `file:` protocol in linkify to allow text in the format of "file://..." to translate into
|
||||
// file-URL links in html view
|
||||
markdownIt.linkify.add('file:', {
|
||||
validate: function(text, pos, self) {
|
||||
const tail = text.slice(pos);
|
||||
if (!self.re.file) {
|
||||
// matches all local file URI on Win/Unix/MacOS systems including reserved characters in some OS (i.e. no OS specific sanity check)
|
||||
self.re.file = new RegExp('^[\\/]{2,3}[\\S]+');
|
||||
}
|
||||
if (self.re.file.test(tail)) {
|
||||
return tail.match(self.re.file)[0].length;
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
});
|
||||
|
||||
// enable file link URLs in MarkdownIt. Keeps other URL restrictions of MarkdownIt untouched.
|
||||
// Format [link name](file://...)
|
||||
markdownIt.validateLink = function(url) {
|
||||
const BAD_PROTO_RE = /^(vbscript|javascript|data):/;
|
||||
const GOOD_DATA_RE = /^data:image\/(gif|png|jpeg|webp);/;
|
||||
|
||||
// url should be normalized at this point, and existing entities are decoded
|
||||
const str = url.trim().toLowerCase();
|
||||
|
||||
if (str.indexOf('data:image/svg+xml,') === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return BAD_PROTO_RE.test(str) ? (GOOD_DATA_RE.test(str) ? true : false) : true;
|
||||
};
|
||||
|
||||
markdownIt.linkify.set({
|
||||
'fuzzyLink': false,
|
||||
'fuzzyIP': false,
|
||||
'fuzzyEmail': false,
|
||||
});
|
||||
};
|
23
packages/renderer/MdToHtml/setupLinkify.ts
Normal file
23
packages/renderer/MdToHtml/setupLinkify.ts
Normal file
@ -0,0 +1,23 @@
|
||||
export default function(markdownIt: any) {
|
||||
// Add `file:` protocol in linkify to allow text in the format of "file://..." to translate into
|
||||
// file-URL links in html view
|
||||
markdownIt.linkify.add('file:', {
|
||||
validate: function(text: string, pos: number, self: any) {
|
||||
const tail = text.slice(pos);
|
||||
if (!self.re.file) {
|
||||
// matches all local file URI on Win/Unix/MacOS systems including reserved characters in some OS (i.e. no OS specific sanity check)
|
||||
self.re.file = new RegExp('^[\\/]{2,3}[\\S]+');
|
||||
}
|
||||
if (self.re.file.test(tail)) {
|
||||
return tail.match(self.re.file)[0].length;
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
});
|
||||
|
||||
markdownIt.linkify.set({
|
||||
'fuzzyLink': false,
|
||||
'fuzzyIP': false,
|
||||
'fuzzyEmail': false,
|
||||
});
|
||||
}
|
15
packages/renderer/MdToHtml/validateLinks.ts
Normal file
15
packages/renderer/MdToHtml/validateLinks.ts
Normal file
@ -0,0 +1,15 @@
|
||||
// enable file link URLs in MarkdownIt. Keeps other URL restrictions of MarkdownIt untouched.
|
||||
// Format [link name](file://...)
|
||||
export default function(url: string) {
|
||||
const BAD_PROTO_RE = /^(vbscript|javascript|data):/;
|
||||
const GOOD_DATA_RE = /^data:image\/(gif|png|jpeg|webp);/;
|
||||
|
||||
// url should be normalized at this point, and existing entities are decoded
|
||||
const str = url.trim().toLowerCase();
|
||||
|
||||
if (str.indexOf('data:image/svg+xml,') === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return BAD_PROTO_RE.test(str) ? (GOOD_DATA_RE.test(str) ? true : false) : true;
|
||||
}
|
@ -2,7 +2,8 @@ import MarkupToHtml, { MarkupLanguage } from './MarkupToHtml';
|
||||
import MdToHtml from './MdToHtml';
|
||||
import HtmlToHtml from './HtmlToHtml';
|
||||
import utils from './utils';
|
||||
const setupLinkify = require('./MdToHtml/setupLinkify');
|
||||
import setupLinkify from './MdToHtml/setupLinkify';
|
||||
import validateLinks from './MdToHtml/validateLinks';
|
||||
const assetsToHeaders = require('./assetsToHeaders');
|
||||
|
||||
export {
|
||||
@ -11,6 +12,7 @@ export {
|
||||
MdToHtml,
|
||||
HtmlToHtml,
|
||||
setupLinkify,
|
||||
validateLinks,
|
||||
assetsToHeaders,
|
||||
utils,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user