mirror of https://gitee.com/answerdev/answer.git
227 lines
5.3 KiB
TypeScript
227 lines
5.3 KiB
TypeScript
import i18next from 'i18next';
|
|
|
|
const Diff = require('diff');
|
|
|
|
function thousandthDivision(num) {
|
|
const reg = /\d{1,3}(?=(\d{3})+$)/g;
|
|
return `${num}`.replace(reg, '$&,');
|
|
}
|
|
|
|
function formatCount($num: number): string {
|
|
let res = String($num);
|
|
if (!Number.isFinite($num)) {
|
|
res = '0';
|
|
} else if ($num < 10000) {
|
|
res = thousandthDivision($num);
|
|
} else if ($num < 1000000) {
|
|
res = `${Math.round($num / 100) / 10}k`;
|
|
} else if ($num >= 1000000) {
|
|
res = `${Math.round($num / 100000) / 10}m`;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
function scrollTop(element) {
|
|
if (!element) {
|
|
return;
|
|
}
|
|
const offset = 120;
|
|
const bodyRect = document.body.getBoundingClientRect().top;
|
|
const elementRect = element.getBoundingClientRect().top;
|
|
const elementPosition = elementRect - bodyRect;
|
|
const offsetPosition = elementPosition - offset;
|
|
|
|
window.scrollTo({
|
|
top: offsetPosition,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Extract user info from markdown
|
|
* @param markdown string
|
|
* @returns Array<{displayName: string, userName: string}>
|
|
*/
|
|
function matchedUsers(markdown) {
|
|
const globalReg = /\B@([\w|]+)/g;
|
|
const reg = /\B@([\w\\_\\.]+)/;
|
|
|
|
const users = markdown.match(globalReg);
|
|
if (!users) {
|
|
return [];
|
|
}
|
|
return users.map((user) => {
|
|
const matched = user.match(reg);
|
|
return {
|
|
userName: matched[1],
|
|
};
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Identify user information from markdown
|
|
* @param markdown string
|
|
* @returns string
|
|
*/
|
|
function parseUserInfo(markdown) {
|
|
const globalReg = /\B@([\w\\_\\.\\-]+)/g;
|
|
return markdown.replace(globalReg, '[@$1](/u/$1)');
|
|
}
|
|
|
|
function formatUptime(value) {
|
|
const t = i18next.t.bind(i18next);
|
|
const second = parseInt(value, 10);
|
|
|
|
if (second > 60 * 60 && second < 60 * 60 * 24) {
|
|
return `${Math.floor(second / 3600)} ${t('dates.hour')}`;
|
|
}
|
|
if (second > 60 * 60 * 24) {
|
|
return `${Math.floor(second / 3600 / 24)} ${t('dates.day')}`;
|
|
}
|
|
|
|
return `< 1 ${t('dates.hour')}`;
|
|
}
|
|
|
|
function escapeRemove(str) {
|
|
if (!str || typeof str !== 'string') return str;
|
|
const arrEntities = {
|
|
lt: '<',
|
|
gt: '>',
|
|
nbsp: ' ',
|
|
amp: '&',
|
|
quot: '"',
|
|
'#39': "'",
|
|
};
|
|
|
|
return str.replace(/&(lt|gt|nbsp|amp|quot|#39);/gi, function (all, t) {
|
|
return arrEntities[t];
|
|
});
|
|
}
|
|
function mixColor(color_1, color_2, weight) {
|
|
function d2h(d) {
|
|
return d.toString(16);
|
|
}
|
|
function h2d(h) {
|
|
return parseInt(h, 16);
|
|
}
|
|
|
|
weight = typeof weight !== 'undefined' ? weight : 50;
|
|
let color = '#';
|
|
|
|
for (let i = 0; i <= 5; i += 2) {
|
|
const v1 = h2d(color_1.substr(i, 2));
|
|
const v2 = h2d(color_2.substr(i, 2));
|
|
let val = d2h(Math.floor(v2 + (v1 - v2) * (weight / 100.0)));
|
|
|
|
while (val.length < 2) {
|
|
val = `0${val}`;
|
|
}
|
|
|
|
color += val;
|
|
}
|
|
|
|
return color;
|
|
}
|
|
|
|
function colorRgb(sColor) {
|
|
sColor = sColor.toLowerCase();
|
|
const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
|
|
if (sColor && reg.test(sColor)) {
|
|
if (sColor.length === 4) {
|
|
let sColorNew = '#';
|
|
for (let i = 1; i < 4; i += 1) {
|
|
sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1));
|
|
}
|
|
sColor = sColorNew;
|
|
}
|
|
const sColorChange: number[] = [];
|
|
for (let i = 1; i < 7; i += 2) {
|
|
sColorChange.push(parseInt(`0x${sColor.slice(i, i + 2)}`, 16));
|
|
}
|
|
return sColorChange.join(',');
|
|
}
|
|
return sColor;
|
|
}
|
|
|
|
function labelStyle(color, hover) {
|
|
const textColor = mixColor('000000', color.replace('#', ''), 40);
|
|
const backgroundColor = mixColor('ffffff', color.replace('#', ''), 80);
|
|
const rgbBackgroundColor = colorRgb(backgroundColor);
|
|
return {
|
|
color: textColor,
|
|
backgroundColor: `rgba(${colorRgb(rgbBackgroundColor)},${hover ? 1 : 0.5})`,
|
|
};
|
|
}
|
|
|
|
function handleFormError(
|
|
error: { list: Array<{ error_field: string; error_msg: string }> },
|
|
data: any,
|
|
) {
|
|
if (error.list?.length > 0) {
|
|
error.list.forEach((item) => {
|
|
data[item.error_field].isInvalid = true;
|
|
data[item.error_field].errorMsg = item.error_msg;
|
|
});
|
|
}
|
|
return data;
|
|
}
|
|
|
|
function diffText(newText: string, oldText: string): string {
|
|
if (!newText) {
|
|
return '';
|
|
}
|
|
|
|
if (typeof oldText !== 'string') {
|
|
return newText
|
|
?.replace(/\n/gi, '<br>')
|
|
?.replace(/<kbd/gi, '<kbd')
|
|
?.replace(/<\/kbd>/gi, '</kbd>')
|
|
?.replace(/<iframe/gi, '<iframe')
|
|
?.replace(/<input/gi, '<input');
|
|
}
|
|
const diff = Diff.diffChars(oldText, newText);
|
|
const result = diff.map((part) => {
|
|
if (part.added) {
|
|
if (part.value.replace(/\n/g, '').length <= 0) {
|
|
return `<span class="review-text-add d-block">${part.value.replace(
|
|
/\n/g,
|
|
'↵\n',
|
|
)}</span>`;
|
|
}
|
|
return `<span class="review-text-add d-block">${part.value}</span>`;
|
|
}
|
|
if (part.removed) {
|
|
if (part.value.replace(/\n/g, '').length <= 0) {
|
|
return `<span class="review-text-delete text-decoration-none d-block">${part.value.replace(
|
|
/\n/g,
|
|
'↵\n',
|
|
)}</span>`;
|
|
}
|
|
return `<span class="review-text-delete">${part.value}</span>`;
|
|
}
|
|
|
|
return part.value;
|
|
});
|
|
|
|
return result
|
|
.join('')
|
|
?.replace(/<iframe/gi, '<iframe')
|
|
?.replace(/<kbd/gi, '<kbd')
|
|
?.replace(/<\/kbd>/gi, '</kbd>')
|
|
?.replace(/<input/gi, '<input');
|
|
}
|
|
|
|
export {
|
|
thousandthDivision,
|
|
formatCount,
|
|
scrollTop,
|
|
matchedUsers,
|
|
parseUserInfo,
|
|
formatUptime,
|
|
escapeRemove,
|
|
mixColor,
|
|
colorRgb,
|
|
labelStyle,
|
|
handleFormError,
|
|
diffText,
|
|
};
|