Export text utils as ES6 modules
This commit is contained in:
parent
c6a48f3f92
commit
1ff3f1a4f7
|
@ -1,3 +1,5 @@
|
|||
import { truncate } from './lib/utils/text_utility';
|
||||
|
||||
const MAX_MESSAGE_LENGTH = 500;
|
||||
const MESSAGE_CELL_SELECTOR = '.abuse-reports .message';
|
||||
|
||||
|
@ -15,7 +17,7 @@ export default class AbuseReports {
|
|||
if (reportMessage.length > MAX_MESSAGE_LENGTH) {
|
||||
$messageCellElement.data('original-message', reportMessage);
|
||||
$messageCellElement.data('message-truncated', 'true');
|
||||
$messageCellElement.text(window.gl.text.truncate(reportMessage, MAX_MESSAGE_LENGTH));
|
||||
$messageCellElement.text(truncate(reportMessage, MAX_MESSAGE_LENGTH));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
import Vue from 'vue';
|
||||
import Flash from '../../../flash';
|
||||
import './lists_dropdown';
|
||||
import { pluralize } from '../../../lib/utils/text_utility';
|
||||
|
||||
const ModalStore = gl.issueBoards.ModalStore;
|
||||
|
||||
|
@ -21,7 +22,7 @@ gl.issueBoards.ModalFooter = Vue.extend({
|
|||
submitText() {
|
||||
const count = ModalStore.selectedCount();
|
||||
|
||||
return `Add ${count > 0 ? count : ''} ${gl.text.pluralize('issue', count)}`;
|
||||
return `Add ${count > 0 ? count : ''} ${pluralize('issue', count)}`;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
prefer-template, object-shorthand, prefer-arrow-callback */
|
||||
/* global Pager */
|
||||
|
||||
import { pluralize } from './lib/utils/text_utility';
|
||||
|
||||
export default (function () {
|
||||
const CommitsList = {};
|
||||
|
||||
|
@ -86,7 +88,7 @@ export default (function () {
|
|||
|
||||
// Update commits count in the previous commits header.
|
||||
commitsCount += Number($(processedData).nextUntil('li.js-commit-header').first().find('li.commit').length);
|
||||
$commitsHeadersLast.find('span.commits-count').text(`${commitsCount} ${gl.text.pluralize('commit', commitsCount)}`);
|
||||
$commitsHeadersLast.find('span.commits-count').text(`${commitsCount} ${pluralize('commit', commitsCount)}`);
|
||||
}
|
||||
|
||||
gl.utils.localTimeAgo($processedData.find('.js-timeago'));
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/* eslint-disable func-names, prefer-arrow-callback */
|
||||
import Api from './api';
|
||||
import { humanize } from './lib/utils/text_utility';
|
||||
|
||||
export default class CreateLabelDropdown {
|
||||
constructor($el, namespacePath, projectPath) {
|
||||
|
@ -107,7 +108,7 @@ export default class CreateLabelDropdown {
|
|||
errors = label.message;
|
||||
} else {
|
||||
errors = Object.keys(label.message).map(key =>
|
||||
`${gl.text.humanize(key)} ${label.message[key].join(', ')}`,
|
||||
`${humanize(key)} ${label.message[key].join(', ')}`,
|
||||
).join('<br/>');
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* eslint-disable no-param-reassign */
|
||||
|
||||
import { __ } from '../locale';
|
||||
import '../lib/utils/text_utility';
|
||||
import { dasherize } from '../lib/utils/text_utility';
|
||||
import DEFAULT_EVENT_OBJECTS from './default_event_objects';
|
||||
|
||||
const EMPTY_STAGE_TEXTS = {
|
||||
|
@ -36,7 +36,7 @@ export default {
|
|||
});
|
||||
|
||||
newData.stages.forEach((item) => {
|
||||
const stageSlug = gl.text.dasherize(item.name.toLowerCase());
|
||||
const stageSlug = dasherize(item.name.toLowerCase());
|
||||
item.active = false;
|
||||
item.isUserAllowed = data.permissions[stageSlug];
|
||||
item.emptyStageText = EMPTY_STAGE_TEXTS[stageSlug];
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import Timeago from 'timeago.js';
|
||||
import _ from 'underscore';
|
||||
import userAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
|
||||
import '../../lib/utils/text_utility';
|
||||
import { humanize } from '../../lib/utils/text_utility';
|
||||
import ActionsComponent from './environment_actions.vue';
|
||||
import ExternalUrlComponent from './environment_external_url.vue';
|
||||
import StopComponent from './environment_stop.vue';
|
||||
|
@ -139,7 +139,7 @@ export default {
|
|||
if (this.hasManualActions) {
|
||||
return this.model.last_deployment.manual_actions.map((action) => {
|
||||
const parsedAction = {
|
||||
name: gl.text.humanize(action.name),
|
||||
name: humanize(action.name),
|
||||
play_path: action.play_path,
|
||||
playable: action.playable,
|
||||
};
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import GfmAutoComplete from './gfm_auto_complete';
|
||||
import dropzoneInput from './dropzone_input';
|
||||
import textUtils from './lib/utils/text_markdown';
|
||||
|
||||
export default class GLForm {
|
||||
constructor(form, enableGFM = false) {
|
||||
|
@ -46,7 +47,7 @@ export default class GLForm {
|
|||
}
|
||||
// form and textarea event listeners
|
||||
this.addEventListeners();
|
||||
gl.text.init(this.form);
|
||||
textUtils.init(this.form);
|
||||
// hide discard button
|
||||
this.form.find('.js-note-discard').hide();
|
||||
this.form.show();
|
||||
|
@ -85,7 +86,7 @@ export default class GLForm {
|
|||
clearEventListeners() {
|
||||
this.textarea.off('focus');
|
||||
this.textarea.off('blur');
|
||||
gl.text.removeListeners(this.form);
|
||||
textUtils.removeListeners(this.form);
|
||||
}
|
||||
|
||||
addEventListeners() {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, one-var, no-underscore-dangle, one-var-declaration-per-line, object-shorthand, no-unused-vars, no-new, comma-dangle, consistent-return, quotes, dot-notation, quote-props, prefer-arrow-callback, max-len */
|
||||
import 'vendor/jquery.waitforimages';
|
||||
import '~/lib/utils/text_utility';
|
||||
import { addDelimiter } from './lib/utils/text_utility';
|
||||
import Flash from './flash';
|
||||
import TaskList from './task_list';
|
||||
import CreateMergeRequestDropdown from './create_merge_request_dropdown';
|
||||
|
@ -73,7 +73,7 @@ export default class Issue {
|
|||
|
||||
let numProjectIssues = Number(projectIssuesCounter.first().text().trim().replace(/[^\d]/, ''));
|
||||
numProjectIssues = isClosed ? numProjectIssues - 1 : numProjectIssues + 1;
|
||||
projectIssuesCounter.text(gl.text.addDelimiter(numProjectIssues));
|
||||
projectIssuesCounter.text(addDelimiter(numProjectIssues));
|
||||
|
||||
if (this.createMergeRequestDropdown) {
|
||||
if (isClosed) {
|
||||
|
|
|
@ -172,7 +172,6 @@ export const getSelectedFragment = () => {
|
|||
return documentFragment;
|
||||
};
|
||||
|
||||
// TODO: Update this name, there is a gl.text.insertText function.
|
||||
export const insertText = (target, text) => {
|
||||
// Firefox doesn't support `document.execCommand('insertText', false, text)` on textareas
|
||||
const selectionStart = target.selectionStart;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import timeago from 'timeago.js';
|
||||
import dateFormat from 'vendor/date.format';
|
||||
import { pluralize } from './text_utility';
|
||||
|
||||
import {
|
||||
lang,
|
||||
|
@ -143,9 +144,9 @@ export function timeIntervalInWords(intervalInSeconds) {
|
|||
let text = '';
|
||||
|
||||
if (minutes >= 1) {
|
||||
text = `${minutes} ${gl.text.pluralize('minute', minutes)} ${seconds} ${gl.text.pluralize('second', seconds)}`;
|
||||
text = `${minutes} ${pluralize('minute', minutes)} ${seconds} ${pluralize('second', seconds)}`;
|
||||
} else {
|
||||
text = `${seconds} ${gl.text.pluralize('second', seconds)}`;
|
||||
text = `${seconds} ${pluralize('second', seconds)}`;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
/* eslint-disable import/prefer-default-export, func-names, space-before-function-paren, wrap-iife, no-var, no-param-reassign, no-cond-assign, quotes, one-var, one-var-declaration-per-line, operator-assignment, no-else-return, prefer-template, prefer-arrow-callback, no-empty, max-len, consistent-return, no-unused-vars, no-return-assign, max-len, vars-on-top */
|
||||
|
||||
const textUtils = {};
|
||||
|
||||
textUtils.selectedText = function(text, textarea) {
|
||||
return text.substring(textarea.selectionStart, textarea.selectionEnd);
|
||||
};
|
||||
|
||||
textUtils.lineBefore = function(text, textarea) {
|
||||
var split;
|
||||
split = text.substring(0, textarea.selectionStart).trim().split('\n');
|
||||
return split[split.length - 1];
|
||||
};
|
||||
|
||||
textUtils.lineAfter = function(text, textarea) {
|
||||
return text.substring(textarea.selectionEnd).trim().split('\n')[0];
|
||||
};
|
||||
|
||||
textUtils.blockTagText = function(text, textArea, blockTag, selected) {
|
||||
var lineAfter, lineBefore;
|
||||
lineBefore = this.lineBefore(text, textArea);
|
||||
lineAfter = this.lineAfter(text, textArea);
|
||||
if (lineBefore === blockTag && lineAfter === blockTag) {
|
||||
// To remove the block tag we have to select the line before & after
|
||||
if (blockTag != null) {
|
||||
textArea.selectionStart = textArea.selectionStart - (blockTag.length + 1);
|
||||
textArea.selectionEnd = textArea.selectionEnd + (blockTag.length + 1);
|
||||
}
|
||||
return selected;
|
||||
} else {
|
||||
return blockTag + "\n" + selected + "\n" + blockTag;
|
||||
}
|
||||
};
|
||||
|
||||
textUtils.insertText = function(textArea, text, tag, blockTag, selected, wrap) {
|
||||
var insertText, inserted, selectedSplit, startChar, removedLastNewLine, removedFirstNewLine, currentLineEmpty, lastNewLine;
|
||||
removedLastNewLine = false;
|
||||
removedFirstNewLine = false;
|
||||
currentLineEmpty = false;
|
||||
|
||||
// Remove the first newline
|
||||
if (selected.indexOf('\n') === 0) {
|
||||
removedFirstNewLine = true;
|
||||
selected = selected.replace(/\n+/, '');
|
||||
}
|
||||
|
||||
// Remove the last newline
|
||||
if (textArea.selectionEnd - textArea.selectionStart > selected.replace(/\n$/, '').length) {
|
||||
removedLastNewLine = true;
|
||||
selected = selected.replace(/\n$/, '');
|
||||
}
|
||||
|
||||
selectedSplit = selected.split('\n');
|
||||
|
||||
if (!wrap) {
|
||||
lastNewLine = textArea.value.substr(0, textArea.selectionStart).lastIndexOf('\n');
|
||||
|
||||
// Check whether the current line is empty or consists only of spaces(=handle as empty)
|
||||
if (/^\s*$/.test(textArea.value.substring(lastNewLine, textArea.selectionStart))) {
|
||||
currentLineEmpty = true;
|
||||
}
|
||||
}
|
||||
|
||||
startChar = !wrap && !currentLineEmpty && textArea.selectionStart > 0 ? '\n' : '';
|
||||
|
||||
if (selectedSplit.length > 1 && (!wrap || (blockTag != null && blockTag !== ''))) {
|
||||
if (blockTag != null && blockTag !== '') {
|
||||
insertText = this.blockTagText(text, textArea, blockTag, selected);
|
||||
} else {
|
||||
insertText = selectedSplit.map(function(val) {
|
||||
if (val.indexOf(tag) === 0) {
|
||||
return "" + (val.replace(tag, ''));
|
||||
} else {
|
||||
return "" + tag + val;
|
||||
}
|
||||
}).join('\n');
|
||||
}
|
||||
} else {
|
||||
insertText = "" + startChar + tag + selected + (wrap ? tag : ' ');
|
||||
}
|
||||
|
||||
if (removedFirstNewLine) {
|
||||
insertText = '\n' + insertText;
|
||||
}
|
||||
|
||||
if (removedLastNewLine) {
|
||||
insertText += '\n';
|
||||
}
|
||||
|
||||
if (document.queryCommandSupported('insertText')) {
|
||||
inserted = document.execCommand('insertText', false, insertText);
|
||||
}
|
||||
if (!inserted) {
|
||||
try {
|
||||
document.execCommand("ms-beginUndoUnit");
|
||||
} catch (error) {}
|
||||
textArea.value = this.replaceRange(text, textArea.selectionStart, textArea.selectionEnd, insertText);
|
||||
try {
|
||||
document.execCommand("ms-endUndoUnit");
|
||||
} catch (error) {}
|
||||
}
|
||||
return this.moveCursor(textArea, tag, wrap, removedLastNewLine);
|
||||
};
|
||||
|
||||
textUtils.moveCursor = function(textArea, tag, wrapped, removedLastNewLine) {
|
||||
var pos;
|
||||
if (!textArea.setSelectionRange) {
|
||||
return;
|
||||
}
|
||||
if (textArea.selectionStart === textArea.selectionEnd) {
|
||||
if (wrapped) {
|
||||
pos = textArea.selectionStart - tag.length;
|
||||
} else {
|
||||
pos = textArea.selectionStart;
|
||||
}
|
||||
|
||||
if (removedLastNewLine) {
|
||||
pos -= 1;
|
||||
}
|
||||
|
||||
return textArea.setSelectionRange(pos, pos);
|
||||
}
|
||||
};
|
||||
|
||||
textUtils.updateText = function(textArea, tag, blockTag, wrap) {
|
||||
var $textArea, selected, text;
|
||||
$textArea = $(textArea);
|
||||
textArea = $textArea.get(0);
|
||||
text = $textArea.val();
|
||||
selected = this.selectedText(text, textArea);
|
||||
$textArea.focus();
|
||||
return this.insertText(textArea, text, tag, blockTag, selected, wrap);
|
||||
};
|
||||
|
||||
textUtils.init = function(form) {
|
||||
var self;
|
||||
self = this;
|
||||
return $('.js-md', form).off('click').on('click', function() {
|
||||
var $this;
|
||||
$this = $(this);
|
||||
return self.updateText($this.closest('.md-area').find('textarea'), $this.data('md-tag'), $this.data('md-block'), !$this.data('md-prepend'));
|
||||
});
|
||||
};
|
||||
|
||||
textUtils.removeListeners = function(form) {
|
||||
return $('.js-md', form).off('click');
|
||||
};
|
||||
|
||||
textUtils.replaceRange = function(s, start, end, substitute) {
|
||||
return s.substring(0, start) + substitute + s.substring(end);
|
||||
};
|
||||
|
||||
export default textUtils;
|
|
@ -1,18 +1,13 @@
|
|||
/* eslint-disable import/prefer-default-export, func-names, space-before-function-paren, wrap-iife, no-var, no-param-reassign, no-cond-assign, quotes, one-var, one-var-declaration-per-line, operator-assignment, no-else-return, prefer-template, prefer-arrow-callback, no-empty, max-len, consistent-return, no-unused-vars, no-return-assign, max-len, vars-on-top */
|
||||
|
||||
import 'vendor/latinise';
|
||||
|
||||
var base;
|
||||
var w = window;
|
||||
if (w.gl == null) {
|
||||
w.gl = {};
|
||||
}
|
||||
if ((base = w.gl).text == null) {
|
||||
base.text = {};
|
||||
}
|
||||
gl.text.addDelimiter = function(text) {
|
||||
return text ? text.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") : text;
|
||||
};
|
||||
/**
|
||||
* Adds a , to a string composed by numbers, at every 3 chars.
|
||||
*
|
||||
* 2333 -> 2,333
|
||||
* 232324 -> 232,324
|
||||
*
|
||||
* @param {String} text
|
||||
* @returns {String}
|
||||
*/
|
||||
export const addDelimiter = text => (text ? text.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',') : text);
|
||||
|
||||
/**
|
||||
* Returns '99+' for numbers bigger than 99.
|
||||
|
@ -20,178 +15,43 @@ gl.text.addDelimiter = function(text) {
|
|||
* @param {Number} count
|
||||
* @return {Number|String}
|
||||
*/
|
||||
export function highCountTrim(count) {
|
||||
return count > 99 ? '99+' : count;
|
||||
}
|
||||
export const highCountTrim = count => (count > 99 ? '99+' : count);
|
||||
|
||||
gl.text.randomString = function() {
|
||||
return Math.random().toString(36).substring(7);
|
||||
};
|
||||
gl.text.replaceRange = function(s, start, end, substitute) {
|
||||
return s.substring(0, start) + substitute + s.substring(end);
|
||||
};
|
||||
gl.text.getTextWidth = function(text, font) {
|
||||
/**
|
||||
* Uses canvas.measureText to compute and return the width of the given text of given font in pixels.
|
||||
*
|
||||
* @param {String} text The text to be rendered.
|
||||
* @param {String} font The css font descriptor that text is to be rendered with (e.g. "bold 14px verdana").
|
||||
*
|
||||
* @see http://stackoverflow.com/questions/118241/calculate-text-width-with-javascript/21015393#21015393
|
||||
*/
|
||||
// re-use canvas object for better performance
|
||||
var canvas = gl.text.getTextWidth.canvas || (gl.text.getTextWidth.canvas = document.createElement('canvas'));
|
||||
var context = canvas.getContext('2d');
|
||||
context.font = font;
|
||||
return context.measureText(text).width;
|
||||
};
|
||||
gl.text.selectedText = function(text, textarea) {
|
||||
return text.substring(textarea.selectionStart, textarea.selectionEnd);
|
||||
};
|
||||
gl.text.lineBefore = function(text, textarea) {
|
||||
var split;
|
||||
split = text.substring(0, textarea.selectionStart).trim().split('\n');
|
||||
return split[split.length - 1];
|
||||
};
|
||||
gl.text.lineAfter = function(text, textarea) {
|
||||
return text.substring(textarea.selectionEnd).trim().split('\n')[0];
|
||||
};
|
||||
gl.text.blockTagText = function(text, textArea, blockTag, selected) {
|
||||
var lineAfter, lineBefore;
|
||||
lineBefore = this.lineBefore(text, textArea);
|
||||
lineAfter = this.lineAfter(text, textArea);
|
||||
if (lineBefore === blockTag && lineAfter === blockTag) {
|
||||
// To remove the block tag we have to select the line before & after
|
||||
if (blockTag != null) {
|
||||
textArea.selectionStart = textArea.selectionStart - (blockTag.length + 1);
|
||||
textArea.selectionEnd = textArea.selectionEnd + (blockTag.length + 1);
|
||||
}
|
||||
return selected;
|
||||
} else {
|
||||
return blockTag + "\n" + selected + "\n" + blockTag;
|
||||
}
|
||||
};
|
||||
gl.text.insertText = function(textArea, text, tag, blockTag, selected, wrap) {
|
||||
var insertText, inserted, selectedSplit, startChar, removedLastNewLine, removedFirstNewLine, currentLineEmpty, lastNewLine;
|
||||
removedLastNewLine = false;
|
||||
removedFirstNewLine = false;
|
||||
currentLineEmpty = false;
|
||||
/**
|
||||
* Converst first char to uppercase and replaces undercores with spaces
|
||||
* @param {String} string
|
||||
* @requires {String}
|
||||
*/
|
||||
export const humanize = string => string.charAt(0).toUpperCase() + string.replace(/_/g, ' ').slice(1);
|
||||
|
||||
// Remove the first newline
|
||||
if (selected.indexOf('\n') === 0) {
|
||||
removedFirstNewLine = true;
|
||||
selected = selected.replace(/\n+/, '');
|
||||
}
|
||||
/**
|
||||
* Adds an 's' to the end of the string when count is bigger than 0
|
||||
* @param {String} str
|
||||
* @param {Number} count
|
||||
* @returns {String}
|
||||
*/
|
||||
export const pluralize = (str, count) => str + (count > 1 || count === 0 ? 's' : '');
|
||||
|
||||
// Remove the last newline
|
||||
if (textArea.selectionEnd - textArea.selectionStart > selected.replace(/\n$/, '').length) {
|
||||
removedLastNewLine = true;
|
||||
selected = selected.replace(/\n$/, '');
|
||||
}
|
||||
/**
|
||||
* Replaces underscores with dashes
|
||||
* @param {*} str
|
||||
* @returns {String}
|
||||
*/
|
||||
export const dasherize = str => str.replace(/[_\s]+/g, '-');
|
||||
|
||||
selectedSplit = selected.split('\n');
|
||||
/**
|
||||
* Removes accents and converts to lower case
|
||||
* @param {String} str
|
||||
* @returns {String}
|
||||
*/
|
||||
export const slugify = str => str.trim().toLowerCase();
|
||||
|
||||
if (!wrap) {
|
||||
lastNewLine = textArea.value.substr(0, textArea.selectionStart).lastIndexOf('\n');
|
||||
/**
|
||||
* Truncates given text
|
||||
*
|
||||
* @param {String} string
|
||||
* @param {Number} maxLength
|
||||
* @returns {String}
|
||||
*/
|
||||
export const truncate = (string, maxLength) => `${string.substr(0, (maxLength - 3))}...`;
|
||||
|
||||
// Check whether the current line is empty or consists only of spaces(=handle as empty)
|
||||
if (/^\s*$/.test(textArea.value.substring(lastNewLine, textArea.selectionStart))) {
|
||||
currentLineEmpty = true;
|
||||
}
|
||||
}
|
||||
|
||||
startChar = !wrap && !currentLineEmpty && textArea.selectionStart > 0 ? '\n' : '';
|
||||
|
||||
if (selectedSplit.length > 1 && (!wrap || (blockTag != null && blockTag !== ''))) {
|
||||
if (blockTag != null && blockTag !== '') {
|
||||
insertText = this.blockTagText(text, textArea, blockTag, selected);
|
||||
} else {
|
||||
insertText = selectedSplit.map(function(val) {
|
||||
if (val.indexOf(tag) === 0) {
|
||||
return "" + (val.replace(tag, ''));
|
||||
} else {
|
||||
return "" + tag + val;
|
||||
}
|
||||
}).join('\n');
|
||||
}
|
||||
} else {
|
||||
insertText = "" + startChar + tag + selected + (wrap ? tag : ' ');
|
||||
}
|
||||
|
||||
if (removedFirstNewLine) {
|
||||
insertText = '\n' + insertText;
|
||||
}
|
||||
|
||||
if (removedLastNewLine) {
|
||||
insertText += '\n';
|
||||
}
|
||||
|
||||
if (document.queryCommandSupported('insertText')) {
|
||||
inserted = document.execCommand('insertText', false, insertText);
|
||||
}
|
||||
if (!inserted) {
|
||||
try {
|
||||
document.execCommand("ms-beginUndoUnit");
|
||||
} catch (error) {}
|
||||
textArea.value = this.replaceRange(text, textArea.selectionStart, textArea.selectionEnd, insertText);
|
||||
try {
|
||||
document.execCommand("ms-endUndoUnit");
|
||||
} catch (error) {}
|
||||
}
|
||||
return this.moveCursor(textArea, tag, wrap, removedLastNewLine);
|
||||
};
|
||||
gl.text.moveCursor = function(textArea, tag, wrapped, removedLastNewLine) {
|
||||
var pos;
|
||||
if (!textArea.setSelectionRange) {
|
||||
return;
|
||||
}
|
||||
if (textArea.selectionStart === textArea.selectionEnd) {
|
||||
if (wrapped) {
|
||||
pos = textArea.selectionStart - tag.length;
|
||||
} else {
|
||||
pos = textArea.selectionStart;
|
||||
}
|
||||
|
||||
if (removedLastNewLine) {
|
||||
pos -= 1;
|
||||
}
|
||||
|
||||
return textArea.setSelectionRange(pos, pos);
|
||||
}
|
||||
};
|
||||
gl.text.updateText = function(textArea, tag, blockTag, wrap) {
|
||||
var $textArea, selected, text;
|
||||
$textArea = $(textArea);
|
||||
textArea = $textArea.get(0);
|
||||
text = $textArea.val();
|
||||
selected = this.selectedText(text, textArea);
|
||||
$textArea.focus();
|
||||
return this.insertText(textArea, text, tag, blockTag, selected, wrap);
|
||||
};
|
||||
gl.text.init = function(form) {
|
||||
var self;
|
||||
self = this;
|
||||
return $('.js-md', form).off('click').on('click', function() {
|
||||
var $this;
|
||||
$this = $(this);
|
||||
return self.updateText($this.closest('.md-area').find('textarea'), $this.data('md-tag'), $this.data('md-block'), !$this.data('md-prepend'));
|
||||
});
|
||||
};
|
||||
gl.text.removeListeners = function(form) {
|
||||
return $('.js-md', form).off('click');
|
||||
};
|
||||
gl.text.humanize = function(string) {
|
||||
return string.charAt(0).toUpperCase() + string.replace(/_/g, ' ').slice(1);
|
||||
};
|
||||
gl.text.pluralize = function(str, count) {
|
||||
return str + (count > 1 || count === 0 ? 's' : '');
|
||||
};
|
||||
gl.text.truncate = function(string, maxLength) {
|
||||
return string.substr(0, (maxLength - 3)) + '...';
|
||||
};
|
||||
gl.text.dasherize = function(str) {
|
||||
return str.replace(/[_\s]+/g, '-');
|
||||
};
|
||||
gl.text.slugify = function(str) {
|
||||
return str.trim().toLowerCase().latinise();
|
||||
};
|
||||
|
|
|
@ -30,7 +30,6 @@ import './commit/image_file';
|
|||
import { handleLocationHash } from './lib/utils/common_utils';
|
||||
import './lib/utils/datetime_utility';
|
||||
import './lib/utils/pretty_time';
|
||||
import './lib/utils/text_utility';
|
||||
import './lib/utils/url_utility';
|
||||
|
||||
// behaviors
|
||||
|
|
|
@ -5,6 +5,7 @@ import 'vendor/jquery.waitforimages';
|
|||
import TaskList from './task_list';
|
||||
import './merge_request_tabs';
|
||||
import IssuablesHelper from './helpers/issuables_helper';
|
||||
import { addDelimiter } from './lib/utils/text_utility';
|
||||
|
||||
(function() {
|
||||
this.MergeRequest = (function() {
|
||||
|
@ -124,7 +125,7 @@ import IssuablesHelper from './helpers/issuables_helper';
|
|||
const $el = $('.nav-links .js-merge-counter');
|
||||
const count = Math.max((parseInt($el.text().replace(/[^\d]/, ''), 10) - by), 0);
|
||||
|
||||
$el.text(gl.text.addDelimiter(count));
|
||||
$el.text(addDelimiter(count));
|
||||
};
|
||||
|
||||
MergeRequest.prototype.hideCloseButton = function() {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script>
|
||||
import tooltip from '../../../vue_shared/directives/tooltip';
|
||||
import icon from '../../../vue_shared/components/icon.vue';
|
||||
|
||||
import { dasherize } from '../../../lib/utils/text_utility';
|
||||
/**
|
||||
* Renders either a cancel, retry or play icon pointing to the given path.
|
||||
* TODO: Remove UJS from here and use an async request instead.
|
||||
|
@ -39,7 +39,7 @@
|
|||
|
||||
computed: {
|
||||
cssClass() {
|
||||
const actionIconDash = gl.text.dasherize(this.actionIcon);
|
||||
const actionIconDash = dasherize(this.actionIcon);
|
||||
return `${actionIconDash} js-icon-${actionIconDash}`;
|
||||
},
|
||||
},
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import tooltip from '../../vue_shared/directives/tooltip';
|
||||
import '../../lib/utils/text_utility';
|
||||
import { pluralize } from '../../lib/utils/text_utility';
|
||||
|
||||
export default {
|
||||
name: 'MRWidgetHeader',
|
||||
|
@ -14,7 +14,7 @@ export default {
|
|||
return this.mr.divergedCommitsCount > 0;
|
||||
},
|
||||
commitsText() {
|
||||
return gl.text.pluralize('commit', this.mr.divergedCommitsCount);
|
||||
return pluralize('commit', this.mr.divergedCommitsCount);
|
||||
},
|
||||
branchNameClipboardData() {
|
||||
// This supports code in app/assets/javascripts/copy_to_clipboard.js that
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import bp from './breakpoints';
|
||||
import { slugify } from './lib/utils/text_utility';
|
||||
|
||||
export default class Wikis {
|
||||
constructor() {
|
||||
|
@ -23,7 +24,7 @@ export default class Wikis {
|
|||
if (!this.newWikiForm) return;
|
||||
|
||||
const slugInput = this.newWikiForm.querySelector('#new_wiki_path');
|
||||
const slug = gl.text.slugify(slugInput.value);
|
||||
const slug = slugify(slugInput.value);
|
||||
|
||||
if (slug.length > 0) {
|
||||
const wikisPath = slugInput.getAttribute('data-wikis-path');
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Export text utils functions as es6 module and add tests
|
||||
merge_request:
|
||||
author:
|
||||
type: other
|
|
@ -0,0 +1,62 @@
|
|||
import textUtils from '~/lib/utils/text_markdown';
|
||||
|
||||
describe('init markdown', () => {
|
||||
let textArea;
|
||||
|
||||
beforeAll(() => {
|
||||
textArea = document.createElement('textarea');
|
||||
document.querySelector('body').appendChild(textArea);
|
||||
textArea.focus();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
textArea.parentNode.removeChild(textArea);
|
||||
});
|
||||
|
||||
describe('without selection', () => {
|
||||
it('inserts the tag on an empty line', () => {
|
||||
const initialValue = '';
|
||||
|
||||
textArea.value = initialValue;
|
||||
textArea.selectionStart = 0;
|
||||
textArea.selectionEnd = 0;
|
||||
|
||||
textUtils.insertText(textArea, textArea.value, '*', null, '', false);
|
||||
|
||||
expect(textArea.value).toEqual(`${initialValue}* `);
|
||||
});
|
||||
|
||||
it('inserts the tag on a new line if the current one is not empty', () => {
|
||||
const initialValue = 'some text';
|
||||
|
||||
textArea.value = initialValue;
|
||||
textArea.setSelectionRange(initialValue.length, initialValue.length);
|
||||
|
||||
textUtils.insertText(textArea, textArea.value, '*', null, '', false);
|
||||
|
||||
expect(textArea.value).toEqual(`${initialValue}\n* `);
|
||||
});
|
||||
|
||||
it('inserts the tag on the same line if the current line only contains spaces', () => {
|
||||
const initialValue = ' ';
|
||||
|
||||
textArea.value = initialValue;
|
||||
textArea.setSelectionRange(initialValue.length, initialValue.length);
|
||||
|
||||
textUtils.insertText(textArea, textArea.value, '*', null, '', false);
|
||||
|
||||
expect(textArea.value).toEqual(`${initialValue}* `);
|
||||
});
|
||||
|
||||
it('inserts the tag on the same line if the current line only contains tabs', () => {
|
||||
const initialValue = '\t\t\t';
|
||||
|
||||
textArea.value = initialValue;
|
||||
textArea.setSelectionRange(initialValue.length, initialValue.length);
|
||||
|
||||
textUtils.insertText(textArea, textArea.value, '*', null, '', false);
|
||||
|
||||
expect(textArea.value).toEqual(`${initialValue}* `);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,109 +1,57 @@
|
|||
import { highCountTrim } from '~/lib/utils/text_utility';
|
||||
import * as textUtils from '~/lib/utils/text_utility';
|
||||
|
||||
describe('text_utility', () => {
|
||||
describe('gl.text.getTextWidth', () => {
|
||||
it('returns zero width when no text is passed', () => {
|
||||
expect(gl.text.getTextWidth('')).toBe(0);
|
||||
describe('addDelimiter', () => {
|
||||
it('should add a delimiter to the given string', () => {
|
||||
expect(textUtils.addDelimiter('1234')).toEqual('1,234');
|
||||
expect(textUtils.addDelimiter('222222')).toEqual('222,222');
|
||||
});
|
||||
|
||||
it('returns zero width when no text is passed and font is passed', () => {
|
||||
expect(gl.text.getTextWidth('', '100px sans-serif')).toBe(0);
|
||||
});
|
||||
|
||||
it('returns width when text is passed', () => {
|
||||
expect(gl.text.getTextWidth('foo') > 0).toBe(true);
|
||||
});
|
||||
|
||||
it('returns bigger width when font is larger', () => {
|
||||
const largeFont = gl.text.getTextWidth('foo', '100px sans-serif');
|
||||
const regular = gl.text.getTextWidth('foo', '10px sans-serif');
|
||||
expect(largeFont > regular).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('gl.text.pluralize', () => {
|
||||
it('returns pluralized', () => {
|
||||
expect(gl.text.pluralize('test', 2)).toBe('tests');
|
||||
});
|
||||
|
||||
it('returns pluralized when count is 0', () => {
|
||||
expect(gl.text.pluralize('test', 0)).toBe('tests');
|
||||
});
|
||||
|
||||
it('does not return pluralized', () => {
|
||||
expect(gl.text.pluralize('test', 1)).toBe('test');
|
||||
it('should not add a delimiter if string contains no numbers', () => {
|
||||
expect(textUtils.addDelimiter('aaaa')).toEqual('aaaa');
|
||||
});
|
||||
});
|
||||
|
||||
describe('highCountTrim', () => {
|
||||
it('returns 99+ for count >= 100', () => {
|
||||
expect(highCountTrim(105)).toBe('99+');
|
||||
expect(highCountTrim(100)).toBe('99+');
|
||||
expect(textUtils.highCountTrim(105)).toBe('99+');
|
||||
expect(textUtils.highCountTrim(100)).toBe('99+');
|
||||
});
|
||||
|
||||
it('returns exact number for count < 100', () => {
|
||||
expect(highCountTrim(45)).toBe(45);
|
||||
expect(textUtils.highCountTrim(45)).toBe(45);
|
||||
});
|
||||
});
|
||||
|
||||
describe('gl.text.insertText', () => {
|
||||
let textArea;
|
||||
describe('humanize', () => {
|
||||
it('should remove underscores and uppercase the first letter', () => {
|
||||
expect(textUtils.humanize('foo_bar')).toEqual('Foo bar');
|
||||
});
|
||||
});
|
||||
|
||||
beforeAll(() => {
|
||||
textArea = document.createElement('textarea');
|
||||
document.querySelector('body').appendChild(textArea);
|
||||
textArea.focus();
|
||||
describe('pluralize', () => {
|
||||
it('should pluralize given string', () => {
|
||||
expect(textUtils.pluralize('test', 2)).toBe('tests');
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
textArea.parentNode.removeChild(textArea);
|
||||
it('should pluralize when count is 0', () => {
|
||||
expect(textUtils.pluralize('test', 0)).toBe('tests');
|
||||
});
|
||||
|
||||
describe('without selection', () => {
|
||||
it('inserts the tag on an empty line', () => {
|
||||
const initialValue = '';
|
||||
it('should not pluralize when count is 1', () => {
|
||||
expect(textUtils.pluralize('test', 1)).toBe('test');
|
||||
});
|
||||
});
|
||||
|
||||
textArea.value = initialValue;
|
||||
textArea.selectionStart = 0;
|
||||
textArea.selectionEnd = 0;
|
||||
describe('dasherize', () => {
|
||||
it('should replace underscores with dashes', () => {
|
||||
expect(textUtils.dasherize('foo_bar_foo')).toEqual('foo-bar-foo');
|
||||
});
|
||||
});
|
||||
|
||||
gl.text.insertText(textArea, textArea.value, '*', null, '', false);
|
||||
|
||||
expect(textArea.value).toEqual(`${initialValue}* `);
|
||||
});
|
||||
|
||||
it('inserts the tag on a new line if the current one is not empty', () => {
|
||||
const initialValue = 'some text';
|
||||
|
||||
textArea.value = initialValue;
|
||||
textArea.setSelectionRange(initialValue.length, initialValue.length);
|
||||
|
||||
gl.text.insertText(textArea, textArea.value, '*', null, '', false);
|
||||
|
||||
expect(textArea.value).toEqual(`${initialValue}\n* `);
|
||||
});
|
||||
|
||||
it('inserts the tag on the same line if the current line only contains spaces', () => {
|
||||
const initialValue = ' ';
|
||||
|
||||
textArea.value = initialValue;
|
||||
textArea.setSelectionRange(initialValue.length, initialValue.length);
|
||||
|
||||
gl.text.insertText(textArea, textArea.value, '*', null, '', false);
|
||||
|
||||
expect(textArea.value).toEqual(`${initialValue}* `);
|
||||
});
|
||||
|
||||
it('inserts the tag on the same line if the current line only contains tabs', () => {
|
||||
const initialValue = '\t\t\t';
|
||||
|
||||
textArea.value = initialValue;
|
||||
textArea.setSelectionRange(initialValue.length, initialValue.length);
|
||||
|
||||
gl.text.insertText(textArea, textArea.value, '*', null, '', false);
|
||||
|
||||
expect(textArea.value).toEqual(`${initialValue}* `);
|
||||
});
|
||||
describe('slugify', () => {
|
||||
it('should remove accents and convert to lower case', () => {
|
||||
expect(textUtils.slugify('João')).toEqual('joão');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue