1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-03-26 21:12:59 +02:00

Desktop: Use plugins whenever printing or exporting notes

Ref: https://discourse.joplinapp.org/t/external-css-per-note-is-being-ignored/13016/6
This commit is contained in:
Laurent Cozic 2020-12-19 17:42:18 +00:00
parent b8493baa5e
commit d1a7d31335
14 changed files with 29 additions and 14 deletions

@ -4,6 +4,7 @@ import shim from '@joplin/lib/shim';
import { ExportOptions, FileSystemItem, Module } from '@joplin/lib/services/interop/types'; import { ExportOptions, FileSystemItem, Module } from '@joplin/lib/services/interop/types';
import { _ } from '@joplin/lib/locale'; import { _ } from '@joplin/lib/locale';
import { PluginStates } from '@joplin/lib/services/plugins/reducer';
const bridge = require('electron').remote.require('./bridge').default; const bridge = require('electron').remote.require('./bridge').default;
const Setting = require('@joplin/lib/models/Setting').default; const Setting = require('@joplin/lib/models/Setting').default;
const Note = require('@joplin/lib/models/Note.js'); const Note = require('@joplin/lib/models/Note.js');
@ -20,6 +21,7 @@ interface ExportNoteOptions {
pageSize?: string; pageSize?: string;
landscape?: boolean; landscape?: boolean;
includeConflicts?: boolean; includeConflicts?: boolean;
plugins?: PluginStates;
} }
export default class InteropServiceHelper { export default class InteropServiceHelper {
@ -54,6 +56,7 @@ export default class InteropServiceHelper {
try { try {
const exportOptions = { const exportOptions = {
customCss: options.customCss ? options.customCss : '', customCss: options.customCss ? options.customCss : '',
plugins: options.plugins,
}; };
htmlFile = await this.exportNoteToHtmlFile(noteId, exportOptions); htmlFile = await this.exportNoteToHtmlFile(noteId, exportOptions);
@ -162,6 +165,7 @@ export default class InteropServiceHelper {
exportOptions.path = path; exportOptions.path = path;
exportOptions.format = module.format; exportOptions.format = module.format;
// exportOptions.modulePath = module.path; // exportOptions.modulePath = module.path;
if (options.plugins) exportOptions.plugins = options.plugins;
exportOptions.target = module.target; exportOptions.target = module.target;
exportOptions.includeConflicts = !!options.includeConflicts; exportOptions.includeConflicts = !!options.includeConflicts;
if (options.sourceFolderIds) exportOptions.sourceFolderIds = options.sourceFolderIds; if (options.sourceFolderIds) exportOptions.sourceFolderIds = options.sourceFolderIds;

@ -373,6 +373,7 @@ class MainScreenComponent extends React.Component<Props, State> {
pageSize: Setting.value('export.pdfPageSize'), pageSize: Setting.value('export.pdfPageSize'),
landscape: Setting.value('export.pdfPageOrientation') === 'landscape', landscape: Setting.value('export.pdfPageOrientation') === 'landscape',
customCss: this.props.customCss, customCss: this.props.customCss,
plugins: this.props.plugins,
}); });
await shim.fsDriver().writeFile(options.path, pdfData, 'buffer'); await shim.fsDriver().writeFile(options.path, pdfData, 'buffer');
} catch (error) { } catch (error) {

@ -88,6 +88,7 @@ interface Props {
pluginMenus: any[]; pluginMenus: any[];
['spellChecker.enabled']: boolean; ['spellChecker.enabled']: boolean;
['spellChecker.language']: string; ['spellChecker.language']: string;
plugins: PluginStates;
} }
const commandNames: string[] = menuCommandNames(); const commandNames: string[] = menuCommandNames();
@ -233,7 +234,11 @@ function useMenu(props: Props) {
exportItems.push({ exportItems.push({
label: module.fullLabel(), label: module.fullLabel(),
click: async () => { click: async () => {
await InteropServiceHelper.export((action: any) => props.dispatch(action), module); await InteropServiceHelper.export(
(action: any) => props.dispatch(action),
module,
{ plugins: props.plugins }
);
}, },
}); });
} }
@ -471,7 +476,7 @@ function useMenu(props: Props) {
label: _('Import'), label: _('Import'),
submenu: importItems, submenu: importItems,
}, { }, {
label: _('Export'), label: _('Export all'),
submenu: exportItems, submenu: exportItems,
}, { }, {
type: 'separator', type: 'separator',
@ -750,7 +755,7 @@ function useMenu(props: Props) {
} else { } else {
setMenu(Menu.buildFromTemplate(template)); setMenu(Menu.buildFromTemplate(template));
} }
}, [props.routeName, props.pluginMenuItems, props.pluginMenus, keymapLastChangeTime, modulesLastChangeTime, props['spellChecker.language'], props['spellChecker.enabled']]); }, [props.routeName, props.pluginMenuItems, props.pluginMenus, keymapLastChangeTime, modulesLastChangeTime, props['spellChecker.language'], props['spellChecker.enabled'], props.plugins]);
useEffect(() => { useEffect(() => {
const whenClauseContext = CommandService.instance().currentWhenClauseContext(); const whenClauseContext = CommandService.instance().currentWhenClauseContext();
@ -847,6 +852,7 @@ const mapStateToProps = (state: AppState) => {
pluginMenus: stateUtils.selectArrayShallow({ array: pluginUtils.viewsByType(state.pluginService.plugins, 'menu') }, 'menuBar.pluginMenus'), pluginMenus: stateUtils.selectArrayShallow({ array: pluginUtils.viewsByType(state.pluginService.plugins, 'menu') }, 'menuBar.pluginMenus'),
['spellChecker.language']: state.settings['spellChecker.language'], ['spellChecker.language']: state.settings['spellChecker.language'],
['spellChecker.enabled']: state.settings['spellChecker.enabled'], ['spellChecker.enabled']: state.settings['spellChecker.enabled'],
plugins: state.pluginService.plugins,
}; };
}; };

@ -24,7 +24,7 @@ interface KeyToLabelMap {
let markupToHtml_: any = null; let markupToHtml_: any = null;
function markupToHtml() { function markupToHtml() {
if (markupToHtml_) return markupToHtml_; if (markupToHtml_) return markupToHtml_;
markupToHtml_ = markupLanguageUtils.newMarkupToHtml(); markupToHtml_ = markupLanguageUtils.newMarkupToHtml({});
return markupToHtml_; return markupToHtml_;
} }

@ -154,7 +154,7 @@ function NoteEditor(props: NoteEditorProps) {
const allAssets = useCallback(async (markupLanguage: number): Promise<any[]> => { const allAssets = useCallback(async (markupLanguage: number): Promise<any[]> => {
const theme = themeStyle(props.themeId); const theme = themeStyle(props.themeId);
const markupToHtml = markupLanguageUtils.newMarkupToHtml({ const markupToHtml = markupLanguageUtils.newMarkupToHtml({}, {
resourceBaseUrl: `file://${Setting.value('resourceDir')}/`, resourceBaseUrl: `file://${Setting.value('resourceDir')}/`,
}); });

@ -1,5 +1,4 @@
import { PluginStates } from '@joplin/lib/services/plugins/reducer'; import { PluginStates } from '@joplin/lib/services/plugins/reducer';
import { contentScriptsToRendererRules } from '@joplin/lib/services/plugins/utils/loadContentScripts';
import { useCallback, useMemo } from 'react'; import { useCallback, useMemo } from 'react';
import { ResourceInfos } from './types'; import { ResourceInfos } from './types';
import markupLanguageUtils from '@joplin/lib/markupLanguageUtils'; import markupLanguageUtils from '@joplin/lib/markupLanguageUtils';
@ -23,9 +22,8 @@ export default function useMarkupToHtml(deps: HookDependencies) {
const { themeId, customCss, plugins } = deps; const { themeId, customCss, plugins } = deps;
const markupToHtml = useMemo(() => { const markupToHtml = useMemo(() => {
return markupLanguageUtils.newMarkupToHtml({ return markupLanguageUtils.newMarkupToHtml(deps.plugins, {
resourceBaseUrl: `file://${Setting.value('resourceDir')}/`, resourceBaseUrl: `file://${Setting.value('resourceDir')}/`,
extraRendererRules: contentScriptsToRendererRules(plugins),
}); });
}, [plugins]); }, [plugins]);

@ -116,7 +116,7 @@ class NoteRevisionViewerComponent extends React.PureComponent {
const theme = themeStyle(this.props.themeId); const theme = themeStyle(this.props.themeId);
const markupToHtml = markupLanguageUtils.newMarkupToHtml({ const markupToHtml = markupLanguageUtils.newMarkupToHtml({}, {
resourceBaseUrl: `file://${Setting.value('resourceDir')}/`, resourceBaseUrl: `file://${Setting.value('resourceDir')}/`,
}); });

@ -288,7 +288,7 @@ class SideBarComponent extends React.Component<Props, State> {
new MenuItem({ new MenuItem({
label: module.fullLabel(), label: module.fullLabel(),
click: async () => { click: async () => {
await InteropServiceHelper.export(this.props.dispatch.bind(this), module, { sourceFolderIds: [itemId] }); await InteropServiceHelper.export(this.props.dispatch.bind(this), module, { sourceFolderIds: [itemId], plugins: this.pluginsRef.current });
}, },
}) })
); );

@ -153,6 +153,7 @@ export default class NoteListUtils {
await InteropServiceHelper.export(props.dispatch.bind(this), module, { await InteropServiceHelper.export(props.dispatch.bind(this), module, {
sourceNoteIds: noteIds, sourceNoteIds: noteIds,
includeConflicts: props.inConflictFolder, includeConflicts: props.inConflictFolder,
plugins: props.plugins,
}); });
}, },
}) })

@ -248,7 +248,7 @@ class Dialog extends React.PureComponent<Props, State> {
markupToHtml() { markupToHtml() {
if (this.markupToHtml_) return this.markupToHtml_; if (this.markupToHtml_) return this.markupToHtml_;
this.markupToHtml_ = markupLanguageUtils.newMarkupToHtml(); this.markupToHtml_ = markupLanguageUtils.newMarkupToHtml({});
return this.markupToHtml_; return this.markupToHtml_;
} }

@ -38,7 +38,7 @@ export default function useSource(noteBody: string, noteMarkupLanguage: number,
}, [themeId, paddingBottom]); }, [themeId, paddingBottom]);
const markupToHtml = useMemo(() => { const markupToHtml = useMemo(() => {
return markupLanguageUtils.newMarkupToHtml(); return markupLanguageUtils.newMarkupToHtml({});
}, [isFirstRender]); }, [isFirstRender]);
// To address https://github.com/laurent22/joplin/issues/433 // To address https://github.com/laurent22/joplin/issues/433

@ -2,6 +2,8 @@ import markdownUtils from './markdownUtils';
import Setting from './models/Setting'; import Setting from './models/Setting';
import shim from './shim'; import shim from './shim';
import MarkupToHtml, { MarkupLanguage } from '@joplin/renderer/MarkupToHtml'; import MarkupToHtml, { MarkupLanguage } from '@joplin/renderer/MarkupToHtml';
import { PluginStates } from './services/plugins/reducer';
import { contentScriptsToRendererRules } from './services/plugins/utils/loadContentScripts';
const htmlUtils = require('./htmlUtils'); const htmlUtils = require('./htmlUtils');
const Resource = require('./models/Resource'); const Resource = require('./models/Resource');
@ -19,7 +21,7 @@ class MarkupLanguageUtils {
// Create a new MarkupToHtml instance while injecting options specific to Joplin // Create a new MarkupToHtml instance while injecting options specific to Joplin
// desktop and mobile applications. // desktop and mobile applications.
newMarkupToHtml(options: any = null) { newMarkupToHtml(plugins: PluginStates, options: any = null) {
const subValues = Setting.subValues('markdown.plugin', Setting.toPlainObject()); const subValues = Setting.subValues('markdown.plugin', Setting.toPlainObject());
const pluginOptions: any = {}; const pluginOptions: any = {};
for (const n in subValues) { for (const n in subValues) {
@ -31,6 +33,7 @@ class MarkupLanguageUtils {
pluginOptions: pluginOptions, pluginOptions: pluginOptions,
tempDir: Setting.value('tempDir'), tempDir: Setting.value('tempDir'),
fsDriver: shim.fsDriver(), fsDriver: shim.fsDriver(),
extraRendererRules: contentScriptsToRendererRules(plugins),
}, options); }, options);
return new MarkupToHtml(options); return new MarkupToHtml(options);

@ -28,7 +28,7 @@ export default class InteropService_Exporter_Html extends InteropService_Exporte
this.resourceDir_ = this.destDir_ ? `${this.destDir_}/_resources` : null; this.resourceDir_ = this.destDir_ ? `${this.destDir_}/_resources` : null;
await shim.fsDriver().mkdir(this.destDir_); await shim.fsDriver().mkdir(this.destDir_);
this.markupToHtml_ = markupLanguageUtils.newMarkupToHtml(); this.markupToHtml_ = markupLanguageUtils.newMarkupToHtml(options.plugins);
this.resources_ = []; this.resources_ = [];
this.style_ = themeStyle(Setting.THEME_LIGHT); this.style_ = themeStyle(Setting.THEME_LIGHT);
} }

@ -1,4 +1,5 @@
import { _ } from '../../locale'; import { _ } from '../../locale';
import { PluginStates } from '../plugins/reducer';
export interface CustomImportContext { export interface CustomImportContext {
sourcePath: string; sourcePath: string;
@ -94,6 +95,7 @@ export interface ExportOptions {
// modulePath?: string; // modulePath?: string;
target?: FileSystemItem; target?: FileSystemItem;
includeConflicts?: boolean; includeConflicts?: boolean;
plugins?: PluginStates;
} }
export interface ImportExportResult { export interface ImportExportResult {