Files
AR-Menu/AR Menu/Needle/MenuScene/node_modules/arabic-persian-reshaper/PersianShaper.js
2025-11-30 08:35:03 +02:00

239 lines
8.4 KiB
JavaScript

/**
* Node Arabic & Persian String Reshaper by Shen Yiming (https://github.com/soimy/arabic-persian-reshaper)
* Forked from (https://github.com/font-store/persian-reshaper)
* Based on (https://raw.github.com/Accorpa/Arabic-Converter-From-and-To-Arabic-Presentation-Forms-B/)
*/
var charsMap = [
/* code,isolated,initial, medial, final */
[ 0x0621, 0xFE80, null , null , null ], /* HAMZA */
[ 0x0622, 0xFE81, null , null , 0xFE82 ], /* ALEF_MADDA */
[ 0x0623, 0xFE83, null , null , 0xFE84 ], /* ALEF_HAMZA_ABOVE */
[ 0x0624, 0xFE85, null , null , 0xFE86 ], /* WAW_HAMZA */
[ 0x0625, 0xFE87, null , null , 0xFE88 ], /* ALEF_HAMZA_BELOW */
[ 0x0626, 0xFE89, 0xFE8B, 0xFE8C, 0xFE8A ], /* YEH_HAMZA */
[ 0x0627, 0xFE8D, null , null , 0xFE8E ], /* ALEF */
[ 0x0628, 0xFE8F, 0xFE91, 0xFE92, 0xFE90 ], /* BEH */
[ 0x0629, 0xFE93, null , null , 0xFE94 ], /* TEH_MARBUTA */
[ 0x062A, 0xFE95, 0xFE97, 0xFE98, 0xFE96 ], /* TEH */
[ 0x062B, 0xFE99, 0xFE9B, 0xFE9C, 0xFE9A ], /* THEH */
[ 0x062C, 0xFE9D, 0xFE9F, 0xFEA0, 0xFE9E ], /* JEEM */
[ 0x062D, 0xFEA1, 0xFEA3, 0xFEA4, 0xFEA2 ], /* HAH */
[ 0x062E, 0xFEA5, 0xFEA7, 0xFEA8, 0xFEA6 ], /* KHAH */
[ 0x062F, 0xFEA9, null , null , 0xFEAA ], /* DAL */
[ 0x0630, 0xFEAB, null , null , 0xFEAC ], /* THAL */
[ 0x0631, 0xFEAD, null , null , 0xFEAE ], /* REH */
[ 0x0632, 0xFEAF, null , null , 0xFEB0 ], /* ZAIN */
[ 0x0698, 0xFB8A, null , null , 0xFB8B ], /* ZHEH */
[ 0x0633, 0xFEB1, 0xFEB3, 0xFEB4, 0xFEB2 ], /* SEEN */
[ 0x0634, 0xFEB5, 0xFEB7, 0xFEB8, 0xFEB6 ], /* SHEEN */
[ 0x0635, 0xFEB9, 0xFEBB, 0xFEBC, 0xFEBA ], /* SAD */
[ 0x0636, 0xFEBD, 0xFEBF, 0xFEC0, 0xFEBE ], /* DAD */
[ 0x0637, 0xFEC1, 0xFEC3, 0xFEC4, 0xFEC2 ], /* TAH */
[ 0x0638, 0xFEC5, 0xFEC7, 0xFEC8, 0xFEC6 ], /* ZAH */
[ 0x0639, 0xFEC9, 0xFECB, 0xFECC, 0xFECA ], /* AIN */
[ 0x063A, 0xFECD, 0xFECF, 0xFED0, 0xFECE ], /* GHAIN */
[ 0x0640, 0x0640, 0x0640, 0x0640, 0x0640 ], /* TATWEEL */
[ 0x0641, 0xFED1, 0xFED3, 0xFED4, 0xFED2 ], /* FEH */
[ 0x0642, 0xFED5, 0xFED7, 0xFED8, 0xFED6 ], /* QAF */
[ 0x0643, 0xFED9, 0xFEDB, 0xFEDC, 0xFEDA ], /* KAF */
[ 0x0644, 0xFEDD, 0xFEDF, 0xFEE0, 0xFEDE ], /* LAM */
[ 0x0645, 0xFEE1, 0xFEE3, 0xFEE4, 0xFEE2 ], /* MEEM */
[ 0x0646, 0xFEE5, 0xFEE7, 0xFEE8, 0xFEE6 ], /* NOON */
[ 0x0647, 0xFEE9, 0xFEEB, 0xFEEC, 0xFEEA ], /* HEH */
[ 0x0648, 0xFEED, null , null , 0xFEEE ], /* WAW */
[ 0x0649, 0xFEEF, null , null , 0xFEF0 ], /* ALEF_MAKSURA */
[ 0x064A, 0xFEF1, 0xFEF3, 0xFEF4, 0xFEF2 ], /* YEH Arabic */
[ 0x06CC, 0xFBFC, 0xFBFE, 0xFBFF, 0xFBFD ], /* YEH Farsi */
[ 0x0686, 0xFB7A, 0xFB7C, 0xFB7D, 0xFB7B ], /* CHEH */
[ 0x067E, 0xFB56, 0xFB58, 0xFB59, 0xFB57 ],
[ 0x06AF, 0xFB92, 0xFB94, 0xFB95, 0xFB93 ],
[ 0x06A9, 0xFB8E, 0xFB90, 0xFB91, 0xFB8F ],
],
combCharsMap = [
//[ [ 0x0644, 0x0622 ], 0xFEF5, null, null, 0xFEF6 ], /* LAM_ALEF_MADDA */
//[ [ 0x0644, 0x0623 ], 0xFEF7, null, null, 0xFEF8 ], /* LAM_ALEF_HAMZA_ABOVE */
//[ [ 0x0644, 0x0625 ], 0xFEF9, null, null, 0xFEFA ], /* LAM_ALEF_HAMZA_BELOW */
[ [ 0x0644, 0x0627 ], 0xFEFB, null, null, 0xFEFC ], /* LAM_ALEF */
],
transChars = [
0x0610, /* ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM */
0x0612, /* ARABIC SIGN ALAYHE ASSALLAM */
0x0613, /* ARABIC SIGN RADI ALLAHOU ANHU */
0x0614, /* ARABIC SIGN TAKHALLUS */
0x0615, /* ARABIC SMALL HIGH TAH */
0x064B, /* ARABIC FATHATAN */
0x064C, /* ARABIC DAMMATAN */
0x064D, /* ARABIC KASRATAN */
0x064E, /* ARABIC FATHA */
0x064F, /* ARABIC DAMMA */
0x0650, /* ARABIC KASRA */
0x0651, /* ARABIC SHADDA */
0x0652, /* ARABIC SUKUN */
0x0653, /* ARABIC MADDAH ABOVE */
0x0654, /* ARABIC HAMZA ABOVE */
0x0655, /* ARABIC HAMZA BELOW */
0x0656, /* ARABIC SUBSCRIPT ALEF */
0x0657, /* ARABIC INVERTED DAMMA */
0x0658, /* ARABIC MARK NOON GHUNNA */
0x0670, /* ARABIC LETTER SUPERSCRIPT ALEF */
0x06D6, /* ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA */
0x06D7, /* ARABIC SMALL HIGH LIGATURE QAF WITH LAM WITH ALEF MAKSURA */
0x06D8, /* ARABIC SMALL HIGH MEEM INITIAL FORM */
0x06D9, /* ARABIC SMALL HIGH LAM ALEF */
0x06DA, /* ARABIC SMALL HIGH JEEM */
0x06DB, /* ARABIC SMALL HIGH THREE DOTS */
0x06DC, /* ARABIC SMALL HIGH SEEN */
0x06DF, /* ARABIC SMALL HIGH ROUNDED ZERO */
0x06E0, /* ARABIC SMALL HIGH UPRIGHT RECTANGULAR ZERO */
0x06E1, /* ARABIC SMALL HIGH DOTLESS HEAD OF KHAH */
0x06E2, /* ARABIC SMALL HIGH MEEM ISOLATED FORM */
0x06E3, /* ARABIC SMALL LOW SEEN */
0x06E4, /* ARABIC SMALL HIGH MADDA */
0x06E7, /* ARABIC SMALL HIGH YEH */
0x06E8, /* ARABIC SMALL HIGH NOON */
0x06EA, /* ARABIC EMPTY CENTRE LOW STOP */
0x06EB, /* ARABIC EMPTY CENTRE HIGH STOP */
0x06EC, /* ARABIC ROUNDED HIGH STOP WITH FILLED CENTRE */
0x06ED, /* ARABIC SMALL LOW MEEM */
];
function CharacterMapContains(c) {
for (var i = 0 ; i < charsMap.length ; ++i)
if (charsMap[ i ][0] == c) return true;
return false;
}
function GetCharRep(c) {
for (var i = 0 ; i < charsMap.length ; ++i)
if (charsMap[ i ][0] == c) return charsMap[i];
return false;
}
function GetCombCharRep(c1, c2) {
for (var i = 0 ; i < combCharsMap.length ; ++i)
if (combCharsMap[i][0][0] == c1 && combCharsMap[i][0][1] == c2) return combCharsMap[i];
return false;
}
function IsTransparent(c) {
for (var i = 0 ; i < transChars.length ; ++i)
if ( transChars[i] == c ) return true;
return false;
}
function convertArabic(normal) {
var crep,
combcrep,
shaped = "";
for ( var i = 0 ; i < normal.length ; ++i ) {
var current = normal.charCodeAt(i);
if ( CharacterMapContains( current ) ) {
var prev = null,
next = null,
prevID = i - 1,
nextID = i + 1;
/*
Transparent characters have no effect in the shaping process.
So, ignore all the transparent characters that are BEFORE the
current character.
*/
for ( ; prevID >= 0 ; --prevID ) {
if ( !IsTransparent( normal.charCodeAt(prevID) ) ) {
break;
}
}
prev = ( prevID >= 0 ) ? normal.charCodeAt(prevID) : null;
crep = prev ? GetCharRep( prev ) : false;
if( crep[2] == null && crep[3] == null ) {
prev = null;
}
/*
Transparent characters have no effect in the shaping process.
So, ignore all the transparent characters that are AFTER the
current character.
*/
for ( ; nextID < normal.length ; ++nextID ) {
if ( !IsTransparent( normal.charCodeAt(nextID) ) ) {
break;
}
}
next = ( nextID <= normal.length ) ? normal.charCodeAt(nextID) : null;
crep = next ? GetCharRep( next ) : false;
if( crep[3] == null && crep[4] == null ) {
next = null;
}
// /* Combinations */
if ( current == 0x0644 && next != null &&
( next == 0x0622 || next == 0x0623 || next == 0x0625 || next == 0x0627) ) {
combcrep = GetCombCharRep(current, next);
if ( prev != null ) {
shaped += String.fromCharCode(combcrep[4]);
} else {
shaped += String.fromCharCode(combcrep[1]);
}
i = i+1;
continue;
}
crep = GetCharRep( current );
/* Medial */
if ( prev != null && next != null && crep[3] != null ) {
shaped += String.fromCharCode(crep[3]);
continue;
} else /* Final */
if ( prev != null && crep[4] != null ) {
shaped += String.fromCharCode(crep[4]);
continue;
} else /* Initial */
if ( next != null && crep[2] != null ) {
shaped += String.fromCharCode(crep[2]);
continue;
} else /* Isolated */ {
shaped += String.fromCharCode(crep[1]);
}
} else {
shaped += String.fromCharCode(current);
}
}
return shaped;
}
exports.convertArabic = convertArabic;
// convert from Arabic Presentation Forms B
function convertArabicBack(apfb) {
var toReturn = "",
selectedChar;
theLoop:
for( var i = 0 ; i < apfb.length ; ++i ) {
selectedChar = apfb.charCodeAt(i);
for( var j = 0 ; j < charsMap.length ; ++j ) {
if( charsMap[j][4] == selectedChar || charsMap[j][2] == selectedChar ||
charsMap[j][1] == selectedChar || charsMap[j][3] == selectedChar ) {
toReturn += String.fromCharCode(charsMap[j][0]);
continue theLoop;
}
}
for( var j = 0 ; j < combCharsMap.length ; ++j ) {
if( combCharsMap[j][4] == selectedChar || combCharsMap[j][2] == selectedChar ||
combCharsMap[j][1] == selectedChar || combCharsMap[j][3] == selectedChar ) {
toReturn += String.fromCharCode(combCharsMap[j][0][0]) + String.fromCharCode(combCharsMap[j][0][1]);
continue theLoop;
}
}
toReturn += String.fromCharCode( selectedChar );
}
return toReturn;
}
exports.convertArabicBack = convertArabicBack;