ansuko 1.1.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.
@@ -0,0 +1,149 @@
1
+ import { haifun } from "../util.js";
2
+ const ansukoJaPlugin = (ansuko) => {
3
+ const _ = ansuko;
4
+ const kanaMap = {
5
+ 'ガ': 'ガ', 'ギ': 'ギ', 'グ': 'グ', 'ゲ': 'ゲ', 'ゴ': 'ゴ',
6
+ 'ザ': 'ザ', 'ジ': 'ジ', 'ズ': 'ズ', 'ゼ': 'ゼ', 'ゾ': 'ゾ',
7
+ 'ダ': 'ダ', 'ヂ': 'ヂ', 'ヅ': 'ヅ', 'デ': 'デ', 'ド': 'ド',
8
+ 'バ': 'バ', 'ビ': 'ビ', 'ブ': 'ブ', 'ベ': 'ベ', 'ボ': 'ボ',
9
+ 'パ': 'パ', 'ピ': 'ピ', 'プ': 'プ', 'ペ': 'ペ', 'ポ': 'ポ',
10
+ 'ヴ': 'ヴ', 'ヷ': 'ヷ', 'ヺ': 'ヺ',
11
+ 'ア': 'ア', 'イ': 'イ', 'ウ': 'ウ', 'エ': 'エ', 'オ': 'オ',
12
+ 'カ': 'カ', 'キ': 'キ', 'ク': 'ク', 'ケ': 'ケ', 'コ': 'コ',
13
+ 'サ': 'サ', 'シ': 'シ', 'ス': 'ス', 'セ': 'セ', 'ソ': 'ソ',
14
+ 'タ': 'タ', 'チ': 'チ', 'ツ': 'ツ', 'テ': 'テ', 'ト': 'ト',
15
+ 'ナ': 'ナ', 'ニ': 'ニ', 'ヌ': 'ヌ', 'ネ': 'ネ', 'ノ': 'ノ',
16
+ 'ハ': 'ハ', 'ヒ': 'ヒ', 'フ': 'フ', 'ヘ': 'ヘ', 'ホ': 'ホ',
17
+ 'マ': 'マ', 'ミ': 'ミ', 'ム': 'ム', 'メ': 'メ', 'モ': 'モ',
18
+ 'ヤ': 'ヤ', 'ユ': 'ユ', 'ヨ': 'ヨ',
19
+ 'ラ': 'ラ', 'リ': 'リ', 'ル': 'ル', 'レ': 'レ', 'ロ': 'ロ',
20
+ 'ワ': 'ワ', 'ヲ': 'ヲ', 'ン': 'ン',
21
+ 'ァ': 'ァ', 'ィ': 'ィ', 'ゥ': 'ゥ', 'ェ': 'ェ', 'ォ': 'ォ',
22
+ 'ッ': 'ッ', 'ャ': 'ャ', 'ュ': 'ュ', 'ョ': 'ョ',
23
+ '。': '。', '、': '、', 'ー': 'ー', '「': '「', '」': '」', '・': '・', '\\)': ')', '\\(': '('
24
+ };
25
+ /**
26
+ * Converts half-width katakana to full-width.
27
+ * @param str - String
28
+ * @returns Full-width katakana or null
29
+ * @example _.kanaToFull('ガギ') // 'ガギ'
30
+ * @category Japanese Utilities
31
+ */
32
+ const kanaToFull = (str) => {
33
+ if (!_.isValidStr(str)) {
34
+ return null;
35
+ }
36
+ const regex = new RegExp(`(${Object.keys(kanaMap).join('|')})`, 'g');
37
+ return str.replace(regex, m => kanaMap[m]);
38
+ };
39
+ /**
40
+ * Converts full-width katakana to half-width (dakuten may split into two characters).
41
+ * @param str - String
42
+ * @returns Half-width katakana or null
43
+ * @example _.kanaToHalf('ガギ') // 'ガギ'
44
+ * @category Japanese Utilities
45
+ */
46
+ const kanaToHalf = (str) => {
47
+ if (!_.isValidStr(str)) {
48
+ return null;
49
+ }
50
+ const reverseMap = _.invert(kanaMap);
51
+ const sortedKeys = Object.keys(reverseMap)
52
+ .sort((v1, v2) => _.size(v2) - _.size(v1));
53
+ const regex = new RegExp(`(${sortedKeys.join('|')})`, 'g');
54
+ return str.replace(regex, m => reverseMap[m]);
55
+ };
56
+ /**
57
+ * Converts katakana to hiragana; half-width input is converted to full-width first.
58
+ * @param str - String
59
+ * @returns Hiragana or null
60
+ * @example _.kanaToHira('アイウ') // 'あいう'
61
+ * @category Japanese Utilities
62
+ */
63
+ const kanaToHira = (str) => {
64
+ if (!_.isValidStr(str)) {
65
+ return null;
66
+ }
67
+ return kanaToFull(str)?.replace(/[\u30a1-\u30f6]/g, s => String.fromCharCode(s.charCodeAt(0) - 0x60)) ?? null;
68
+ };
69
+ /**
70
+ * Converts hiragana to katakana.
71
+ * @param str - String
72
+ * @returns Katakana or null
73
+ * @example _.hiraToKana('あいう') // 'アイウ'
74
+ * @category Japanese Utilities
75
+ */
76
+ const hiraToKana = (str) => {
77
+ if (!_.isValidStr(str)) {
78
+ return null;
79
+ }
80
+ return str.replace(/[\u3041-\u3096]/g, s => String.fromCharCode(s.charCodeAt(0) + 0x60)) ?? null;
81
+ };
82
+ /**
83
+ * Converts half-width characters to full-width; optionally normalizes hyphens.
84
+ * @param value - Value to convert
85
+ * @param withHaifun - Hyphen replacement character
86
+ * @returns Full-width string or null
87
+ * @example _.toFullWidth('ABC-123','ー') // 'ABCー123'
88
+ * @category Japanese Utilities
89
+ */
90
+ const toFullWidth = (value, withHaifun) => {
91
+ if (_.isNil(value)) {
92
+ return null;
93
+ }
94
+ const withFullKana = kanaToFull(String(value));
95
+ if (_.isNil(withFullKana)) {
96
+ return null;
97
+ }
98
+ const str = withFullKana.split('').map(char => {
99
+ const code = char.charCodeAt(0);
100
+ // スペース
101
+ if (code === 0x0020) {
102
+ return '\u3000'; // 全角スペース
103
+ }
104
+ // 全角は0x0021~0x007E、半角は0xFF01~0xFF5E
105
+ if (code >= 0x0021 && code <= 0x007E) {
106
+ return String.fromCharCode(code + 0xFEE0);
107
+ }
108
+ return char;
109
+ }).join('');
110
+ return withHaifun ? haifun(str, withHaifun) : str;
111
+ };
112
+ /**
113
+ * Converts to half-width and optionally normalizes hyphens.
114
+ * @param value - Value to convert
115
+ * @param withHaifun - Hyphen replacement character
116
+ * @returns Half-width string or null
117
+ * @example _.toHalfWidth('ABCー123','-') // 'ABC-123'
118
+ * @example _.toHalfWidth(' アイウ 123 ') // ' アイウ 123 '
119
+ * @category Japanese Utilities
120
+ */
121
+ const toHalfWidth = (value, withHaifun) => {
122
+ if (_.isNil(value)) {
123
+ return null;
124
+ }
125
+ const str = String(value).split('').map(char => {
126
+ const code = char.charCodeAt(0);
127
+ // スペース
128
+ if (code === 0x3000) {
129
+ return '\u0020'; // 半角スペース
130
+ }
131
+ // 全角は0xFF01~0xFF5E、半角は0x0021~0x007E
132
+ if (code >= 0xFF01 && code <= 0xFF5E) {
133
+ return String.fromCharCode(code - 0xFEE0);
134
+ }
135
+ return char;
136
+ }).join('');
137
+ return withHaifun ? haifun(str, withHaifun) : str;
138
+ };
139
+ const a = ansuko;
140
+ a.kanaToFull = kanaToFull;
141
+ a.kanaToHalf = kanaToHalf;
142
+ a.kanaToHira = kanaToHira;
143
+ a.hiraToKana = hiraToKana;
144
+ a.toHalfWidth = toHalfWidth;
145
+ a.toFullWidth = toFullWidth;
146
+ a.haifun = haifun;
147
+ return ansuko;
148
+ };
149
+ export default ansukoJaPlugin;
@@ -0,0 +1,22 @@
1
+ declare global {
2
+ interface Array<T> {
3
+ /**
4
+ * Maps with negated predicate result (boolean array).
5
+ * @param predicate - Predicate
6
+ * @returns Boolean array
7
+ * @example [1,2,3].notMap(n => n > 1) // [true,false,false]
8
+ * @category Array Utilities
9
+ */
10
+ notMap(predicate: (item: T) => boolean): boolean[];
11
+ /**
12
+ * Filters by negated predicate (items that do NOT match).
13
+ * @param predicate - Predicate
14
+ * @returns Filtered items
15
+ * @example [1,2,3].notFilter(n => n % 2 === 0) // [1,3]
16
+ * @category Array Utilities
17
+ */
18
+ notFilter(predicate: (item: T) => boolean): T[];
19
+ }
20
+ }
21
+ declare const ansukoPrototypePlugin: (ansuko: any) => void;
22
+ export default ansukoPrototypePlugin;
@@ -0,0 +1,9 @@
1
+ const ansukoPrototypePlugin = (ansuko) => {
2
+ Array.prototype.notMap = function (predicate) {
3
+ return this.map(ansuko.negate(predicate));
4
+ };
5
+ Array.prototype.notFilter = function (predicate) {
6
+ return this.filter(ansuko.negate(predicate));
7
+ };
8
+ };
9
+ export default ansukoPrototypePlugin;
package/dist/util.d.ts ADDED
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Normalizes many hyphen/dash/horizontal-line code points into a single character.
3
+ * @param text - Text to normalize
4
+ * @param replacement - Replacement character (default "‐")
5
+ * @param expandInterpretation - Also normalize tildes/underscores and related marks
6
+ * @returns Normalized text or null
7
+ * @example haifun('TokyoーOsaka—Nagoya') // 'Tokyo‐Osaka‐Nagoya'
8
+ * @example haifun('file_name〜test','‐',true) // 'file‐name‐test'
9
+ * @example haifun('ABC—123−XYZ','-') // 'ABC-123-XYZ'
10
+ * @category String Utilities
11
+ */
12
+ export declare const haifun: (text?: string, replacement?: string, expandInterpretation?: boolean) => string | null;
13
+ /**
14
+ * Converts full-width characters to half-width; optionally normalizes hyphens.
15
+ * @param value - Value to convert
16
+ * @param withHaifun - Hyphen replacement character
17
+ * @returns Half-width string or null
18
+ * @example toHalfWidth('ABC123') // 'ABC123'
19
+ * @example toHalfWidth('東京都千代田区1ー2ー3','-') // '東京都千代田区1-2-3'
20
+ * @example toHalfWidth('ABC 123') // 'ABC 123'
21
+ * @category String Utilities
22
+ */
23
+ export declare const toHalfWidth: (value: unknown, withHaifun?: string) => string | null;
package/dist/util.js ADDED
@@ -0,0 +1,104 @@
1
+ import _ from "lodash";
2
+ // Escape special characters inside character classes: ] - \ ^
3
+ const escapeForCharClass = (s) => s.replace(/[\]\-\\\^]/g, '\\$&');
4
+ /**
5
+ * Normalizes many hyphen/dash/horizontal-line code points into a single character.
6
+ * @param text - Text to normalize
7
+ * @param replacement - Replacement character (default "‐")
8
+ * @param expandInterpretation - Also normalize tildes/underscores and related marks
9
+ * @returns Normalized text or null
10
+ * @example haifun('TokyoーOsaka—Nagoya') // 'Tokyo‐Osaka‐Nagoya'
11
+ * @example haifun('file_name〜test','‐',true) // 'file‐name‐test'
12
+ * @example haifun('ABC—123−XYZ','-') // 'ABC-123-XYZ'
13
+ * @category String Utilities
14
+ */
15
+ export const haifun = (text, replacement = "‐", expandInterpretation = false) => {
16
+ const base = [
17
+ "\u002D", // - (HYPHEN-MINUS: ASCII hyphen/minus)
18
+ "\u02D7", // ˗ (MODIFIER LETTER MINUS SIGN)
19
+ "\u1173", // ᅳ (HANGUL JUNGSEONG EU)
20
+ "\u1B78", // ᭸ (BALINESE LETTER U)
21
+ "\u2010", // ‐ (HYPHEN)
22
+ "\u2011", // ‑ (NON-BREAKING HYPHEN)
23
+ "\u2012", // ‒ (FIGURE DASH)
24
+ "\u2013", // – (EN DASH)
25
+ "\u2014", // — (EM DASH)
26
+ "\u2015", // ― (HORIZONTAL BAR)
27
+ "\u2043", // ⁃ (HYPHEN BULLET)
28
+ "\u207B", // ⁻ (SUPERSCRIPT MINUS)
29
+ "\u2212", // − (MINUS SIGN)
30
+ "\u25AC", // ▬ (BLACK RECTANGLE)
31
+ "\u2500", // ─ (BOX DRAWINGS LIGHT HORIZONTAL)
32
+ "\u2501", // ━ (BOX DRAWINGS HEAVY HORIZONTAL)
33
+ "\u2574", // ╴ (BOX DRAWINGS LIGHT LEFT)
34
+ "\u2576", // ╶ (BOX DRAWINGS LIGHT RIGHT)
35
+ "\u257C", // ╼ (BOX DRAWINGS LIGHT LEFT AND HEAVY RIGHT)
36
+ "\u257A", // ╺ (BOX DRAWINGS HEAVY LEFT AND LIGHT RIGHT)
37
+ "\u257E", // ╾ (BOX DRAWINGS HEAVY LEFT)
38
+ "\u2796", // ➖ (HEAVY MINUS SIGN)
39
+ "\u2F00", // ⼀ (KANGXI RADICAL ONE)
40
+ "\u30FC", // ー (KATAKANA-HIRAGANA PROLONGED SOUND MARK)
41
+ "\u3127", // ㄧ (BOPOMOFO LETTER I)
42
+ "\u3161", // ㅡ (HANGUL LETTER EU)
43
+ "\u3192", // ㆒ (IDEOGRAPHIC ANNOTATION ONE MARK)
44
+ "\u31D0", // ㇐ (CJK STROKE H)
45
+ "\u4E00", // 一 (CJK UNIFIED IDEOGRAPH-4E00)
46
+ "\u4EA0", // 亠 (CJK UNIFIED IDEOGRAPH-4EA0)
47
+ "\uFE58", // ﹘ (SMALL EM DASH)
48
+ "\uFE63", // ﹣ (SMALL HYPHEN-MINUS)
49
+ "\uFF0D", // − (FULL WIDTH HYPHEN-MINUS)
50
+ "\uFF70", // ー (HALF WIDTH PROLONGED SOUND MARK)
51
+ "\uFFDA", // ᅳ (HALFWIDTH HANGUL LETTER EU)
52
+ "\u10110", // 𐄐 (AEGEAN NUMBER TEN)
53
+ "\u10191", // 𐆑 (ROMAN UNCIA SIGN)
54
+ "\u1680", // (OGHAM SPACE MARK)
55
+ ];
56
+ const ex = [
57
+ "\u2192", // → (RIGHTWARDS ARROW)
58
+ "\u2504", // ┄ (BOX DRAWINGS LIGHT TRIPLE DASH HORIZONTAL)
59
+ "\u2505", // ┅ (BOX DRAWINGS HEAVY TRIPLE DASH HORIZONTAL)
60
+ "\u2508", // ┈ (BOX DRAWINGS LIGHT QUADRUPLE DASH HORIZONTAL)
61
+ "\u2509", // ┉ (BOX DRAWINGS HEAVY QUADRUPLE DASH HORIZONTAL)
62
+ "\u254C", // ╌ (BOX DRAWINGS LIGHT DOUBLE DASH HORIZONTAL)
63
+ "\u254D", // ╍ (BOX DRAWINGS HEAVY DOUBLE DASH HORIZONTAL)
64
+ "\u301C", // 〜 (WAVE DASH)
65
+ "\u007E", // ~ (TILDE)
66
+ "\u005F", // _ (LOW LINE)
67
+ "\uFF3F", // _ (FULLWIDTH LOW LINE)
68
+ "\uFE4E", // ﹎ (CENTRELINE LOW LINE)
69
+ "\uFFE3", //  ̄ (FULLWIDTH MACRON)
70
+ "\u02C9", // ˉ (MODIFIER LETTER MACRON)
71
+ ];
72
+ const baseClass = base.map(escapeForCharClass).join("");
73
+ const exClass = ex.map(escapeForCharClass).join("");
74
+ const res = text?.replace(new RegExp(`[${baseClass}]`, "gu"), replacement);
75
+ return (expandInterpretation ? res?.replace(new RegExp(`[${exClass}]`, "gu"), replacement) ?? undefined : res) ?? null;
76
+ };
77
+ /**
78
+ * Converts full-width characters to half-width; optionally normalizes hyphens.
79
+ * @param value - Value to convert
80
+ * @param withHaifun - Hyphen replacement character
81
+ * @returns Half-width string or null
82
+ * @example toHalfWidth('ABC123') // 'ABC123'
83
+ * @example toHalfWidth('東京都千代田区1ー2ー3','-') // '東京都千代田区1-2-3'
84
+ * @example toHalfWidth('ABC 123') // 'ABC 123'
85
+ * @category String Utilities
86
+ */
87
+ export const toHalfWidth = (value, withHaifun) => {
88
+ if (_.isNil(value)) {
89
+ return null;
90
+ }
91
+ const str = String(value).split('').map(char => {
92
+ const code = char.charCodeAt(0);
93
+ // スペース
94
+ if (code === 0x3000) {
95
+ return '\u0020'; // 全角スペース
96
+ }
97
+ // 全角は0xFF01~0xFF5E、半角は0x0021~0x007E
98
+ if (code >= 0xFF01 && code <= 0xFF5E) {
99
+ return String.fromCharCode(code - 0xFEE0);
100
+ }
101
+ return char;
102
+ }).join('');
103
+ return withHaifun ? haifun(str, withHaifun) : str;
104
+ };
@@ -0,0 +1,2 @@
1
+ declare const _default: import("vite").UserConfig;
2
+ export default _default;
@@ -0,0 +1,8 @@
1
+ import { defineConfig } from 'vitest/config';
2
+ export default defineConfig({
3
+ test: {
4
+ include: ['tests/**/*.test.*'],
5
+ exclude: ['dist/**', 'docs/**'],
6
+ environment: 'node',
7
+ },
8
+ });
package/package.json ADDED
@@ -0,0 +1,84 @@
1
+ {
2
+ "name": "ansuko",
3
+ "version": "1.1.1",
4
+ "description": "A modern JavaScript/TypeScript utility library that extends lodash with practical, intuitive behaviors. Fixes lodash quirks, adds Promise support, Japanese text processing, and GeoJSON utilities.",
5
+ "keywords": [
6
+ "lodash",
7
+ "utility",
8
+ "utilities",
9
+ "typescript",
10
+ "promise",
11
+ "async",
12
+ "japanese",
13
+ "katakana",
14
+ "hiragana",
15
+ "geojson",
16
+ "turf",
17
+ "gis",
18
+ "json5",
19
+ "functional"
20
+ ],
21
+ "author": "Naoto Sera <sera@4am.jp>",
22
+ "license": "MIT",
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/sera4am/ansuko.git"
26
+ },
27
+ "bugs": {
28
+ "url": "https://github.com/sera4am/ansuko/issues"
29
+ },
30
+ "homepage": "https://github.com/sera4am/ansuko#readme",
31
+ "main": "./dist/index.js",
32
+ "types": "./dist/index.d.ts",
33
+ "type": "module",
34
+ "files": [
35
+ "dist",
36
+ "README.md",
37
+ "LICENSE"
38
+ ],
39
+ "exports": {
40
+ ".": "./dist/index.js",
41
+ "./plugins/ja": "./dist/plugins/ja.js",
42
+ "./plugins/geo": "./dist/plugins/geo.js",
43
+ "./plugins/prototype": "./dist/plugins/prototype.js"
44
+ },
45
+ "scripts": {
46
+ "build": "tsc",
47
+ "prepublishOnly": "npm run build",
48
+ "test": "npm run build && vitest run",
49
+ "test:watch": "vitest",
50
+ "lint": "eslint src --ext .ts,.tsx"
51
+ },
52
+ "dependencies": {
53
+ "@turf/turf": "^7.3.1",
54
+ "json5": "^2.2.3",
55
+ "lodash": "^4.17.21"
56
+ },
57
+ "devDependencies": {
58
+ "@eslint/eslintrc": "^3.3.3",
59
+ "@eslint/js": "^9.39.2",
60
+ "@types/geojson": "^7946.0.16",
61
+ "@types/lodash": "^4.14.202",
62
+ "@typescript-eslint/eslint-plugin": "^8.52.0",
63
+ "eslint": "^9.39.2",
64
+ "typescript": "^5.3.3",
65
+ "vitest": "^1.6.0"
66
+ },
67
+ "engines": {
68
+ "node": ">=16.0.0"
69
+ },
70
+ "vitest": {
71
+ "test": {
72
+ "include": [
73
+ "tests/**/*.test.*"
74
+ ],
75
+ "exclude": [
76
+ "ansuko.test.js",
77
+ "unionPolygon.test.js",
78
+ "test.geo.js",
79
+ "dist/**",
80
+ "docs/**"
81
+ ]
82
+ }
83
+ }
84
+ }