@simplysm/core-common 13.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cache/typecheck-browser.tsbuildinfo +1 -0
- package/.cache/typecheck-node.tsbuildinfo +1 -0
- package/.cache/typecheck-tests-browser.tsbuildinfo +1 -0
- package/.cache/typecheck-tests-node.tsbuildinfo +1 -0
- package/README.md +887 -0
- package/dist/common.types.d.ts +74 -0
- package/dist/common.types.d.ts.map +1 -0
- package/dist/common.types.js +5 -0
- package/dist/common.types.js.map +7 -0
- package/dist/env.d.ts +6 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +9 -0
- package/dist/env.js.map +7 -0
- package/dist/errors/argument-error.d.ts +25 -0
- package/dist/errors/argument-error.d.ts.map +1 -0
- package/dist/errors/argument-error.js +18 -0
- package/dist/errors/argument-error.js.map +7 -0
- package/dist/errors/not-implemented-error.d.ts +29 -0
- package/dist/errors/not-implemented-error.d.ts.map +1 -0
- package/dist/errors/not-implemented-error.js +14 -0
- package/dist/errors/not-implemented-error.js.map +7 -0
- package/dist/errors/sd-error.d.ts +27 -0
- package/dist/errors/sd-error.d.ts.map +1 -0
- package/dist/errors/sd-error.js +23 -0
- package/dist/errors/sd-error.js.map +7 -0
- package/dist/errors/timeout-error.d.ts +31 -0
- package/dist/errors/timeout-error.d.ts.map +1 -0
- package/dist/errors/timeout-error.js +17 -0
- package/dist/errors/timeout-error.js.map +7 -0
- package/dist/extensions/arr-ext.d.ts +15 -0
- package/dist/extensions/arr-ext.d.ts.map +1 -0
- package/dist/extensions/arr-ext.helpers.d.ts +19 -0
- package/dist/extensions/arr-ext.helpers.d.ts.map +1 -0
- package/dist/extensions/arr-ext.helpers.js +35 -0
- package/dist/extensions/arr-ext.helpers.js.map +7 -0
- package/dist/extensions/arr-ext.js +546 -0
- package/dist/extensions/arr-ext.js.map +7 -0
- package/dist/extensions/arr-ext.types.d.ts +215 -0
- package/dist/extensions/arr-ext.types.d.ts.map +1 -0
- package/dist/extensions/arr-ext.types.js +1 -0
- package/dist/extensions/arr-ext.types.js.map +7 -0
- package/dist/extensions/map-ext.d.ts +57 -0
- package/dist/extensions/map-ext.d.ts.map +1 -0
- package/dist/extensions/map-ext.js +26 -0
- package/dist/extensions/map-ext.js.map +7 -0
- package/dist/extensions/set-ext.d.ts +36 -0
- package/dist/extensions/set-ext.d.ts.map +1 -0
- package/dist/extensions/set-ext.js +29 -0
- package/dist/extensions/set-ext.js.map +7 -0
- package/dist/features/debounce-queue.d.ts +53 -0
- package/dist/features/debounce-queue.d.ts.map +1 -0
- package/dist/features/debounce-queue.js +80 -0
- package/dist/features/debounce-queue.js.map +7 -0
- package/dist/features/event-emitter.d.ts +66 -0
- package/dist/features/event-emitter.d.ts.map +1 -0
- package/dist/features/event-emitter.js +82 -0
- package/dist/features/event-emitter.js.map +7 -0
- package/dist/features/serial-queue.d.ts +47 -0
- package/dist/features/serial-queue.d.ts.map +1 -0
- package/dist/features/serial-queue.js +66 -0
- package/dist/features/serial-queue.js.map +7 -0
- package/dist/globals.d.ts +12 -0
- package/dist/globals.d.ts.map +1 -0
- package/dist/globals.js +1 -0
- package/dist/globals.js.map +7 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +7 -0
- package/dist/types/date-only.d.ts +152 -0
- package/dist/types/date-only.d.ts.map +1 -0
- package/dist/types/date-only.js +251 -0
- package/dist/types/date-only.js.map +7 -0
- package/dist/types/date-time.d.ts +96 -0
- package/dist/types/date-time.d.ts.map +1 -0
- package/dist/types/date-time.js +220 -0
- package/dist/types/date-time.js.map +7 -0
- package/dist/types/lazy-gc-map.d.ts +80 -0
- package/dist/types/lazy-gc-map.d.ts.map +1 -0
- package/dist/types/lazy-gc-map.js +179 -0
- package/dist/types/lazy-gc-map.js.map +7 -0
- package/dist/types/time.d.ts +68 -0
- package/dist/types/time.d.ts.map +1 -0
- package/dist/types/time.js +151 -0
- package/dist/types/time.js.map +7 -0
- package/dist/types/uuid.d.ts +35 -0
- package/dist/types/uuid.d.ts.map +1 -0
- package/dist/types/uuid.js +71 -0
- package/dist/types/uuid.js.map +7 -0
- package/dist/utils/bytes.d.ts +51 -0
- package/dist/utils/bytes.d.ts.map +1 -0
- package/dist/utils/bytes.js +89 -0
- package/dist/utils/bytes.js.map +7 -0
- package/dist/utils/date-format.d.ts +90 -0
- package/dist/utils/date-format.d.ts.map +1 -0
- package/dist/utils/date-format.js +106 -0
- package/dist/utils/date-format.js.map +7 -0
- package/dist/utils/json.d.ts +34 -0
- package/dist/utils/json.d.ts.map +1 -0
- package/dist/utils/json.js +152 -0
- package/dist/utils/json.js.map +7 -0
- package/dist/utils/num.d.ts +60 -0
- package/dist/utils/num.d.ts.map +1 -0
- package/dist/utils/num.js +39 -0
- package/dist/utils/num.js.map +7 -0
- package/dist/utils/obj.d.ts +258 -0
- package/dist/utils/obj.d.ts.map +1 -0
- package/dist/utils/obj.js +538 -0
- package/dist/utils/obj.js.map +7 -0
- package/dist/utils/path.d.ts +23 -0
- package/dist/utils/path.d.ts.map +1 -0
- package/dist/utils/path.js +21 -0
- package/dist/utils/path.js.map +7 -0
- package/dist/utils/primitive.d.ts +18 -0
- package/dist/utils/primitive.d.ts.map +1 -0
- package/dist/utils/primitive.js +20 -0
- package/dist/utils/primitive.js.map +7 -0
- package/dist/utils/str.d.ts +103 -0
- package/dist/utils/str.d.ts.map +1 -0
- package/dist/utils/str.js +128 -0
- package/dist/utils/str.js.map +7 -0
- package/dist/utils/template-strings.d.ts +84 -0
- package/dist/utils/template-strings.d.ts.map +1 -0
- package/dist/utils/template-strings.js +49 -0
- package/dist/utils/template-strings.js.map +7 -0
- package/dist/utils/transferable.d.ts +47 -0
- package/dist/utils/transferable.d.ts.map +1 -0
- package/dist/utils/transferable.js +153 -0
- package/dist/utils/transferable.js.map +7 -0
- package/dist/utils/wait.d.ts +19 -0
- package/dist/utils/wait.d.ts.map +1 -0
- package/dist/utils/wait.js +19 -0
- package/dist/utils/wait.js.map +7 -0
- package/dist/utils/xml.d.ts +36 -0
- package/dist/utils/xml.d.ts.map +1 -0
- package/dist/utils/xml.js +51 -0
- package/dist/utils/xml.js.map +7 -0
- package/dist/zip/sd-zip.d.ts +80 -0
- package/dist/zip/sd-zip.d.ts.map +1 -0
- package/dist/zip/sd-zip.js +153 -0
- package/dist/zip/sd-zip.js.map +7 -0
- package/package.json +31 -0
- package/src/common.types.ts +91 -0
- package/src/env.ts +11 -0
- package/src/errors/argument-error.ts +40 -0
- package/src/errors/not-implemented-error.ts +32 -0
- package/src/errors/sd-error.ts +53 -0
- package/src/errors/timeout-error.ts +36 -0
- package/src/extensions/arr-ext.helpers.ts +53 -0
- package/src/extensions/arr-ext.ts +777 -0
- package/src/extensions/arr-ext.types.ts +258 -0
- package/src/extensions/map-ext.ts +86 -0
- package/src/extensions/set-ext.ts +68 -0
- package/src/features/debounce-queue.ts +116 -0
- package/src/features/event-emitter.ts +112 -0
- package/src/features/serial-queue.ts +94 -0
- package/src/globals.ts +12 -0
- package/src/index.ts +55 -0
- package/src/types/date-only.ts +329 -0
- package/src/types/date-time.ts +294 -0
- package/src/types/lazy-gc-map.ts +244 -0
- package/src/types/time.ts +210 -0
- package/src/types/uuid.ts +113 -0
- package/src/utils/bytes.ts +160 -0
- package/src/utils/date-format.ts +239 -0
- package/src/utils/json.ts +230 -0
- package/src/utils/num.ts +97 -0
- package/src/utils/obj.ts +956 -0
- package/src/utils/path.ts +40 -0
- package/src/utils/primitive.ts +33 -0
- package/src/utils/str.ts +252 -0
- package/src/utils/template-strings.ts +132 -0
- package/src/utils/transferable.ts +269 -0
- package/src/utils/wait.ts +40 -0
- package/src/utils/xml.ts +105 -0
- package/src/zip/sd-zip.ts +218 -0
- package/tests/errors/errors.spec.ts +196 -0
- package/tests/extensions/array-extension.spec.ts +790 -0
- package/tests/extensions/map-extension.spec.ts +147 -0
- package/tests/extensions/set-extension.spec.ts +74 -0
- package/tests/types/date-only.spec.ts +636 -0
- package/tests/types/date-time.spec.ts +391 -0
- package/tests/types/lazy-gc-map.spec.ts +692 -0
- package/tests/types/time.spec.ts +559 -0
- package/tests/types/types.spec.ts +55 -0
- package/tests/types/uuid.spec.ts +91 -0
- package/tests/utils/bytes-utils.spec.ts +230 -0
- package/tests/utils/date-format.spec.ts +371 -0
- package/tests/utils/debounce-queue.spec.ts +272 -0
- package/tests/utils/json.spec.ts +475 -0
- package/tests/utils/number.spec.ts +184 -0
- package/tests/utils/object.spec.ts +827 -0
- package/tests/utils/path.spec.ts +78 -0
- package/tests/utils/primitive.spec.ts +55 -0
- package/tests/utils/sd-event-emitter.spec.ts +216 -0
- package/tests/utils/serial-queue.spec.ts +365 -0
- package/tests/utils/string.spec.ts +294 -0
- package/tests/utils/template-strings.spec.ts +96 -0
- package/tests/utils/transferable.spec.ts +698 -0
- package/tests/utils/wait.spec.ts +145 -0
- package/tests/utils/xml.spec.ts +146 -0
- package/tests/zip/sd-zip.spec.ts +234 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 경로 유틸리티 함수
|
|
3
|
+
* Node.js path 모듈 대체용 (브라우저 환경 지원)
|
|
4
|
+
*
|
|
5
|
+
* @note 이 유틸리티는 POSIX 스타일 경로(슬래시 `/`)만 지원합니다.
|
|
6
|
+
* Windows 백슬래시(`\`) 경로는 지원하지 않습니다.
|
|
7
|
+
* 브라우저 환경 및 Capacitor 플러그인용으로 설계되었습니다.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 경로 조합 (path.join 대체)
|
|
12
|
+
* @note POSIX 스타일 경로만 지원 (슬래시 `/`)
|
|
13
|
+
*/
|
|
14
|
+
export function pathJoin(...segments: string[]): string {
|
|
15
|
+
return segments
|
|
16
|
+
.map((s, i) => (i === 0 ? s.replace(/\/+$/, "") : s.replace(/^\/+|\/+$/g, "")))
|
|
17
|
+
.filter(Boolean)
|
|
18
|
+
.join("/");
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* 파일명 추출 (path.basename 대체)
|
|
23
|
+
*/
|
|
24
|
+
export function pathBasename(filePath: string, ext?: string): string {
|
|
25
|
+
const name = filePath.split("/").pop() ?? "";
|
|
26
|
+
if (ext != null && ext !== "" && name.endsWith(ext)) {
|
|
27
|
+
return name.slice(0, -ext.length);
|
|
28
|
+
}
|
|
29
|
+
return name;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* 확장자 추출 (path.extname 대체)
|
|
34
|
+
* @note 숨김 파일(예: `.gitignore`)은 빈 문자열을 반환합니다 (Node.js path.extname과 동일)
|
|
35
|
+
*/
|
|
36
|
+
export function pathExtname(filePath: string): string {
|
|
37
|
+
const name = filePath.split("/").pop() ?? "";
|
|
38
|
+
const dotIndex = name.lastIndexOf(".");
|
|
39
|
+
return dotIndex > 0 ? name.slice(dotIndex) : "";
|
|
40
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { DateTime } from "../types/date-time";
|
|
2
|
+
import { DateOnly } from "../types/date-only";
|
|
3
|
+
import { Time } from "../types/time";
|
|
4
|
+
import { Uuid } from "../types/uuid";
|
|
5
|
+
import { ArgumentError } from "../errors/argument-error";
|
|
6
|
+
import type { PrimitiveTypeMap, PrimitiveTypeStr } from "../common.types";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 값에서 PrimitiveTypeStr 추론
|
|
10
|
+
*
|
|
11
|
+
* 런타임에서 값의 타입을 검사하여 해당하는 PrimitiveTypeStr을 반환합니다.
|
|
12
|
+
*
|
|
13
|
+
* @param value 타입을 추론할 값
|
|
14
|
+
* @returns 값에 해당하는 PrimitiveTypeStr
|
|
15
|
+
* @throws ArgumentError 지원하지 않는 타입인 경우
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* getPrimitiveTypeStr("hello") // "string"
|
|
19
|
+
* getPrimitiveTypeStr(123) // "number"
|
|
20
|
+
* getPrimitiveTypeStr(new DateTime()) // "DateTime"
|
|
21
|
+
* getPrimitiveTypeStr(new Uint8Array()) // "Bytes"
|
|
22
|
+
*/
|
|
23
|
+
export function getPrimitiveTypeStr(value: PrimitiveTypeMap[PrimitiveTypeStr]): PrimitiveTypeStr {
|
|
24
|
+
if (typeof value === "string") return "string";
|
|
25
|
+
if (typeof value === "number") return "number";
|
|
26
|
+
if (typeof value === "boolean") return "boolean";
|
|
27
|
+
if (value instanceof DateTime) return "DateTime";
|
|
28
|
+
if (value instanceof DateOnly) return "DateOnly";
|
|
29
|
+
if (value instanceof Time) return "Time";
|
|
30
|
+
if (value instanceof Uuid) return "Uuid";
|
|
31
|
+
if (value instanceof Uint8Array) return "Bytes";
|
|
32
|
+
throw new ArgumentError("알 수 없는 값 타입입니다.", { type: typeof value });
|
|
33
|
+
}
|
package/src/utils/str.ts
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 문자열 유틸리티 함수
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
//#region 한글 조사 처리
|
|
6
|
+
|
|
7
|
+
// 한글 조사 매핑 테이블 (모듈 로드 시 1회만 생성)
|
|
8
|
+
const suffixTable = {
|
|
9
|
+
을: { t: "을", f: "를" },
|
|
10
|
+
은: { t: "은", f: "는" },
|
|
11
|
+
이: { t: "이", f: "가" },
|
|
12
|
+
와: { t: "과", f: "와" },
|
|
13
|
+
랑: { t: "이랑", f: "랑" },
|
|
14
|
+
로: { t: "으로", f: "로" },
|
|
15
|
+
라: { t: "이라", f: "라" },
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 한글 조사를 받침에 따라 적절히 반환
|
|
20
|
+
* @param text 텍스트
|
|
21
|
+
* @param type 조사 타입
|
|
22
|
+
* - `"을"`: 을/를
|
|
23
|
+
* - `"은"`: 은/는
|
|
24
|
+
* - `"이"`: 이/가
|
|
25
|
+
* - `"와"`: 과/와
|
|
26
|
+
* - `"랑"`: 이랑/랑
|
|
27
|
+
* - `"로"`: 으로/로
|
|
28
|
+
* - `"라"`: 이라/라
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* getSuffix("사과", "을") // "를"
|
|
32
|
+
* getSuffix("책", "이") // "이"
|
|
33
|
+
*/
|
|
34
|
+
export function strGetSuffix(text: string, type: "을" | "은" | "이" | "와" | "랑" | "로" | "라"): string {
|
|
35
|
+
const table = suffixTable;
|
|
36
|
+
|
|
37
|
+
// 빈 문자열 또는 마지막 글자가 한글이 아닌 경우 받침 없음으로 처리
|
|
38
|
+
if (text.length === 0) {
|
|
39
|
+
return table[type].f;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const lastCharCode = text.charCodeAt(text.length - 1);
|
|
43
|
+
|
|
44
|
+
// 한글 범위 체크 (0xAC00 ~ 0xD7A3)
|
|
45
|
+
if (lastCharCode < 0xac00 || lastCharCode > 0xd7a3) {
|
|
46
|
+
return table[type].f;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// 받침 존재 여부 및 종성 인덱스 계산
|
|
50
|
+
const jongseongIndex = (lastCharCode - 0xac00) % 28;
|
|
51
|
+
const hasLast = jongseongIndex !== 0;
|
|
52
|
+
|
|
53
|
+
// "로" 조사는 받침 ㄹ(종성 인덱스 8)일 때 "로"로 처리
|
|
54
|
+
if (type === "로" && jongseongIndex === 8) {
|
|
55
|
+
return table[type].f;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return hasLast ? table[type].t : table[type].f;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
//#endregion
|
|
62
|
+
|
|
63
|
+
//#region 전각→반각 변환
|
|
64
|
+
|
|
65
|
+
// 전각 → 반각 매핑 테이블 (모듈 로드 시 1회만 생성)
|
|
66
|
+
const specialCharMap: Record<string, string> = {
|
|
67
|
+
"A": "A",
|
|
68
|
+
"B": "B",
|
|
69
|
+
"C": "C",
|
|
70
|
+
"D": "D",
|
|
71
|
+
"E": "E",
|
|
72
|
+
"F": "F",
|
|
73
|
+
"G": "G",
|
|
74
|
+
"H": "H",
|
|
75
|
+
"I": "I",
|
|
76
|
+
"J": "J",
|
|
77
|
+
"K": "K",
|
|
78
|
+
"L": "L",
|
|
79
|
+
"M": "M",
|
|
80
|
+
"N": "N",
|
|
81
|
+
"O": "O",
|
|
82
|
+
"P": "P",
|
|
83
|
+
"Q": "Q",
|
|
84
|
+
"R": "R",
|
|
85
|
+
"S": "S",
|
|
86
|
+
"T": "T",
|
|
87
|
+
"U": "U",
|
|
88
|
+
"V": "V",
|
|
89
|
+
"W": "W",
|
|
90
|
+
"X": "X",
|
|
91
|
+
"Y": "Y",
|
|
92
|
+
"Z": "Z",
|
|
93
|
+
"a": "a",
|
|
94
|
+
"b": "b",
|
|
95
|
+
"c": "c",
|
|
96
|
+
"d": "d",
|
|
97
|
+
"e": "e",
|
|
98
|
+
"f": "f",
|
|
99
|
+
"g": "g",
|
|
100
|
+
"h": "h",
|
|
101
|
+
"i": "i",
|
|
102
|
+
"j": "j",
|
|
103
|
+
"k": "k",
|
|
104
|
+
"l": "l",
|
|
105
|
+
"m": "m",
|
|
106
|
+
"n": "n",
|
|
107
|
+
"o": "o",
|
|
108
|
+
"p": "p",
|
|
109
|
+
"q": "q",
|
|
110
|
+
"r": "r",
|
|
111
|
+
"s": "s",
|
|
112
|
+
"t": "t",
|
|
113
|
+
"u": "u",
|
|
114
|
+
"v": "v",
|
|
115
|
+
"w": "w",
|
|
116
|
+
"x": "x",
|
|
117
|
+
"y": "y",
|
|
118
|
+
"z": "z",
|
|
119
|
+
"0": "0",
|
|
120
|
+
"1": "1",
|
|
121
|
+
"2": "2",
|
|
122
|
+
"3": "3",
|
|
123
|
+
"4": "4",
|
|
124
|
+
"5": "5",
|
|
125
|
+
"6": "6",
|
|
126
|
+
"7": "7",
|
|
127
|
+
"8": "8",
|
|
128
|
+
"9": "9",
|
|
129
|
+
" ": " ",
|
|
130
|
+
")": ")",
|
|
131
|
+
"(": "(",
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
// 정규식도 1회만 생성
|
|
135
|
+
const specialCharRegex = new RegExp(`[${Object.keys(specialCharMap).join("")}]`, "g");
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* 전각(Full-width) 문자를 반각(Half-width) 문자로 변환
|
|
139
|
+
*
|
|
140
|
+
* 변환 대상:
|
|
141
|
+
* - 전각 영문 대문자 (A-Z → A-Z)
|
|
142
|
+
* - 전각 영문 소문자 (a-z → a-z)
|
|
143
|
+
* - 전각 숫자 (0-9 → 0-9)
|
|
144
|
+
* - 전각 공백 ( → 일반 공백)
|
|
145
|
+
* - 전각 괄호 (() → ())
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* replaceSpecialDefaultChar("A123") // "A123"
|
|
149
|
+
* replaceSpecialDefaultChar("(株)") // "(株)"
|
|
150
|
+
*/
|
|
151
|
+
export function strReplaceFullWidth(str: string): string {
|
|
152
|
+
return str.replace(specialCharRegex, (char) => specialCharMap[char] ?? char);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
//#endregion
|
|
156
|
+
|
|
157
|
+
//#region 케이스 변환
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* PascalCase로 변환
|
|
161
|
+
* @example "hello-world" → "HelloWorld"
|
|
162
|
+
* @example "hello_world" → "HelloWorld"
|
|
163
|
+
* @example "hello.world" → "HelloWorld"
|
|
164
|
+
*/
|
|
165
|
+
export function strToPascalCase(str: string): string {
|
|
166
|
+
return str.replace(/[-._][a-z]/g, (m) => m[1].toUpperCase()).replace(/^[a-z]/, (m) => m.toUpperCase());
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* camelCase로 변환
|
|
171
|
+
* @example "hello-world" → "helloWorld"
|
|
172
|
+
* @example "hello_world" → "helloWorld"
|
|
173
|
+
* @example "HelloWorld" → "helloWorld"
|
|
174
|
+
*/
|
|
175
|
+
export function strToCamelCase(str: string): string {
|
|
176
|
+
return str.replace(/[-._][a-z]/g, (m) => m[1].toUpperCase()).replace(/^[A-Z]/, (m) => m.toLowerCase());
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* kebab-case로 변환
|
|
181
|
+
*
|
|
182
|
+
* @example "HelloWorld" → "hello-world"
|
|
183
|
+
* @example "helloWorld" → "hello-world"
|
|
184
|
+
* @example "hello_world" → "hello_world" (소문자만 있으면 변환 안됨)
|
|
185
|
+
* @example "Hello_World" → "hello-_world" (기존 분리자는 유지됨)
|
|
186
|
+
* @example "Hello-World" → "hello--world" (기존 분리자는 유지됨)
|
|
187
|
+
* @example "XMLParser" → "x-m-l-parser" (연속된 대문자는 각각 분리됨)
|
|
188
|
+
*/
|
|
189
|
+
export function strToKebabCase(str: string): string {
|
|
190
|
+
return toCaseWithSeparator(str, "-");
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* snake_case로 변환
|
|
195
|
+
*
|
|
196
|
+
* @example "HelloWorld" → "hello_world"
|
|
197
|
+
* @example "helloWorld" → "hello_world"
|
|
198
|
+
* @example "hello-world" → "hello-world" (소문자만 있으면 변환 안됨)
|
|
199
|
+
* @example "Hello-World" → "hello_-world" (기존 분리자는 유지됨)
|
|
200
|
+
* @example "Hello_World" → "hello__world" (기존 분리자는 유지됨)
|
|
201
|
+
* @example "XMLParser" → "x_m_l_parser" (연속된 대문자는 각각 분리됨)
|
|
202
|
+
*/
|
|
203
|
+
export function strToSnakeCase(str: string): string {
|
|
204
|
+
return toCaseWithSeparator(str, "_");
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function toCaseWithSeparator(str: string, separator: string): string {
|
|
208
|
+
return str.replace(/^[A-Z]/, (m) => m.toLowerCase()).replace(/[-_]?[A-Z]/g, (m) => separator + m.toLowerCase());
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
//#endregion
|
|
212
|
+
|
|
213
|
+
//#region 기타
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* undefined 또는 빈 문자열 여부 체크 (타입 가드)
|
|
217
|
+
*
|
|
218
|
+
* @param str 체크할 문자열
|
|
219
|
+
* @returns undefined, null, 빈 문자열이면 true
|
|
220
|
+
*
|
|
221
|
+
* @example
|
|
222
|
+
* const name: string | undefined = getValue();
|
|
223
|
+
* if (strIsNullOrEmpty(name)) {
|
|
224
|
+
* // name: "" | undefined
|
|
225
|
+
* console.log("이름이 비어있습니다");
|
|
226
|
+
* } else {
|
|
227
|
+
* // name: string (비어있지 않은 문자열)
|
|
228
|
+
* console.log(`이름: ${name}`);
|
|
229
|
+
* }
|
|
230
|
+
*/
|
|
231
|
+
export function strIsNullOrEmpty(str: string | undefined): str is "" | undefined {
|
|
232
|
+
return str == null || str === "";
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* 문자열 특정 위치에 삽입
|
|
237
|
+
*
|
|
238
|
+
* @param str 원본 문자열
|
|
239
|
+
* @param index 삽입할 위치 (0부터 시작)
|
|
240
|
+
* @param insertString 삽입할 문자열
|
|
241
|
+
* @returns 삽입된 새 문자열
|
|
242
|
+
*
|
|
243
|
+
* @example
|
|
244
|
+
* strInsert("Hello World", 5, ","); // "Hello, World"
|
|
245
|
+
* strInsert("abc", 0, "X"); // "Xabc"
|
|
246
|
+
* strInsert("abc", 3, "X"); // "abcX"
|
|
247
|
+
*/
|
|
248
|
+
export function strInsert(str: string, index: number, insertString: string): string {
|
|
249
|
+
return str.substring(0, index) + insertString + str.substring(index);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
//#endregion
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 템플릿 문자열 태그 함수들
|
|
3
|
+
* IDE 코드 하이라이팅 지원용 (실제 동작은 문자열 조합 + 들여쓰기 정리)
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* JavaScript 코드 하이라이팅용 템플릿 태그
|
|
8
|
+
* @param strings 템플릿 문자열 배열
|
|
9
|
+
* @param values 보간된 값들
|
|
10
|
+
* @returns 들여쓰기가 정리된 문자열
|
|
11
|
+
* @example
|
|
12
|
+
* const code = js`
|
|
13
|
+
* function hello() {
|
|
14
|
+
* return "world";
|
|
15
|
+
* }
|
|
16
|
+
* `;
|
|
17
|
+
*/
|
|
18
|
+
export function js(strings: TemplateStringsArray, ...values: unknown[]): string {
|
|
19
|
+
return _combine(strings, values);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* TypeScript 코드 하이라이팅용 템플릿 태그
|
|
24
|
+
* @param strings 템플릿 문자열 배열
|
|
25
|
+
* @param values 보간된 값들
|
|
26
|
+
* @returns 들여쓰기가 정리된 문자열
|
|
27
|
+
* @example
|
|
28
|
+
* const code = ts`
|
|
29
|
+
* interface User {
|
|
30
|
+
* name: string;
|
|
31
|
+
* age: number;
|
|
32
|
+
* }
|
|
33
|
+
* `;
|
|
34
|
+
*/
|
|
35
|
+
export function ts(strings: TemplateStringsArray, ...values: unknown[]): string {
|
|
36
|
+
return _combine(strings, values);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* HTML 마크업 하이라이팅용 템플릿 태그
|
|
41
|
+
* @param strings 템플릿 문자열 배열
|
|
42
|
+
* @param values 보간된 값들
|
|
43
|
+
* @returns 들여쓰기가 정리된 문자열
|
|
44
|
+
* @example
|
|
45
|
+
* const markup = html`
|
|
46
|
+
* <div class="container">
|
|
47
|
+
* <span>${name}</span>
|
|
48
|
+
* </div>
|
|
49
|
+
* `;
|
|
50
|
+
*/
|
|
51
|
+
export function html(strings: TemplateStringsArray, ...values: unknown[]): string {
|
|
52
|
+
return _combine(strings, values);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* MSSQL T-SQL 하이라이팅용 템플릿 태그
|
|
57
|
+
* @param strings 템플릿 문자열 배열
|
|
58
|
+
* @param values 보간된 값들
|
|
59
|
+
* @returns 들여쓰기가 정리된 문자열
|
|
60
|
+
* @example
|
|
61
|
+
* const query = tsql`
|
|
62
|
+
* SELECT TOP 10 *
|
|
63
|
+
* FROM Users
|
|
64
|
+
* WHERE Name LIKE '%${keyword}%'
|
|
65
|
+
* `;
|
|
66
|
+
*/
|
|
67
|
+
export function tsql(strings: TemplateStringsArray, ...values: unknown[]): string {
|
|
68
|
+
return _combine(strings, values);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* MySQL SQL 하이라이팅용 템플릿 태그
|
|
73
|
+
* @param strings 템플릿 문자열 배열
|
|
74
|
+
* @param values 보간된 값들
|
|
75
|
+
* @returns 들여쓰기가 정리된 문자열
|
|
76
|
+
* @example
|
|
77
|
+
* const query = mysql`
|
|
78
|
+
* SELECT *
|
|
79
|
+
* FROM users
|
|
80
|
+
* LIMIT 10
|
|
81
|
+
* `;
|
|
82
|
+
*/
|
|
83
|
+
export function mysql(strings: TemplateStringsArray, ...values: unknown[]): string {
|
|
84
|
+
return _combine(strings, values);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* PostgreSQL SQL 하이라이팅용 템플릿 태그
|
|
89
|
+
* @param strings 템플릿 문자열 배열
|
|
90
|
+
* @param values 보간된 값들
|
|
91
|
+
* @returns 들여쓰기가 정리된 문자열
|
|
92
|
+
* @example
|
|
93
|
+
* const query = pgsql`
|
|
94
|
+
* SELECT *
|
|
95
|
+
* FROM users
|
|
96
|
+
* OFFSET 0 LIMIT 10
|
|
97
|
+
* `;
|
|
98
|
+
*/
|
|
99
|
+
export function pgsql(strings: TemplateStringsArray, ...values: unknown[]): string {
|
|
100
|
+
return _combine(strings, values);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function _combine(strings: TemplateStringsArray, values: unknown[]): string {
|
|
104
|
+
const raw = strings.reduce((result, str, i) => {
|
|
105
|
+
const value = values[i] !== undefined ? String(values[i]) : "";
|
|
106
|
+
return result + str + value;
|
|
107
|
+
}, "");
|
|
108
|
+
return _trimIndent(raw);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function _trimIndent(text: string): string {
|
|
112
|
+
const lines = text.split("\n");
|
|
113
|
+
|
|
114
|
+
// 첫/마지막 빈 줄 제거 (연속된 빈 줄 모두 제거)
|
|
115
|
+
while (lines.length > 0 && lines[0].trim() === "") {
|
|
116
|
+
lines.shift();
|
|
117
|
+
}
|
|
118
|
+
while (lines.length > 0 && lines[lines.length - 1].trim() === "") {
|
|
119
|
+
lines.pop();
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// 최소 들여쓰기 계산
|
|
123
|
+
const minIndent = lines
|
|
124
|
+
.filter((line) => line.trim() !== "")
|
|
125
|
+
.reduce((min, line) => {
|
|
126
|
+
const indent = line.match(/^ */)?.[0].length ?? 0;
|
|
127
|
+
return Math.min(min, indent);
|
|
128
|
+
}, Infinity);
|
|
129
|
+
|
|
130
|
+
// 들여쓰기 제거
|
|
131
|
+
return lines.map((line) => (line.trim() === "" ? "" : line.slice(minIndent))).join("\n");
|
|
132
|
+
}
|