1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 | (function(){
|
10 | 'use strict';
|
11 |
|
12 | var CHO = [
|
13 | 'ㄱ', 'ㄲ', 'ㄴ', 'ㄷ', 'ㄸ',
|
14 | 'ㄹ', 'ㅁ', 'ㅂ', 'ㅃ', 'ㅅ', 'ㅆ',
|
15 | 'ㅇ', 'ㅈ', 'ㅉ', 'ㅊ', 'ㅋ', 'ㅌ',
|
16 | 'ㅍ', 'ㅎ'
|
17 | ]
|
18 | , JUNG = [
|
19 | 'ㅏ', 'ㅐ', 'ㅑ', 'ㅒ', 'ㅓ',
|
20 | 'ㅔ', 'ㅕ', 'ㅖ', 'ㅗ', ['ㅗ', 'ㅏ'], ['ㅗ', 'ㅐ'],
|
21 | ['ㅗ', 'ㅣ'], 'ㅛ', 'ㅜ', ['ㅜ','ㅓ'], ['ㅜ','ㅔ'], ['ㅜ','ㅣ'],
|
22 | 'ㅠ', 'ㅡ', ['ㅡ', 'ㅣ'], 'ㅣ'
|
23 | ]
|
24 | , JONG = [
|
25 | '', 'ㄱ', 'ㄲ', ['ㄱ','ㅅ'], 'ㄴ', ['ㄴ','ㅈ'], ['ㄴ', 'ㅎ'], 'ㄷ', 'ㄹ',
|
26 | ['ㄹ', 'ㄱ'], ['ㄹ','ㅁ'], ['ㄹ','ㅂ'], ['ㄹ','ㅅ'], ['ㄹ','ㅌ'], ['ㄹ','ㅍ'], ['ㄹ','ㅎ'], 'ㅁ',
|
27 | 'ㅂ', ['ㅂ','ㅅ'], 'ㅅ', 'ㅆ', 'ㅇ', 'ㅈ', 'ㅊ', 'ㅋ', 'ㅌ', 'ㅍ', 'ㅎ'
|
28 | ]
|
29 | , HANGUL_OFFSET = 0xAC00
|
30 | , CONSONANTS = [
|
31 | 'ㄱ', 'ㄲ', 'ㄳ', 'ㄴ', 'ㄵ', 'ㄶ', 'ㄷ', 'ㄸ',
|
32 | 'ㄹ', 'ㄺ', 'ㄻ', 'ㄼ', 'ㄽ', 'ㄾ', 'ㄿ', 'ㅀ',
|
33 | 'ㅁ', 'ㅂ', 'ㅃ', 'ㅄ', 'ㅅ', 'ㅆ', 'ㅇ', 'ㅈ',
|
34 | 'ㅉ', 'ㅊ', 'ㅋ', 'ㅌ', 'ㅍ', 'ㅎ'
|
35 | ]
|
36 | , COMPLETE_CHO = [
|
37 | 'ㄱ', 'ㄲ', 'ㄴ', 'ㄷ', 'ㄸ',
|
38 | 'ㄹ', 'ㅁ', 'ㅂ', 'ㅃ', 'ㅅ', 'ㅆ',
|
39 | 'ㅇ', 'ㅈ', 'ㅉ', 'ㅊ', 'ㅋ', 'ㅌ', 'ㅍ', 'ㅎ'
|
40 | ]
|
41 | , COMPLETE_JUNG = [
|
42 | 'ㅏ', 'ㅐ', 'ㅑ', 'ㅒ', 'ㅓ',
|
43 | 'ㅔ', 'ㅕ', 'ㅖ', 'ㅗ', 'ㅘ', 'ㅙ',
|
44 | 'ㅚ', 'ㅛ', 'ㅜ', 'ㅝ', 'ㅞ', 'ㅟ',
|
45 | 'ㅠ', 'ㅡ', 'ㅢ', 'ㅣ'
|
46 | ]
|
47 | , COMPLETE_JONG = [
|
48 | '', 'ㄱ', 'ㄲ', 'ㄳ', 'ㄴ', 'ㄵ', 'ㄶ', 'ㄷ', 'ㄹ',
|
49 | 'ㄺ', 'ㄻ', 'ㄼ', 'ㄽ', 'ㄾ', 'ㄿ', 'ㅀ', 'ㅁ',
|
50 | 'ㅂ', 'ㅄ', 'ㅅ', 'ㅆ', 'ㅇ', 'ㅈ', 'ㅊ', 'ㅋ', 'ㅌ', 'ㅍ', 'ㅎ'
|
51 | ]
|
52 | , COMPLEX_CONSONANTS = [
|
53 | ['ㄱ','ㅅ','ㄳ'],
|
54 | ['ㄴ','ㅈ','ㄵ'],
|
55 | ['ㄴ','ㅎ','ㄶ'],
|
56 | ['ㄹ','ㄱ','ㄺ'],
|
57 | ['ㄹ','ㅁ','ㄻ'],
|
58 | ['ㄹ','ㅂ','ㄼ'],
|
59 | ['ㄹ','ㅅ','ㄽ'],
|
60 | ['ㄹ','ㅌ','ㄾ'],
|
61 | ['ㄹ','ㅍ','ㄿ'],
|
62 | ['ㄹ','ㅎ','ㅀ'],
|
63 | ['ㅂ','ㅅ','ㅄ']
|
64 | ]
|
65 | , COMPLEX_VOWELS = [
|
66 | ['ㅗ','ㅏ','ㅘ'],
|
67 | ['ㅗ','ㅐ','ㅙ'],
|
68 | ['ㅗ','ㅣ','ㅚ'],
|
69 | ['ㅜ','ㅓ','ㅝ'],
|
70 | ['ㅜ','ㅔ','ㅞ'],
|
71 | ['ㅜ','ㅣ','ㅟ'],
|
72 | ['ㅡ','ㅣ','ㅢ']
|
73 | ]
|
74 | , CONSONANTS_HASH
|
75 | , CHO_HASH
|
76 | , JUNG_HASH
|
77 | , JONG_HASH
|
78 | , COMPLEX_CONSONANTS_HASH
|
79 | , COMPLEX_VOWELS_HASH
|
80 | ;
|
81 |
|
82 |
|
83 | function _makeHash(array){
|
84 | var length = array.length
|
85 | , hash = {0 : 0}
|
86 | ;
|
87 | for (var i = 0 ; i < length ; i++) {
|
88 | if(array[i])
|
89 | hash[array[i].charCodeAt(0)] = i;
|
90 | }
|
91 | return hash;
|
92 | }
|
93 |
|
94 | CONSONANTS_HASH = _makeHash(CONSONANTS);
|
95 | CHO_HASH = _makeHash(COMPLETE_CHO);
|
96 | JUNG_HASH = _makeHash(COMPLETE_JUNG);
|
97 | JONG_HASH = _makeHash(COMPLETE_JONG);
|
98 |
|
99 | function _makeComplexHash(array){
|
100 | var length = array.length
|
101 | , hash = {}
|
102 | , code1
|
103 | , code2
|
104 | ;
|
105 | for (var i = 0 ; i < length ; i++) {
|
106 | code1 = array[i][0].charCodeAt(0);
|
107 | code2 = array[i][1].charCodeAt(0);
|
108 | if (typeof hash[code1] === 'undefined') {
|
109 | hash[code1] = {};
|
110 | }
|
111 | hash[code1][code2] = array[i][2].charCodeAt(0);
|
112 | }
|
113 | return hash;
|
114 | }
|
115 |
|
116 | COMPLEX_CONSONANTS_HASH = _makeComplexHash(COMPLEX_CONSONANTS);
|
117 | COMPLEX_VOWELS_HASH = _makeComplexHash(COMPLEX_VOWELS);
|
118 |
|
119 | function _isConsonant(c){
|
120 | return CONSONANTS_HASH[c];
|
121 | }
|
122 |
|
123 | function _isCho(c){
|
124 | return typeof CHO_HASH[c] !== 'undefined';
|
125 | }
|
126 |
|
127 | function _isJung(c){
|
128 | return typeof JUNG_HASH[c] !== 'undefined';
|
129 | }
|
130 |
|
131 | function _isJong(c){
|
132 | return typeof JONG_HASH[c] !== 'undefined';
|
133 | }
|
134 |
|
135 | function _isHangul(c /* code number */){
|
136 | return 0xAC00 <= c && c <= 0xd7a3;
|
137 | }
|
138 |
|
139 | function _isJungJoinable(a,b){
|
140 | return (COMPLEX_VOWELS_HASH[a] && COMPLEX_VOWELS_HASH[a][b]) ? COMPLEX_VOWELS_HASH[a][b] : false;
|
141 | }
|
142 |
|
143 | function _isJongJoinable(a,b){
|
144 | return COMPLEX_CONSONANTS_HASH[a] && COMPLEX_CONSONANTS_HASH[a][b] ? COMPLEX_CONSONANTS_HASH[a][b] : false;
|
145 | }
|
146 |
|
147 | var disassemble = function(string){
|
148 | if (typeof string === 'object') {
|
149 | string = string.join('');
|
150 | }
|
151 |
|
152 | var result = []
|
153 | , length = string.length
|
154 | , cho
|
155 | , jung
|
156 | , jong
|
157 | , code
|
158 | ;
|
159 |
|
160 | for (var i = 0 ; i < length ; i++) {
|
161 | code = string.charCodeAt(i);
|
162 | if (_isHangul(code)) {
|
163 | code -= HANGUL_OFFSET;
|
164 | jong = code % 28;
|
165 | jung = (code - jong) / 28 % 21;
|
166 | cho = parseInt((code - jong) / 28 / 21);
|
167 | result.push(CHO[cho]);
|
168 | if (typeof JUNG[jung] === 'object') {
|
169 | result = result.concat(JUNG[jung]);
|
170 | } else {
|
171 | result.push(JUNG[jung]);
|
172 | }
|
173 | if (jong > 0) {
|
174 | if(typeof JONG[jong] === 'object') {
|
175 | result = result.concat(JONG[jong]);
|
176 | } else {
|
177 | result.push(JONG[jong]);
|
178 | }
|
179 | }
|
180 | } else if (_isConsonant(code)) {
|
181 | var r;
|
182 | if (_isCho(code)) {
|
183 | r = CHO[CHO_HASH[code]];
|
184 | } else {
|
185 | r = JONG[JONG_HASH[code]];
|
186 | }
|
187 | if (typeof r == 'string') {
|
188 | result.push(r);
|
189 | } else {
|
190 | result = result.concat(r);
|
191 | }
|
192 | } else if (_isJung(code)) {
|
193 | var r = JUNG[JUNG_HASH[code]];
|
194 | if (typeof r == 'string') {
|
195 | result.push(r);
|
196 | } else {
|
197 | result = result.concat(r);
|
198 | }
|
199 | } else {
|
200 | result.push(string.charAt(i));
|
201 | }
|
202 | }
|
203 | return result;
|
204 | };
|
205 |
|
206 | var assemble = function(array){
|
207 | if (typeof array === 'string') {
|
208 | array = disassemble(array);
|
209 | }
|
210 |
|
211 | var result = []
|
212 | , length = array.length
|
213 | , code
|
214 | , stage = 0
|
215 | , complete_index = -1
|
216 | , previous_code
|
217 | ;
|
218 |
|
219 | function _makeHangul(index){
|
220 | var code
|
221 | , cho
|
222 | , jung1
|
223 | , jung2
|
224 | , jong1 = 0
|
225 | , jong2
|
226 | , hangul = ''
|
227 | ;
|
228 | if (complete_index + 1 > index) {
|
229 | return;
|
230 | }
|
231 | for (var step = 1 ; ; step++) {
|
232 | if (step === 1) {
|
233 | cho = array[complete_index + step].charCodeAt(0);
|
234 | if (_isJung(cho)) {
|
235 | if (complete_index + step + 1 <= index && _isJung(jung1 = array[complete_index + step + 1].charCodeAt(0))) {
|
236 | result.push(String.fromCharCode(_isJungJoinable(cho, jung1)));
|
237 | complete_index = index;
|
238 | return;
|
239 | } else {
|
240 | result.push(array[complete_index + step])
|
241 | complete_index = index;
|
242 | return;
|
243 | }
|
244 | } else if (!_isCho(cho)) {
|
245 | result.push(array[complete_index + step]);
|
246 | complete_index = index;
|
247 | return;
|
248 | }
|
249 | hangul = array[complete_index + step];
|
250 | } else if (step === 2) {
|
251 | jung1 = array[complete_index + step].charCodeAt(0);
|
252 | if (_isCho(jung1)) {
|
253 | cho = _isJongJoinable(cho, jung1);
|
254 | hangul = String.fromCharCode(cho);
|
255 | result.push(hangul);
|
256 | complete_index = index;
|
257 | return;
|
258 | } else {
|
259 | hangul = String.fromCharCode((CHO_HASH[cho] * 21 + JUNG_HASH[jung1]) * 28 + HANGUL_OFFSET);
|
260 | }
|
261 | } else if (step === 3) {
|
262 | jung2 = array[complete_index + step].charCodeAt(0);
|
263 | if (_isJungJoinable(jung1, jung2)) {
|
264 | jung1 = _isJungJoinable(jung1, jung2);
|
265 | } else {
|
266 | jong1 = jung2;
|
267 | }
|
268 | hangul = String.fromCharCode((CHO_HASH[cho] * 21 + JUNG_HASH[jung1]) * 28 + JONG_HASH[jong1] + HANGUL_OFFSET);
|
269 | } else if (step === 4) {
|
270 | jong2 = array[complete_index + step].charCodeAt(0);
|
271 | if (_isJongJoinable(jong1, jong2)) {
|
272 | jong1 = _isJongJoinable(jong1, jong2);
|
273 | } else {
|
274 | jong1 = jong2;
|
275 | }
|
276 | hangul = String.fromCharCode((CHO_HASH[cho] * 21 + JUNG_HASH[jung1]) * 28 + JONG_HASH[jong1] + HANGUL_OFFSET);
|
277 | } else if (step === 5) {
|
278 | jong2 = array[complete_index + step].charCodeAt(0);
|
279 | jong1 = _isJongJoinable(jong1, jong2);
|
280 | hangul = String.fromCharCode((CHO_HASH[cho] * 21 + JUNG_HASH[jung1]) * 28 + JONG_HASH[jong1] + HANGUL_OFFSET);
|
281 | }
|
282 |
|
283 | if (complete_index + step >= index) {
|
284 | result.push(hangul);
|
285 | complete_index = index;
|
286 | return;
|
287 | }
|
288 | }
|
289 | }
|
290 |
|
291 | for (var i = 0 ; i < length ; i++) {
|
292 | code = array[i].charCodeAt(0);
|
293 | if (!_isCho(code) && !_isJung(code) && !_isJong(code)){
|
294 | _makeHangul(i-1);
|
295 | _makeHangul(i);
|
296 | stage = 0;
|
297 | continue;
|
298 | }
|
299 |
|
300 | if (stage == 0) {
|
301 | if (_isCho(code)) {
|
302 | stage = 1;
|
303 | } else if (_isJung(code)) {
|
304 |
|
305 | stage = 4;
|
306 | }
|
307 | } else if (stage == 1) {
|
308 | if (_isJung(code)) {
|
309 | stage = 2;
|
310 | } else {
|
311 | if (_isJongJoinable(previous_code, code)) {
|
312 |
|
313 | stage = 5;
|
314 | } else {
|
315 | _makeHangul(i-1);
|
316 | }
|
317 | }
|
318 | } else if (stage == 2) {
|
319 | if (_isJong(code)) {
|
320 | stage = 3;
|
321 | } else if (_isJung(code)) {
|
322 | if (_isJungJoinable(previous_code, code)) {
|
323 | } else {
|
324 | _makeHangul(i-1);
|
325 | stage = 4;
|
326 | }
|
327 | } else {
|
328 | _makeHangul(i-1);
|
329 | stage = 1;
|
330 | }
|
331 | } else if (stage == 3) {
|
332 | if (_isJong(code)) {
|
333 | if (_isJongJoinable(previous_code, code)) {
|
334 | } else {
|
335 | _makeHangul(i-1);
|
336 | stage = 1;
|
337 | }
|
338 | } else if (_isCho(code)) {
|
339 | _makeHangul(i-1);
|
340 | stage = 1;
|
341 | } else if (_isJung(code)) {
|
342 | _makeHangul(i-2);
|
343 | stage = 2;
|
344 | }
|
345 | } else if (stage == 4) {
|
346 | if (_isJung(code)) {
|
347 | if(_isJungJoinable(previous_code, code)) {
|
348 | _makeHangul(i);
|
349 | stage = 0;
|
350 | } else {
|
351 | _makeHangul(i-1);
|
352 | }
|
353 | } else {
|
354 | _makeHangul(i-1);
|
355 | stage = 1;
|
356 | }
|
357 | } else if (stage == 5) {
|
358 | if (_isJung(code)) {
|
359 | _makeHangul(i-2);
|
360 | stage = 2;
|
361 | } else {
|
362 | _makeHangul(i-1);
|
363 | stage = 1;
|
364 | }
|
365 | }
|
366 | previous_code = code;
|
367 | }
|
368 | _makeHangul(i-1);
|
369 | return result.join('');
|
370 | };
|
371 |
|
372 | var search = function(a, b){
|
373 | var ad = disassemble(a).join('')
|
374 | , bd = disassemble(b).join('');
|
375 |
|
376 | return ad.indexOf(bd);
|
377 | };
|
378 |
|
379 | function Searcher(string) {
|
380 | this.string = string;
|
381 | this.disassembled = disassemble(string).join('');
|
382 | }
|
383 |
|
384 | Searcher.prototype.search = function(string) {
|
385 | return disassemble(string).join('').indexOf(this.disassembled);
|
386 | };
|
387 |
|
388 | var hangul = {
|
389 | disassemble: disassemble,
|
390 | assemble: assemble,
|
391 | search: search,
|
392 | Searcher: Searcher,
|
393 | isHangul: function(c){
|
394 | if (typeof c === 'string')
|
395 | c = c.charCodeAt(0);
|
396 | return _isHangul(c);
|
397 | },
|
398 | isConsonant: function(c){
|
399 | if (typeof c === 'string')
|
400 | c = c.charCodeAt(0);
|
401 | return (typeof _isConsonant(c)) !== 'undefined';
|
402 | },
|
403 | isVowel: function(c){
|
404 | if (typeof c === 'string')
|
405 | c = c.charCodeAt(0);
|
406 | return _isJung(c);
|
407 | },
|
408 | isCho: function(c){
|
409 | if (typeof c === 'string')
|
410 | c = c.charCodeAt(0);
|
411 | return _isCho(c);
|
412 |
|
413 | },
|
414 | isJong: function(c){
|
415 | if (typeof c === 'string')
|
416 | c = c.charCodeAt(0);
|
417 | return _isJong(c);
|
418 | }
|
419 | };
|
420 |
|
421 | if (typeof define == 'function' && define.amd) {
|
422 | define(function(){
|
423 | return hangul;
|
424 | });
|
425 | } else if (typeof module !== 'undefined') {
|
426 | module.exports = hangul;
|
427 | } else {
|
428 | window.Hangul = hangul;
|
429 | };
|
430 | })();
|
431 |
|