import Setting from '@joplin/lib/models/Setting';
import { processImagesInPastedHtml, processPastedHtml } from './resourceHandling';
import markupLanguageUtils from '@joplin/lib/markupLanguageUtils';
import HtmlToMd from '@joplin/lib/HtmlToMd';
import { HtmlToMarkdownHandler, MarkupToHtmlHandler } from './types';
import { setupDatabaseAndSynchronizer, switchClient } from '@joplin/lib/testing/test-utils';
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 };
};
describe('resourceHandling', () => {
it('should sanitize pasted HTML', async () => {
Setting.setConstant('resourceDir', '/home/.config/joplin/resources');
const testCases = [
['Test: ', 'Test: '],
['test', 'test'],
['test', 'test'],
['evil.pdf', 'evil.pdf'],
['', ''],
['', ''],
[
'',
'
',
],
];
for (const [html, expected] of testCases) {
expect(await processPastedHtml(html, null, null)).toBe(expected);
}
});
it('should clean up pasted HTML', async () => {
const { markupToHtml, htmlToMd } = createTestMarkupConverters();
const testCases = [
['
Hello
', 'Hello
\nWorld
\n'], ['', ''], ]; for (const [html, expected] of testCases) { expect(await processPastedHtml(html, htmlToMd, markupToHtml)).toBe(expected); } }); 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 = `
`;
expect(await processPastedHtml(html, htmlToMd, markupToHtml)).toBe(html);
});
it('should normalize HTML-encoded newlines in image alt attributes', async () => {
// Word encodes newlines in alt text as
HTML entities. These must be
// normalized to spaces before Turndown processes the HTML, otherwise
// node.outerHTML (returned verbatim for images with width/height) embeds
// literal newlines that break Markdown raw HTML block parsing.
const resourceSrc = `file://${encodeURI(Setting.value('resourceDir'))}/resource.png`;
const testCases: [string, string][] = [
// HTML entity newlines (Word clipboard format:
= LF)
[
`