refac: escapeHtml, nl2br, TemplateEngine 분리

This commit is contained in:
2021-08-26 01:37:46 +09:00
parent 3b9884160b
commit 5a0a8bedc1
9 changed files with 76 additions and 82 deletions
+2 -1
View File
@@ -2,7 +2,8 @@
import axios from 'axios';
import $ from 'jquery';
import { trim } from 'lodash';
import { escapeHtml, nl2br } from './common_legacy';
import { escapeHtml } from "./legacy/escapeHtml";
import { nl2br } from "./util/nl2br";
import { InvalidResponse } from './defs';
import { convertFormData } from './util/convertFormData';
import { setAxiosXMLHttpRequest } from './util/setAxiosXMLHttpRequest';
+4 -4
View File
@@ -1,4 +1,7 @@
import { activeFlip, escapeHtml, isInt, mb_strwidth, mb_strimwidth, convertDictById, convertSet, hexToRgb, isBrightColor, convColorValue, numberWithCommas, linkifyStrWithOpt, TemplateEngine, getIconPath, combineObject, combineArray, activeFlipItem, errUnknown, errUnknownToast, quickReject, nl2br, getNpcColor, initTooltip } from "./common_legacy";
import { activeFlip, mb_strwidth, mb_strimwidth, convertDictById, convertSet, hexToRgb, isBrightColor, convColorValue, numberWithCommas, linkifyStrWithOpt, getIconPath, combineObject, combineArray, activeFlipItem, errUnknown, errUnknownToast, quickReject, getNpcColor, initTooltip } from "./common_legacy";
import { TemplateEngine } from "./util/TemplateEngine";
import { escapeHtml } from "./legacy/escapeHtml";
import { nl2br } from "./util/nl2br";
import jQuery from "jquery";
window.jQuery = jQuery;
window.$ = jQuery;
@@ -22,8 +25,6 @@ declare global {
/** @deprecated Module 사용할 것 */
escapeHtml: typeof escapeHtml;
/** @deprecated Module 사용할 것 */
isInt: typeof isInt;
/** @deprecated Module 사용할 것 */
mb_strwidth: typeof mb_strwidth;
/** @deprecated Module 사용할 것 */
mb_strimwidth: typeof mb_strimwidth;
@@ -69,7 +70,6 @@ declare global {
}
window.escapeHtml = escapeHtml;
window.isInt = isInt;
window.mb_strwidth = mb_strwidth;
window.mb_strimwidth = mb_strimwidth;
window.convertDictById = convertDictById;
-74
View File
@@ -8,38 +8,6 @@ import axios from "axios";
axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
//TODO: X-Requested-With 믿지 말자.
/**
* <>& 등을 html에서도 그대로 보이도록 escape주는 함수
* @see https://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery
*/
export const escapeHtml = (() => {
const entityMap: { [v: string]: string } = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#39;',
'/': '&#x2F;',
'`': '&#x60;',
'=': '&#x3D;'
};
return function (string: string) {
return String(string).replace(/[&<>"'`=/]/g, function (s: string) {
return entityMap[s];
});
}
})();
/**
* 변수가 정수인지 확인하는 함수
* @param {*} n 정수인지 확인하기 위한 인자
* @return {boolean} 정수인지 여부
*/
export function isInt(n: unknown): n is number {
const v = n as number;
return +v === v && !(v % 1);
}
//https://gist.github.com/demouth/3217440
@@ -196,45 +164,6 @@ export function linkifyStrWithOpt(text: string): string {
return window.linkifyStr(text, {});
}
/**
* 단순한 Template 함수. <%변수명%>으로 template 가능
* @see https://github.com/krasimir/absurd/blob/master/lib/processors/html/helpers/TemplateEngine.js
* @param {string} html
* @param {object} options
* @returns {string}
*/
export function TemplateEngine(html: string, options: Record<string | number, unknown> = {}): string {
const re = /<%(.+?)%>/g;
const reExp = /(^( )?(var|if|for|else|switch|case|break|{|}|;))(.*)?/g;
const code = ['with(obj) { var r=[];\n'];
let cursor = 0;
const add = function (line: string, js?: boolean) {
js ? code.push(line.match(reExp) ? line + '\n' : 'r.push(' + line + ');\n') :
code.push(line != '' ? 'r.push("' + line.replace(/"/g, '\\"') + '");\n' : '');
return add;
}
options.e = escapeHtml;
options.linkifyStr = linkifyStrWithOpt;
for (; ;) {
const match = re.exec(html);
if (!match) {
break;
}
add(html.slice(cursor, match.index))(match[1], true);
cursor = match.index + match[0].length;
}
add(html.substr(cursor, html.length - cursor));
code.push('return r.join(""); }');
const compiledCode = code.join('').replace(/[\r\t\n]/g, ' ');
try {
return new Function('obj', compiledCode).apply(options, [options]);
} catch (err) {
console.error("'" + err.message + "'", " in \n\nCode:\n", code, "\n");
throw err;
}
}
export function getIconPath(imgsvr: boolean | 1 | 0, picture: string): string {
// ../d_shared/common_path.js 필요
if (!imgsvr) {
@@ -326,9 +255,6 @@ export function quickReject<T>(errMsg: string): JQuery.Promise<T> {
return deferred.promise();
}
export function nl2br(text: string): string {
return text.replace(/\n/g, "<br>");
}
/*
function br2nl (text) {
return text.replace(/<\s*\/?br\s*[\/]?>/gi, '\n');
+19
View File
@@ -0,0 +1,19 @@
/**
* <>& 등을 html에서도 그대로 보이도록 escape주는 함수
* @see https://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery
*/
const entityMap: { [v: string]: string } = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#39;',
'/': '&#x2F;',
'`': '&#x60;',
'=': '&#x3D;'
};
export function escapeHtml(string: string): string{
return String(string).replace(/[&<>"'`=/]/g, function (s: string) {
return entityMap[s];
});
}
+2 -1
View File
@@ -1,5 +1,6 @@
import axios from 'axios';
import { errUnknown, getIconPath, TemplateEngine } from './common_legacy';
import { errUnknown, getIconPath } from './common_legacy';
import { TemplateEngine } from "./util/TemplateEngine";
import { GeneralListResponse, InvalidResponse } from './defs';
import { convertFormData } from './util/convertFormData';
import { unwrap_any } from './util/unwrap_any';
+42
View File
@@ -0,0 +1,42 @@
import { escapeHtml } from "../legacy/escapeHtml";
import { linkifyStrWithOpt } from "../common_legacy";
/**
* 단순한 Template 함수. <%변수명%>으로 template 가능
* @see https://github.com/krasimir/absurd/blob/master/lib/processors/html/helpers/TemplateEngine.js
* @param {string} html
* @param {object} options
* @returns {string}
*/
export function TemplateEngine(html: string, options: Record<string | number, unknown> = {}): string {
const re = /<%(.+?)%>/g;
const reExp = /(^( )?(var|if|for|else|switch|case|break|{|}|;))(.*)?/g;
const code = ['with(obj) { var r=[];\n'];
let cursor = 0;
const add = function (line: string, js?: boolean) {
js ? code.push(line.match(reExp) ? line + '\n' : 'r.push(' + line + ');\n') :
code.push(line != '' ? 'r.push("' + line.replace(/"/g, '\\"') + '");\n' : '');
return add;
};
options.e = escapeHtml;
options.linkifyStr = linkifyStrWithOpt;
for (; ;) {
const match = re.exec(html);
if (!match) {
break;
}
add(html.slice(cursor, match.index))(match[1], true);
cursor = match.index + match[0].length;
}
add(html.substr(cursor, html.length - cursor));
code.push('return r.join(""); }');
const compiledCode = code.join('').replace(/[\r\t\n]/g, ' ');
try {
return new Function('obj', compiledCode).apply(options, [options]);
} catch (err) {
console.error("'" + err.message + "'", " in \n\nCode:\n", code, "\n");
throw err;
}
}
+4
View File
@@ -0,0 +1,4 @@
export function nl2br(text: string): string {
return text.replace(/\n/g, "<br>");
}
+1 -1
View File
@@ -4,7 +4,7 @@ import axios from 'axios';
import { setAxiosXMLHttpRequest } from '../hwe/ts/util/setAxiosXMLHttpRequest';
import { InvalidResponse } from '../hwe/ts/defs';
import { convertFormData } from '../hwe/ts/util/convertFormData';
import { TemplateEngine } from '../hwe/ts/common_legacy';
import { TemplateEngine } from "../hwe/ts/util/TemplateEngine";
import { unwrap_any } from '../hwe/ts/util/unwrap_any';
import { unwrap } from '../hwe/ts/util/unwrap';
+2 -1
View File
@@ -1,6 +1,7 @@
import axios from 'axios';
import $ from 'jquery';
import { initTooltip, TemplateEngine } from '../hwe/ts/common_legacy';
import { initTooltip } from '../hwe/ts/common_legacy';
import { TemplateEngine } from "../hwe/ts/util/TemplateEngine";
import { InvalidResponse } from '../hwe/ts/defs';
import { getDateTimeNow } from '../hwe/ts/util/getDateTimeNow';
import { setAxiosXMLHttpRequest } from '../hwe/ts/util/setAxiosXMLHttpRequest';