mirror of
https://github.com/laurent22/joplin.git
synced 2025-01-23 18:53:36 +02:00
Desktop: Fixes #4452: Fixed exporting as HTML or PDF when a plugin is active, and make sure plugin assets are also exported
This commit is contained in:
parent
127a28e9b0
commit
bd5e3d363c
@ -139,6 +139,9 @@ packages/app-cli/tests/services_CommandService.js.map
|
|||||||
packages/app-cli/tests/services_InteropService.d.ts
|
packages/app-cli/tests/services_InteropService.d.ts
|
||||||
packages/app-cli/tests/services_InteropService.js
|
packages/app-cli/tests/services_InteropService.js
|
||||||
packages/app-cli/tests/services_InteropService.js.map
|
packages/app-cli/tests/services_InteropService.js.map
|
||||||
|
packages/app-cli/tests/services_InteropService_Exporter_Html.d.ts
|
||||||
|
packages/app-cli/tests/services_InteropService_Exporter_Html.js
|
||||||
|
packages/app-cli/tests/services_InteropService_Exporter_Html.js.map
|
||||||
packages/app-cli/tests/services_PluginService.d.ts
|
packages/app-cli/tests/services_PluginService.d.ts
|
||||||
packages/app-cli/tests/services_PluginService.js
|
packages/app-cli/tests/services_PluginService.js
|
||||||
packages/app-cli/tests/services_PluginService.js.map
|
packages/app-cli/tests/services_PluginService.js.map
|
||||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -126,6 +126,9 @@ packages/app-cli/tests/services_CommandService.js.map
|
|||||||
packages/app-cli/tests/services_InteropService.d.ts
|
packages/app-cli/tests/services_InteropService.d.ts
|
||||||
packages/app-cli/tests/services_InteropService.js
|
packages/app-cli/tests/services_InteropService.js
|
||||||
packages/app-cli/tests/services_InteropService.js.map
|
packages/app-cli/tests/services_InteropService.js.map
|
||||||
|
packages/app-cli/tests/services_InteropService_Exporter_Html.d.ts
|
||||||
|
packages/app-cli/tests/services_InteropService_Exporter_Html.js
|
||||||
|
packages/app-cli/tests/services_InteropService_Exporter_Html.js.map
|
||||||
packages/app-cli/tests/services_PluginService.d.ts
|
packages/app-cli/tests/services_PluginService.d.ts
|
||||||
packages/app-cli/tests/services_PluginService.js
|
packages/app-cli/tests/services_PluginService.js
|
||||||
packages/app-cli/tests/services_PluginService.js.map
|
packages/app-cli/tests/services_PluginService.js.map
|
||||||
|
@ -37,6 +37,7 @@ module.exports = {
|
|||||||
'<rootDir>/tests/test-utils-synchronizer.js',
|
'<rootDir>/tests/test-utils-synchronizer.js',
|
||||||
'<rootDir>/tests/file_api_driver.js',
|
'<rootDir>/tests/file_api_driver.js',
|
||||||
'<rootDir>/tests/tmp/',
|
'<rootDir>/tests/tmp/',
|
||||||
|
'<rootDir>/tests/test data/',
|
||||||
],
|
],
|
||||||
|
|
||||||
// To avoid this warning:
|
// To avoid this warning:
|
||||||
|
@ -0,0 +1,98 @@
|
|||||||
|
import InteropService from '@joplin/lib/services/interop/InteropService';
|
||||||
|
import { PluginStates } from '@joplin/lib/services/plugins/reducer';
|
||||||
|
import { setupDatabaseAndSynchronizer, switchClient, exportDir } from './test-utils';
|
||||||
|
import Folder from '@joplin/lib/models/Folder';
|
||||||
|
import Note from '@joplin/lib/models/Note';
|
||||||
|
import * as fs from 'fs-extra';
|
||||||
|
import { tempFilePath } from './test-utils';
|
||||||
|
import { ContentScriptType } from '@joplin/lib/services/plugins/api/types';
|
||||||
|
|
||||||
|
async function recreateExportDir() {
|
||||||
|
const dir = exportDir();
|
||||||
|
await fs.remove(dir);
|
||||||
|
await fs.mkdirp(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('services_InteropService_Exporter_Html', function() {
|
||||||
|
|
||||||
|
beforeEach(async (done) => {
|
||||||
|
await setupDatabaseAndSynchronizer(1);
|
||||||
|
await switchClient(1);
|
||||||
|
await recreateExportDir();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should export HTML file', (async () => {
|
||||||
|
const service = InteropService.instance();
|
||||||
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
|
await Note.save({ body: '**ma note**', parent_id: folder1.id });
|
||||||
|
const filePath = `${exportDir()}/test.html`;
|
||||||
|
|
||||||
|
await service.export({
|
||||||
|
path: filePath,
|
||||||
|
format: 'html',
|
||||||
|
});
|
||||||
|
|
||||||
|
const content = await fs.readFile(filePath, 'utf8');
|
||||||
|
expect(content).toContain('<strong>ma note</strong>');
|
||||||
|
}));
|
||||||
|
|
||||||
|
test('should export plugin assets', (async () => {
|
||||||
|
const service = InteropService.instance();
|
||||||
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
|
await Note.save({ body: '**ma note**', parent_id: folder1.id });
|
||||||
|
const filePath = `${exportDir()}/test.html`;
|
||||||
|
|
||||||
|
const contentScriptPath = tempFilePath('js');
|
||||||
|
|
||||||
|
await fs.writeFile(contentScriptPath, `module.exports = {
|
||||||
|
default: function(_context) {
|
||||||
|
return {
|
||||||
|
plugin: function (markdownIt, _options) {
|
||||||
|
|
||||||
|
},
|
||||||
|
assets: function() {
|
||||||
|
return [
|
||||||
|
{ name: 'fence.css' }
|
||||||
|
];
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}`);
|
||||||
|
|
||||||
|
const assetPath = `${require('path').dirname(contentScriptPath)}/fence.css`;
|
||||||
|
const fenceContent = 'strong { color: red; }';
|
||||||
|
await fs.writeFile(assetPath, fenceContent);
|
||||||
|
|
||||||
|
const plugins: PluginStates = {
|
||||||
|
'test': {
|
||||||
|
id: 'test',
|
||||||
|
contentScripts: {
|
||||||
|
[ContentScriptType.MarkdownItPlugin]: [
|
||||||
|
{
|
||||||
|
id: 'mdContentScript',
|
||||||
|
path: contentScriptPath,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
views: {},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
await service.export({
|
||||||
|
path: filePath,
|
||||||
|
format: 'html',
|
||||||
|
plugins,
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const fenceRelativePath = 'pluginAssets/mdContentScript/fence.css';
|
||||||
|
|
||||||
|
const content = await fs.readFile(filePath, 'utf8');
|
||||||
|
expect(content).toContain(fenceRelativePath);
|
||||||
|
|
||||||
|
const readFenceContent = await fs.readFile(`${exportDir()}/${fenceRelativePath}`, 'utf8');
|
||||||
|
expect(readFenceContent).toBe(fenceContent);
|
||||||
|
}));
|
||||||
|
|
||||||
|
});
|
@ -117,7 +117,7 @@ export default class InteropService_Exporter_Html extends InteropService_Exporte
|
|||||||
// The source path is a bit hard-coded but shouldn't change.
|
// The source path is a bit hard-coded but shouldn't change.
|
||||||
for (let i = 0; i < result.pluginAssets.length; i++) {
|
for (let i = 0; i < result.pluginAssets.length; i++) {
|
||||||
const asset = result.pluginAssets[i];
|
const asset = result.pluginAssets[i];
|
||||||
const filePath = `${libRootPath}/node_modules/@joplin/renderer/assets/${asset.name}`;
|
const filePath = asset.pathIsAbsolute ? asset.path : `${libRootPath}/node_modules/@joplin/renderer/assets/${asset.name}`;
|
||||||
const destPath = `${dirname(noteFilePath)}/pluginAssets/${asset.name}`;
|
const destPath = `${dirname(noteFilePath)}/pluginAssets/${asset.name}`;
|
||||||
await shim.fsDriver().mkdir(dirname(destPath));
|
await shim.fsDriver().mkdir(dirname(destPath));
|
||||||
await shim.fsDriver().copy(filePath, destPath);
|
await shim.fsDriver().copy(filePath, destPath);
|
||||||
|
@ -10,8 +10,15 @@ export enum MarkupLanguage {
|
|||||||
|
|
||||||
export interface RenderResultPluginAsset {
|
export interface RenderResultPluginAsset {
|
||||||
name: string;
|
name: string;
|
||||||
path: string;
|
|
||||||
mime: string;
|
mime: string;
|
||||||
|
path: string;
|
||||||
|
|
||||||
|
// For built-in Mardown-it plugins, the asset path is relative (and can be
|
||||||
|
// found inside the @joplin/renderer package), while for external plugins
|
||||||
|
// (content scripts), the path is absolute. We use this property to tell if
|
||||||
|
// it's relative or absolute, as that will inform how it's loaded in various
|
||||||
|
// places.
|
||||||
|
pathIsAbsolute: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RenderResult {
|
export interface RenderResult {
|
||||||
|
@ -14,6 +14,7 @@ interface RendererRule {
|
|||||||
assets?(theme: any): any;
|
assets?(theme: any): any;
|
||||||
plugin?: any;
|
plugin?: any;
|
||||||
assetPath?: string;
|
assetPath?: string;
|
||||||
|
assetPathIsAbsolute?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RendererRules {
|
interface RendererRules {
|
||||||
@ -231,6 +232,7 @@ export default class MdToHtml {
|
|||||||
this.extraRendererRules_[id] = {
|
this.extraRendererRules_[id] = {
|
||||||
...module,
|
...module,
|
||||||
assetPath,
|
assetPath,
|
||||||
|
assetPathIsAbsolute: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,6 +284,7 @@ export default class MdToHtml {
|
|||||||
files.push(Object.assign({}, asset, {
|
files.push(Object.assign({}, asset, {
|
||||||
name: name,
|
name: name,
|
||||||
path: assetPath,
|
path: assetPath,
|
||||||
|
pathIsAbsolute: !!rule && !!rule.assetPathIsAbsolute,
|
||||||
mime: mime,
|
mime: mime,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user