Commit 866b7a96 authored by Denys Mishunov's avatar Denys Mishunov

Refactoring the markdown extension

parent 7c9516fb
...@@ -30,5 +30,6 @@ export const EDITOR_DIFF_INSTANCE_FN = 'createDiffInstance'; ...@@ -30,5 +30,6 @@ export const EDITOR_DIFF_INSTANCE_FN = 'createDiffInstance';
export const EXTENSION_CI_SCHEMA_FILE_NAME_MATCH = '.gitlab-ci.yml'; export const EXTENSION_CI_SCHEMA_FILE_NAME_MATCH = '.gitlab-ci.yml';
export const EXTENSION_MARKDOWN_PREVIEW_PANEL_CLASS = 'md'; export const EXTENSION_MARKDOWN_PREVIEW_PANEL_CLASS = 'md';
export const EXTENSION_MARKDOWN_PREVIEW_PANEL_PARENT_CLASS = 'source-editor-preview';
export const EXTENSION_MARKDOWN_PREVIEW_ACTION_ID = 'markdown-preview'; export const EXTENSION_MARKDOWN_PREVIEW_ACTION_ID = 'markdown-preview';
export const EXTENSION_MARKDOWN_PREVIEW_PANEL_WIDTH = 0.5; // 50% of the width export const EXTENSION_MARKDOWN_PREVIEW_PANEL_WIDTH = 0.5; // 50% of the width
...@@ -9,6 +9,7 @@ import { ...@@ -9,6 +9,7 @@ import {
EXTENSION_MARKDOWN_PREVIEW_PANEL_CLASS, EXTENSION_MARKDOWN_PREVIEW_PANEL_CLASS,
EXTENSION_MARKDOWN_PREVIEW_ACTION_ID, EXTENSION_MARKDOWN_PREVIEW_ACTION_ID,
EXTENSION_MARKDOWN_PREVIEW_PANEL_WIDTH, EXTENSION_MARKDOWN_PREVIEW_PANEL_WIDTH,
EXTENSION_MARKDOWN_PREVIEW_PANEL_PARENT_CLASS,
} from '../constants'; } from '../constants';
import { SourceEditorExtension } from './source_editor_extension_base'; import { SourceEditorExtension } from './source_editor_extension_base';
...@@ -30,63 +31,76 @@ const getPreview = (text, projectPath = '') => { ...@@ -30,63 +31,76 @@ const getPreview = (text, projectPath = '') => {
}); });
}; };
export class EditorMarkdownExtension extends SourceEditorExtension { const setupDomElement = ({ injectToEl = null } = {}) => {
constructor({ instance, ...args } = {}) { const previewEl = document.createElement('div');
super({ instance, ...args }); previewEl.classList.add(EXTENSION_MARKDOWN_PREVIEW_PANEL_CLASS);
EditorMarkdownExtension.setupLivePreview(instance); previewEl.style.display = 'none';
if (injectToEl) {
injectToEl.appendChild(previewEl);
} }
return previewEl;
};
static setupPanelElement(injectToEl = null) { export class EditorMarkdownExtension extends SourceEditorExtension {
const previewEl = document.createElement('div'); constructor({ instance, projectPath, ...args } = {}) {
previewEl.classList.add(EXTENSION_MARKDOWN_PREVIEW_PANEL_CLASS); super({ instance, ...args });
previewEl.style.display = 'none'; Object.assign(instance, {
if (injectToEl) { projectPath,
injectToEl.appendChild(previewEl); preview: {
} el: undefined,
return previewEl; action: undefined,
shown: false,
},
});
this.setupPreviewAction.call(instance);
} }
static togglePreviewLayout(editor) { static togglePreviewLayout() {
const currentLayout = editor.getLayoutInfo(); const { width, height } = this.getLayoutInfo();
const width = editor.preview const newWidth = this.preview.shown
? currentLayout.width / EXTENSION_MARKDOWN_PREVIEW_PANEL_WIDTH ? width / EXTENSION_MARKDOWN_PREVIEW_PANEL_WIDTH
: currentLayout.width * EXTENSION_MARKDOWN_PREVIEW_PANEL_WIDTH; : width * EXTENSION_MARKDOWN_PREVIEW_PANEL_WIDTH;
editor.layout({ width, height: currentLayout.height }); this.layout({ width: newWidth, height });
} }
static togglePreviewPanel(editor) { static togglePreviewPanel() {
const parentEl = editor.getDomNode().parentElement; const parentEl = this.getDomNode().parentElement;
const { previewEl } = editor; const { el: previewEl } = this.preview;
parentEl.classList.toggle('source-editor-preview'); parentEl.classList.toggle(EXTENSION_MARKDOWN_PREVIEW_PANEL_PARENT_CLASS);
if (previewEl.style.display === 'none') { if (previewEl.style.display === 'none') {
// Show the preview panel // Show the preview panel
const fetchPreview = () => { this.fetchPreview();
getPreview(editor.getValue(), editor.projectPath)
.then((data) => {
previewEl.innerHTML = sanitize(data);
syntaxHighlight(previewEl.querySelectorAll('.js-syntax-highlight'));
previewEl.style.display = 'block';
})
.catch(() => createFlash(BLOB_PREVIEW_ERROR));
};
fetchPreview();
Object.assign(editor, {
modelChangeListener: editor.onDidChangeModelContent(
debounce(fetchPreview.bind(editor), 250),
),
});
} else { } else {
// Hide the preview panel // Hide the preview panel
previewEl.style.display = 'none'; previewEl.style.display = 'none';
editor.modelChangeListener.dispose();
} }
} }
static setupLivePreview(instance) { cleanup() {
if (!instance || instance.getAction(EXTENSION_MARKDOWN_PREVIEW_ACTION_ID)) return; this.preview.action.dispose();
if (this.preview.shown) {
EditorMarkdownExtension.togglePreviewPanel.call(this);
EditorMarkdownExtension.togglePreviewLayout.call(this);
}
this.preview.shown = false;
}
fetchPreview() {
const { el: previewEl } = this.preview;
getPreview(this.getValue(), this.projectPath)
.then((data) => {
previewEl.innerHTML = sanitize(data);
syntaxHighlight(previewEl.querySelectorAll('.js-syntax-highlight'));
previewEl.style.display = 'block';
})
.catch(() => createFlash(BLOB_PREVIEW_ERROR));
}
setupPreviewAction() {
if (this.getAction(EXTENSION_MARKDOWN_PREVIEW_ACTION_ID)) return;
instance.addAction({ this.preview.action = this.addAction({
id: EXTENSION_MARKDOWN_PREVIEW_ACTION_ID, id: EXTENSION_MARKDOWN_PREVIEW_ACTION_ID,
label: __('Preview Markdown'), label: __('Preview Markdown'),
keybindings: [ keybindings: [
...@@ -98,19 +112,36 @@ export class EditorMarkdownExtension extends SourceEditorExtension { ...@@ -98,19 +112,36 @@ export class EditorMarkdownExtension extends SourceEditorExtension {
// Method that will be executed when the action is triggered. // Method that will be executed when the action is triggered.
// @param ed The editor instance is passed in as a convenience // @param ed The editor instance is passed in as a convenience
run(e) { run(instance) {
e.togglePreview(); instance.togglePreview();
}, },
}); });
} }
togglePreview() { togglePreview() {
if (!this.previewEl) { if (!this.preview?.el) {
this.previewEl = EditorMarkdownExtension.setupPanelElement(this.getDomNode().parentElement); this.preview.el = setupDomElement({ injectToEl: this.getDomNode().parentElement });
}
EditorMarkdownExtension.togglePreviewLayout.call(this);
EditorMarkdownExtension.togglePreviewPanel.call(this);
if (!this.preview?.shown) {
this.modelChangeListener = this.onDidChangeModelContent(
debounce(this.fetchPreview.bind(this), 250),
);
} else {
this.modelChangeListener.dispose();
} }
EditorMarkdownExtension.togglePreviewLayout(this);
EditorMarkdownExtension.togglePreviewPanel(this); this.preview.shown = !this.preview?.shown;
this.preview = !this.preview;
this.getModel().onDidChangeLanguage(({ newLanguage, oldLanguage } = {}) => {
if (newLanguage === 'markdown' && oldLanguage !== newLanguage) {
this.setupPreviewAction();
} else {
this.cleanup();
}
});
} }
getSelectedText(selection = this.getSelection()) { getSelectedText(selection = this.getSelection()) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment