2023-08-23 19:16:06 +02:00
|
|
|
import Setting from '@joplin/lib/models/Setting';
|
2023-07-27 16:41:57 +02:00
|
|
|
import { processPastedHtml } from './resourceHandling';
|
2024-01-26 21:11:05 +02:00
|
|
|
import markupLanguageUtils from '@joplin/lib/markupLanguageUtils';
|
|
|
|
import HtmlToMd from '@joplin/lib/HtmlToMd';
|
|
|
|
import { HtmlToMarkdownHandler, MarkupToHtmlHandler } from './types';
|
2023-07-27 16:41:57 +02:00
|
|
|
|
2024-03-06 16:13:24 +02:00
|
|
|
const createTestMarkupConverters = () => {
|
|
|
|
const markupToHtml: MarkupToHtmlHandler = async (markupLanguage, markup, options) => {
|
|
|
|
const conv = markupLanguageUtils.newMarkupToHtml({}, {
|
|
|
|
resourceBaseUrl: `file://${Setting.value('resourceDir')}/`,
|
|
|
|
customCss: '',
|
|
|
|
});
|
|
|
|
return conv.render(markupLanguage, markup, {}, options);
|
|
|
|
};
|
|
|
|
|
|
|
|
const htmlToMd: HtmlToMarkdownHandler = async (_markupLanguage, html, _originalCss) => {
|
|
|
|
const conv = new HtmlToMd();
|
|
|
|
return conv.parse(html);
|
|
|
|
};
|
|
|
|
|
|
|
|
return { markupToHtml, htmlToMd };
|
|
|
|
};
|
|
|
|
|
2023-07-27 16:41:57 +02:00
|
|
|
describe('resourceHandling', () => {
|
|
|
|
it('should sanitize pasted HTML', async () => {
|
2023-08-23 19:16:06 +02:00
|
|
|
Setting.setConstant('resourceDir', '/home/.config/joplin/resources');
|
|
|
|
|
2023-07-27 16:41:57 +02:00
|
|
|
const testCases = [
|
|
|
|
['Test: <style onload="evil()"></style>', 'Test: <style></style>'],
|
|
|
|
['<a href="javascript: alert()">test</a>', '<a href="#">test</a>'],
|
2023-08-23 19:16:06 +02:00
|
|
|
['<a href="file:///home/.config/joplin/resources/test.pdf">test</a>', '<a href="file:///home/.config/joplin/resources/test.pdf">test</a>'],
|
|
|
|
['<a href="file:///etc/passwd">evil.pdf</a>', '<a href="#">evil.pdf</a>'],
|
2023-07-27 16:41:57 +02:00
|
|
|
['<script >evil()</script>', ''],
|
|
|
|
['<script>evil()</script>', ''],
|
|
|
|
[
|
|
|
|
'<img onload="document.body.innerHTML = evil;" src="data:image/svg+xml;base64,=="/>',
|
|
|
|
'<img src="data:image/svg+xml;base64,=="/>',
|
|
|
|
],
|
|
|
|
];
|
|
|
|
|
|
|
|
for (const [html, expected] of testCases) {
|
2024-01-26 21:11:05 +02:00
|
|
|
expect(await processPastedHtml(html, null, null)).toBe(expected);
|
2023-07-27 16:41:57 +02:00
|
|
|
}
|
|
|
|
});
|
2024-01-26 21:11:05 +02:00
|
|
|
|
|
|
|
it('should clean up pasted HTML', async () => {
|
2024-03-06 16:13:24 +02:00
|
|
|
const { markupToHtml, htmlToMd } = createTestMarkupConverters();
|
2024-01-26 21:11:05 +02:00
|
|
|
|
|
|
|
const testCases = [
|
|
|
|
['<p style="background-color: red">Hello</p><p style="display: hidden;">World</p>', '<p>Hello</p>\n<p>World</p>\n'],
|
|
|
|
['', ''],
|
|
|
|
];
|
|
|
|
|
|
|
|
for (const [html, expected] of testCases) {
|
|
|
|
expect(await processPastedHtml(html, htmlToMd, markupToHtml)).toBe(expected);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2024-03-06 16:13:24 +02:00
|
|
|
it('should preserve images pasted from the resource directory', async () => {
|
|
|
|
const { markupToHtml, htmlToMd } = createTestMarkupConverters();
|
|
|
|
|
|
|
|
// All images in the resource directory should be preserved.
|
|
|
|
const html = `<img src="file://${encodeURI(Setting.value('resourceDir'))}/resource.png" alt="test"/>`;
|
|
|
|
expect(await processPastedHtml(html, htmlToMd, markupToHtml)).toBe(html);
|
|
|
|
});
|
2023-07-27 16:41:57 +02:00
|
|
|
});
|