2025-07-30 02:52:57 -07:00
|
|
|
import '../../utils/polyfills';
|
2025-07-29 12:25:43 -07:00
|
|
|
import { createEditor } from '@joplin/editor/ProseMirror';
|
2025-07-30 02:52:57 -07:00
|
|
|
import { EditorProcessApi, EditorProps, MainProcessApi } from '../types';
|
|
|
|
|
import WebViewToRNMessenger from '../../../utils/ipc/WebViewToRNMessenger';
|
|
|
|
|
import { MarkupLanguage } from '@joplin/renderer/types';
|
2025-07-29 12:25:43 -07:00
|
|
|
import '@joplin/editor/ProseMirror/styles';
|
2025-07-30 02:52:57 -07:00
|
|
|
import readFileToBase64 from '../../utils/readFileToBase64';
|
2025-07-29 12:25:43 -07:00
|
|
|
import { EditorLanguageType } from '@joplin/editor/types';
|
2025-07-30 02:52:57 -07:00
|
|
|
import convertHtmlToMarkdown from './convertHtmlToMarkdown';
|
2025-08-19 23:29:30 -07:00
|
|
|
import { ExportedWebViewGlobals as MarkdownEditorWebViewGlobals } from '../../markdownEditorBundle/types';
|
|
|
|
|
import { EditorEventType } from '@joplin/editor/events';
|
2025-07-29 12:25:43 -07:00
|
|
|
|
|
|
|
|
const wrapHtmlForMarkdownConversion = (html: HTMLElement) => {
|
|
|
|
|
// Add a container element -- when converting to HTML, Turndown
|
|
|
|
|
// sometimes doesn't process the toplevel element in the same way
|
|
|
|
|
// as other elements (e.g. in the case of Joplin source blocks).
|
|
|
|
|
const wrapper = html.ownerDocument.createElement('div');
|
|
|
|
|
wrapper.appendChild(html.cloneNode(true));
|
|
|
|
|
return wrapper;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const htmlToMarkdown = (html: HTMLElement): string => {
|
2025-07-30 02:52:57 -07:00
|
|
|
return convertHtmlToMarkdown(html);
|
2025-07-29 12:25:43 -07:00
|
|
|
};
|
|
|
|
|
|
2025-08-19 23:29:30 -07:00
|
|
|
export const initialize = async (
|
|
|
|
|
{
|
|
|
|
|
settings,
|
|
|
|
|
initialText,
|
|
|
|
|
initialNoteId,
|
|
|
|
|
parentElementClassName,
|
|
|
|
|
initialSearch,
|
|
|
|
|
}: EditorProps,
|
|
|
|
|
markdownEditorApi: MarkdownEditorWebViewGlobals,
|
|
|
|
|
) => {
|
2025-07-29 12:25:43 -07:00
|
|
|
const messenger = new WebViewToRNMessenger<EditorProcessApi, MainProcessApi>('rich-text-editor', null);
|
|
|
|
|
const parentElement = document.getElementsByClassName(parentElementClassName)[0];
|
|
|
|
|
if (!parentElement) throw new Error('Parent element not found');
|
|
|
|
|
if (!(parentElement instanceof HTMLElement)) {
|
|
|
|
|
throw new Error('Parent node is not an element.');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const assetContainer = document.createElement('div');
|
|
|
|
|
assetContainer.id = 'joplin-container-pluginAssetsContainer';
|
|
|
|
|
document.body.appendChild(assetContainer);
|
|
|
|
|
|
|
|
|
|
const editor = await createEditor(parentElement, {
|
|
|
|
|
settings,
|
|
|
|
|
initialText,
|
|
|
|
|
initialNoteId,
|
2025-08-07 02:18:09 -07:00
|
|
|
onLocalize: messenger.remoteApi.onLocalize,
|
2025-07-29 12:25:43 -07:00
|
|
|
|
|
|
|
|
onPasteFile: async (data) => {
|
|
|
|
|
const base64 = await readFileToBase64(data);
|
|
|
|
|
await messenger.remoteApi.onPasteFile(data.type, base64);
|
|
|
|
|
},
|
|
|
|
|
onLogMessage: (message: string) => {
|
|
|
|
|
void messenger.remoteApi.logMessage(message);
|
|
|
|
|
},
|
|
|
|
|
onEvent: (event) => {
|
|
|
|
|
void messenger.remoteApi.onEditorEvent(event);
|
|
|
|
|
},
|
|
|
|
|
}, {
|
2025-08-07 02:18:09 -07:00
|
|
|
renderMarkupToHtml: async (markup, options) => {
|
|
|
|
|
let language = MarkupLanguage.Markdown;
|
|
|
|
|
if (settings.language === EditorLanguageType.Html && !options.forceMarkdown) {
|
|
|
|
|
language = MarkupLanguage.Html;
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-29 12:25:43 -07:00
|
|
|
return await messenger.remoteApi.onRender({
|
|
|
|
|
markup,
|
2025-08-07 02:18:09 -07:00
|
|
|
language,
|
2025-07-29 12:25:43 -07:00
|
|
|
}, {
|
|
|
|
|
pluginAssetContainerSelector: `#${assetContainer.id}`,
|
|
|
|
|
splitted: true,
|
|
|
|
|
mapsToLine: true,
|
2025-08-07 02:18:09 -07:00
|
|
|
removeUnusedPluginAssets: options.isFullPageRender,
|
2025-07-29 12:25:43 -07:00
|
|
|
});
|
|
|
|
|
},
|
2025-08-26 00:46:00 -07:00
|
|
|
renderHtmlToMarkup: (html) => {
|
2025-07-29 12:25:43 -07:00
|
|
|
if (settings.language === EditorLanguageType.Markdown) {
|
|
|
|
|
return htmlToMarkdown(wrapHtmlForMarkdownConversion(html));
|
|
|
|
|
} else {
|
2025-08-26 00:46:00 -07:00
|
|
|
return html.outerHTML;
|
2025-07-29 12:25:43 -07:00
|
|
|
}
|
|
|
|
|
},
|
2025-08-19 23:29:30 -07:00
|
|
|
}, (parent, language, onChange) => {
|
|
|
|
|
return markdownEditorApi.createEditorWithParent({
|
|
|
|
|
initialText: '',
|
|
|
|
|
initialNoteId: '',
|
|
|
|
|
parentElementOrClassName: parent,
|
|
|
|
|
settings: { ...editor.getSettings(), language },
|
|
|
|
|
onEvent: (event) => {
|
|
|
|
|
if (event.kind === EditorEventType.Change) {
|
|
|
|
|
onChange(event.value);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
});
|
2025-07-29 12:25:43 -07:00
|
|
|
});
|
2025-09-30 09:22:55 -07:00
|
|
|
editor.setSearchState(initialSearch, 'initialSearch');
|
2025-07-29 12:25:43 -07:00
|
|
|
|
|
|
|
|
messenger.setLocalInterface({
|
|
|
|
|
editor,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return editor;
|
|
|
|
|
};
|
|
|
|
|
|
2025-07-30 02:52:57 -07:00
|
|
|
export { default as setUpLogger } from '../../utils/setUpLogger';
|
2025-07-29 12:25:43 -07:00
|
|
|
|