2019-12-26 22:10:19 +05:30
|
|
|
/* eslint-disable func-names */
|
2017-08-17 22:00:37 +05:30
|
|
|
|
2018-05-09 12:01:36 +05:30
|
|
|
import $ from 'jquery';
|
2023-03-17 16:20:25 +05:30
|
|
|
import { renderGFM } from '~/behaviors/markdown/render_gfm';
|
2023-05-27 22:25:52 +05:30
|
|
|
import { createAlert } from '~/alert';
|
2021-03-11 19:13:27 +05:30
|
|
|
import axios from '~/lib/utils/axios_utils';
|
2018-05-09 12:01:36 +05:30
|
|
|
import { __ } from '~/locale';
|
|
|
|
|
2016-09-29 09:46:39 +05:30
|
|
|
// MarkdownPreview
|
|
|
|
//
|
2017-08-17 22:00:37 +05:30
|
|
|
// Handles toggling the "Write" and "Preview" tab clicks, rendering the preview
|
2017-09-10 17:25:29 +05:30
|
|
|
// (including the explanation of quick actions), and showing a warning when
|
2017-08-17 22:00:37 +05:30
|
|
|
// more than `x` users are referenced.
|
2016-09-29 09:46:39 +05:30
|
|
|
//
|
2017-08-17 22:00:37 +05:30
|
|
|
|
2019-12-26 22:10:19 +05:30
|
|
|
let lastTextareaHeight;
|
|
|
|
let lastTextareaPreviewed;
|
2018-03-17 18:26:18 +05:30
|
|
|
|
|
|
|
function MarkdownPreview() {}
|
|
|
|
|
|
|
|
// Minimum number of users referenced before triggering a warning
|
|
|
|
MarkdownPreview.prototype.referenceThreshold = 10;
|
2019-07-31 22:56:46 +05:30
|
|
|
MarkdownPreview.prototype.emptyMessage = __('Nothing to preview.');
|
2018-03-17 18:26:18 +05:30
|
|
|
|
|
|
|
MarkdownPreview.prototype.ajaxCache = {};
|
|
|
|
|
2021-03-08 18:12:59 +05:30
|
|
|
MarkdownPreview.prototype.showPreview = function ($form) {
|
2019-12-26 22:10:19 +05:30
|
|
|
const preview = $form.find('.js-md-preview');
|
|
|
|
const url = preview.data('url');
|
2018-03-17 18:26:18 +05:30
|
|
|
if (preview.hasClass('md-preview-loading')) {
|
|
|
|
return;
|
|
|
|
}
|
2018-11-08 19:23:39 +05:30
|
|
|
|
2019-12-26 22:10:19 +05:30
|
|
|
const mdText = $form.find('textarea.markdown-area').val();
|
2018-03-17 18:26:18 +05:30
|
|
|
|
2019-10-12 21:52:04 +05:30
|
|
|
if (mdText === undefined) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-03-17 18:26:18 +05:30
|
|
|
if (mdText.trim().length === 0) {
|
|
|
|
preview.text(this.emptyMessage);
|
|
|
|
this.hideReferencedUsers($form);
|
|
|
|
} else {
|
2019-07-31 22:56:46 +05:30
|
|
|
preview.addClass('md-preview-loading').text(__('Loading...'));
|
2021-03-08 18:12:59 +05:30
|
|
|
this.fetchMarkdownPreview(mdText, url, (response) => {
|
2019-12-26 22:10:19 +05:30
|
|
|
let body;
|
2019-12-21 20:55:43 +05:30
|
|
|
if (response.body.length > 0) {
|
|
|
|
({ body } = response);
|
|
|
|
} else {
|
|
|
|
body = this.emptyMessage;
|
|
|
|
}
|
|
|
|
|
|
|
|
preview.removeClass('md-preview-loading').html(body);
|
2023-03-17 16:20:25 +05:30
|
|
|
renderGFM(preview.get(0));
|
2019-12-21 20:55:43 +05:30
|
|
|
this.renderReferencedUsers(response.references.users, $form);
|
|
|
|
|
|
|
|
if (response.references.commands) {
|
|
|
|
this.renderReferencedCommands(response.references.commands, $form);
|
|
|
|
}
|
|
|
|
});
|
2018-03-17 18:26:18 +05:30
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-03-08 18:12:59 +05:30
|
|
|
MarkdownPreview.prototype.fetchMarkdownPreview = function (text, url, success) {
|
2018-03-17 18:26:18 +05:30
|
|
|
if (!url) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (text === this.ajaxCache.text) {
|
|
|
|
success(this.ajaxCache.response);
|
|
|
|
return;
|
|
|
|
}
|
2018-12-13 13:39:08 +05:30
|
|
|
axios
|
|
|
|
.post(url, {
|
|
|
|
text,
|
|
|
|
})
|
|
|
|
.then(({ data }) => {
|
|
|
|
this.ajaxCache = {
|
2019-12-04 20:38:33 +05:30
|
|
|
text,
|
2018-12-13 13:39:08 +05:30
|
|
|
response: data,
|
|
|
|
};
|
|
|
|
success(data);
|
|
|
|
})
|
2021-09-30 23:02:18 +05:30
|
|
|
.catch(() =>
|
2022-11-25 23:54:43 +05:30
|
|
|
createAlert({
|
2021-11-18 22:05:49 +05:30
|
|
|
message: __('An error occurred while fetching Markdown preview'),
|
2021-09-30 23:02:18 +05:30
|
|
|
}),
|
|
|
|
);
|
2018-03-17 18:26:18 +05:30
|
|
|
};
|
|
|
|
|
2021-03-08 18:12:59 +05:30
|
|
|
MarkdownPreview.prototype.hideReferencedUsers = function ($form) {
|
2018-03-17 18:26:18 +05:30
|
|
|
$form.find('.referenced-users').hide();
|
|
|
|
};
|
|
|
|
|
2021-03-08 18:12:59 +05:30
|
|
|
MarkdownPreview.prototype.renderReferencedUsers = function (users, $form) {
|
2019-12-26 22:10:19 +05:30
|
|
|
const referencedUsers = $form.find('.referenced-users');
|
2018-03-17 18:26:18 +05:30
|
|
|
if (referencedUsers.length) {
|
|
|
|
if (users.length >= this.referenceThreshold) {
|
|
|
|
referencedUsers.show();
|
|
|
|
referencedUsers.find('.js-referenced-users-count').text(users.length);
|
|
|
|
} else {
|
|
|
|
referencedUsers.hide();
|
2016-09-13 17:45:13 +05:30
|
|
|
}
|
2018-03-17 18:26:18 +05:30
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-03-08 18:12:59 +05:30
|
|
|
MarkdownPreview.prototype.hideReferencedCommands = function ($form) {
|
2018-03-17 18:26:18 +05:30
|
|
|
$form.find('.referenced-commands').hide();
|
|
|
|
};
|
|
|
|
|
2021-03-08 18:12:59 +05:30
|
|
|
MarkdownPreview.prototype.renderReferencedCommands = function (commands, $form) {
|
2019-12-26 22:10:19 +05:30
|
|
|
const referencedCommands = $form.find('.referenced-commands');
|
2018-03-17 18:26:18 +05:30
|
|
|
if (commands.length > 0) {
|
|
|
|
referencedCommands.html(commands);
|
|
|
|
referencedCommands.show();
|
|
|
|
} else {
|
|
|
|
referencedCommands.html('');
|
|
|
|
referencedCommands.hide();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-12-26 22:10:19 +05:30
|
|
|
const markdownPreview = new MarkdownPreview();
|
2018-03-17 18:26:18 +05:30
|
|
|
|
2019-12-26 22:10:19 +05:30
|
|
|
const previewButtonSelector = '.js-md-preview-button';
|
2018-03-17 18:26:18 +05:30
|
|
|
lastTextareaPreviewed = null;
|
|
|
|
|
2019-12-21 20:55:43 +05:30
|
|
|
$(document).on('markdown-preview:show', (e, $form) => {
|
2018-03-17 18:26:18 +05:30
|
|
|
if (!$form) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
lastTextareaPreviewed = $form.find('textarea.markdown-area');
|
|
|
|
lastTextareaHeight = lastTextareaPreviewed.height();
|
|
|
|
|
|
|
|
// toggle tabs
|
2023-07-09 08:55:56 +05:30
|
|
|
$form.find(previewButtonSelector).val('edit');
|
|
|
|
$form.find(previewButtonSelector).children('span.gl-button-text').text(__('Continue editing'));
|
|
|
|
$form.find(previewButtonSelector).addClass('gl-shadow-none! gl-bg-transparent!');
|
2018-03-17 18:26:18 +05:30
|
|
|
|
|
|
|
// toggle content
|
|
|
|
$form.find('.md-write-holder').hide();
|
|
|
|
$form.find('.md-preview-holder').show();
|
2023-07-09 08:55:56 +05:30
|
|
|
$form.find('.md-header-toolbar, .js-zen-enter').addClass('gl-display-none!');
|
|
|
|
|
2018-03-17 18:26:18 +05:30
|
|
|
markdownPreview.showPreview($form);
|
|
|
|
});
|
|
|
|
|
2019-12-21 20:55:43 +05:30
|
|
|
$(document).on('markdown-preview:hide', (e, $form) => {
|
2018-03-17 18:26:18 +05:30
|
|
|
if (!$form) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
lastTextareaPreviewed = null;
|
2016-09-13 17:45:13 +05:30
|
|
|
|
2018-03-17 18:26:18 +05:30
|
|
|
if (lastTextareaHeight) {
|
|
|
|
$form.find('textarea.markdown-area').height(lastTextareaHeight);
|
|
|
|
}
|
|
|
|
|
|
|
|
// toggle tabs
|
2023-07-09 08:55:56 +05:30
|
|
|
$form.find(previewButtonSelector).val('preview');
|
|
|
|
$form.find(previewButtonSelector).children('span.gl-button-text').text(__('Preview'));
|
2018-03-17 18:26:18 +05:30
|
|
|
|
|
|
|
// toggle content
|
|
|
|
$form.find('.md-write-holder').show();
|
|
|
|
$form.find('textarea.markdown-area').focus();
|
|
|
|
$form.find('.md-preview-holder').hide();
|
2023-07-09 08:55:56 +05:30
|
|
|
$form.find('.md-header-toolbar, .js-zen-enter').removeClass('gl-display-none!');
|
2018-03-17 18:26:18 +05:30
|
|
|
|
|
|
|
markdownPreview.hideReferencedCommands($form);
|
|
|
|
});
|
|
|
|
|
2019-12-21 20:55:43 +05:30
|
|
|
$(document).on('markdown-preview:toggle', (e, keyboardEvent) => {
|
2019-12-26 22:10:19 +05:30
|
|
|
let $target;
|
2018-03-17 18:26:18 +05:30
|
|
|
$target = $(keyboardEvent.target);
|
|
|
|
if ($target.is('textarea.markdown-area')) {
|
|
|
|
$(document).triggerHandler('markdown-preview:show', [$target.closest('form')]);
|
|
|
|
keyboardEvent.preventDefault();
|
|
|
|
} else if (lastTextareaPreviewed) {
|
|
|
|
$target = lastTextareaPreviewed;
|
|
|
|
$(document).triggerHandler('markdown-preview:hide', [$target.closest('form')]);
|
|
|
|
keyboardEvent.preventDefault();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-03-08 18:12:59 +05:30
|
|
|
$(document).on('click', previewButtonSelector, function (e) {
|
2018-03-17 18:26:18 +05:30
|
|
|
e.preventDefault();
|
2019-12-26 22:10:19 +05:30
|
|
|
const $form = $(this).closest('form');
|
2023-07-09 08:55:56 +05:30
|
|
|
const eventName = e.currentTarget.getAttribute('value') === 'preview' ? 'show' : 'hide';
|
|
|
|
$(document).triggerHandler(`markdown-preview:${eventName}`, [$form]);
|
|
|
|
});
|
|
|
|
|
|
|
|
$(document).on('mousedown', previewButtonSelector, function (e) {
|
|
|
|
e.preventDefault();
|
|
|
|
const $form = $(this).closest('form');
|
|
|
|
$form.find(previewButtonSelector).removeClass('gl-shadow-none! gl-bg-transparent!');
|
|
|
|
});
|
|
|
|
|
|
|
|
$(document).on('mouseenter', previewButtonSelector, function (e) {
|
|
|
|
e.preventDefault();
|
|
|
|
const $form = $(this).closest('form');
|
|
|
|
$form.find(previewButtonSelector).removeClass('gl-bg-transparent!');
|
2018-03-17 18:26:18 +05:30
|
|
|
});
|
|
|
|
|
2023-07-09 08:55:56 +05:30
|
|
|
$(document).on('mouseleave', previewButtonSelector, function (e) {
|
2018-03-17 18:26:18 +05:30
|
|
|
e.preventDefault();
|
2019-12-26 22:10:19 +05:30
|
|
|
const $form = $(this).closest('form');
|
2023-07-09 08:55:56 +05:30
|
|
|
$form.find(previewButtonSelector).addClass('gl-bg-transparent!');
|
2018-03-17 18:26:18 +05:30
|
|
|
});
|
|
|
|
|
|
|
|
export default MarkdownPreview;
|