Skip to content

Commit

Permalink
240109 add tifinagh (#6)
Browse files Browse the repository at this point in the history
## Add
- support Tifinagh
  • Loading branch information
amerharb authored Jan 10, 2024
1 parent c2f09a4 commit 577e0be
Show file tree
Hide file tree
Showing 14 changed files with 516 additions and 75 deletions.
4 changes: 4 additions & 0 deletions packages/abjad-convert/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Changelog
<!-- https://keepachangelog.com/en/1.0.0/ -->

## [0.2.0] 2024-01-10
### Added
- Support Tifinagh

## [0.1.0] 2024-01-06
### Added
- Support Syriac
Expand Down
121 changes: 114 additions & 7 deletions packages/abjad-convert/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Abjad Convert
[![Version](https://img.shields.io/badge/version-0.1.0-blue.svg)](https://github.com/amerharb/abjad/tree/version/0.1.0)
[![Version](https://img.shields.io/badge/version-0.2.0-blue.svg)](https://github.com/amerharb/abjad/tree/version/0.2.0)
[![License: GPLv3](https://img.shields.io/badge/License-ISC-blue.svg)](https://opensource.org/licenses/ISC)
![Coverage](https://raw.githubusercontent.com/amerharb/abjad/version/0.1.0/packages/abjad-convert/badges/coverage.svg)
![Github workflow](https://github.com/amerharb/abjad/actions/workflows/lint-test.yaml/badge.svg?branch=version/0.1.0)
![Coverage](https://raw.githubusercontent.com/amerharb/abjad/version/0.2.0/packages/abjad-convert/badges/coverage.svg)
![Github workflow](https://github.com/amerharb/abjad/actions/workflows/lint-test.yaml/badge.svg?branch=version/0.2.0)

**abjad-convert** is a package for converting Abjad alphabets phonetically.

Expand All @@ -11,6 +11,7 @@ current supported alphabets:
- Imperial Aramaic
- Phoenician
- Syriac
- Tifinagh
- Uguritic

## How to use
Expand All @@ -29,15 +30,121 @@ import { convert, Abjad } from 'abjad-convert';

const arabicWord = 'مرحبا';

const imperialAramaicWord = convert(arabicWord, Abjad.Arabic, Abjad.ImperialAramaic);
console.log(imperialAramaicWord); // 𐡌𐡓𐡇𐡁𐡀

const phoenicianWord = convert(arabicWord, Abjad.Arabic, Abjad.Phoenician);
console.log(phoenicianWord); // 𐤌𐤓𐤇𐤁𐤀

const syriacWord = convert(arabicWord, Abjad.Arabic, Abjad.Syriac);
console.log(syriacWord); // ܡܪܚܒܐ

const tifinaghWord = convert(arabicWord, Abjad.Arabic, Abjad.Tifinagh);
console.log(tifinaghWord); // ⵎⵔⵃⴱⴰ

const ugariticWord = convert(arabicWord, Abjad.Arabic, Abjad.Ugaritic);
console.log(ugariticWord); // 𐎎𐎗𐎈𐎁𐎀
```
## Contributing
### Adding new script
Pull requests are welcome. For adding new script. let's say that we want to add a new script "Foo"
- Step #1: create a feature branch from `main` named `abjad-convert/version/0.[x].0` where `x` is the next minor of current version number.
- Step #2: create a new branch that will the previous feature branch when creating the PR.
- Step #3: create a new folder named `foo` in `src`.
- Step #4: add pdf documentation for the script we want to add from www.unicode.org. for example for Ugaritic the file is `U10380.pdf`. this file will be used as a reference
- Step #5: add a new file named `letters.ts` in `foo` folder this file will export
- - `letters` an array of letters written using unicode values with jsdoc each line will contain
the value of the letter using UTF-16 BE using escape \u followed by 4 hex digits.
notice that UTF16BE value is not always the same as the unicode value.
for example for letter Alpa in Ugaritic the unicode value is `0x10380` but the UTF16BE encode value is `0xD800DF80`
follow the value with jsdoc that contain array index, letter itself, unicode value, and the name of the letter.
for example for ugaritic looks like this:

const imperialAramaicWord = convert(arabicWord, Abjad.Arabic, Abjad.ImperialAramaic);
console.log(imperialAramaicWord); // 𐡌𐡓𐡇𐡁𐡀
```ts
export const letters = [
'\uD800\uDF80', /** #0 𐎀 U+10380 UGARITIC LETTER ALPA */
'\uD800\uDF81', /** #1 𐎁 U+10381 UGARITIC LETTER BETA */
//...
];
```
- - 'Fo' an alias object called `Fo` short of Foo. this will give an alias for all letters mentioned in the letters array.

const syriacWord = convert(arabicWord, Abjad.Arabic, Abjad.Syriac);
console.log(syriacWord); // ܡܪܚܒܐ
for example for ugaritic looks like this:
```ts
export const Ug = {
Alpa: letters[0], // 𐎀
Beta: letters[1], // 𐎁
//...
};
```

- Step #6: Add the script to the enum `Abjad` in `src/types.ts` file.
at this point we have finished adding the script, but it is an island script. Meaning that it can't be converted to or from any other script.

- Step #7: To make it convertable we need at least to have one from and one to converter to another script.
the preferred way is to add a converter to and from Arabic script, as it is currently act as a de facto hub script for all abjad scripts.
The algorithm for converting will look first for 1-step converter (direct converter) the one that convert from the source to the target, in case there isn't any it will look for 2-steps approach where it can find a middle script,
after that it won't look for 3 or more steps, it will basically throw an error.
That is why Arabic is used as preferred hub, so if all script add converter to Arabic and Arabic add converter to all other scripts then all conversion is possible.
However, there is a plan in the future to add IPA to be a canonical hub script.

- - Adding to Arabic: Add file to `foo` folder with name `toArabic.ts` that include a class called FooToArabicConverter that implements `IConverter` interface.
it should look like this:
```ts
import { IConverter } from '../types';
import { Fo } from './letters'
import { Ar } from '../arabic/letters'
import { IConverter } from '../IConverter'
import { Abjad } from '../types'

export class FooToArabicConverter implements IConverter {
public readonly from = Abjad.Foo
public readonly to = Abjad.Arabic
public convert(fooText: string): string {
// convert logic here
// return (araic text)
}
}
```
- - Add toArabic converter to `converterFactory.ts`
- - - import the new converter in alphabetical order
```ts
//...
import { FooToArabicConverter } from './foo/toArabic'
//...
```
- - - add the converter to converters array in alphabetical order
```ts
const converters: IConverter[] = [
//...
new TifinaghToArabicConverter(),
//...
];
```
- - Add toFoo converter to `arabic` folder with name `toFoo.ts` that include a class called ArabicToFooConverter that implements `IConverter` interface.
it should look like this:
```ts
import {Ar} from './letters'
import {Fo} from '../foo/letters'
import {IConverter} from '../IConverter'
import {Abjad} from '../types'

export class ArabicToFooConverter implements IConverter {
public readonly from = Abjad.Arabic
public readonly to = Abjad.Foo
public convert(arabicText: string): string {
// convert logic here
// return (foo text)
}
}
```
- - Add toFoo converter to `converterFactory.ts`

- Step #8 add unit test to`test/index.test.ts`.

- Step #9: update for new version
- - update `CHANGELOG.md` with the new version number and the changes.
- - Step #10 update `README.md` links and badges.
- - Update version in `package.json` file.
- - run yarn to update yarn.lock files
- - run test to update coverage badges
2 changes: 1 addition & 1 deletion packages/abjad-convert/badges/coverage.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 7 additions & 2 deletions packages/abjad-convert/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "abjad-convert",
"version": "0.1.0",
"version": "0.2.0-next.0",
"main": "dist/src/index.js",
"types": "dist/src/index.d.ts",
"files": [
Expand All @@ -10,8 +10,13 @@
"CHANGELOG.md",
"README.md"
],
"repository": "git@github.com:amerharb/abjad.git",
"author": "Amer Harb",
"repository": {
"type": "git",
"url": "git+https://github.com/amerharb/abjad.git"
},
"homepage": "https://github.com/amerharb/abjad#readme",
"url": "https://github.com/amerharb/abjad/issues",
"email": "abjad@amerharb.com",
"keywords": [
"abjad",
Expand Down
59 changes: 59 additions & 0 deletions packages/abjad-convert/src/arabic/toTifinagh.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { Ar } from './letters'
import { Ti } from '../tifinagh/letters'
import { IConverter } from '../IConverter'
import { Abjad } from '../types'

export class ArabicToTifinaghConverter implements IConverter {
public readonly from = Abjad.Arabic
public readonly to = Abjad.Tifinagh

private map = new Map<string, string>(
[
[' ', ' '],
[Ar.Hamza, Ti.Ya], /** ء -> ⴰ */
[Ar.AlefMadda, Ti.Ya], /** ا -> ⴰ */
[Ar.AlefHamza, Ti.Ya], /** أ -> ⴰ*/
[Ar.WawHamza, Ti.Yu], /** ؤ -> ⵓ */
[Ar.AlefHamzaMaksura, Ti.Ya], /** ى -> ⴰ */
[Ar.Alef, Ti.Ya], /** ا -> ⴰ */
[Ar.Ba, Ti.Yab], /** ب -> ⴱ */
[Ar.TaMarbuta, Ti.Ya], /** ة -> ⴰ */
[Ar.Ta, Ti.Yat], /** ت -> ⵜ */
[Ar.Tha, Ti.Yath], /** ث -> ⵝ */
[Ar.Jeem, Ti.Yazh], /** ج -> ⵊ */
[Ar.H7aa, Ti.Yahh], /** ح -> ⵃ */
[Ar.Khaa, Ti.Yakh], /** خ -> ⵅ */
[Ar.Dal, Ti.Yad], /** د -> ⴷ */
[Ar.Thal, Ti.Yadh], /** ذ -> ⴸ */
[Ar.Ra, Ti.Yar], /** ر -> ⵔ */
[Ar.Zay, Ti.Ya], /** ز -> ⴰ */
[Ar.Seen, Ti.Yas], /** س -> ⵙ */
[Ar.Sheen, Ti.Yash], /** ش -> ⵛ */
[Ar.Sad, Ti.Yat], /** ص -> ⵜ */
[Ar.Dad, Ti.Yadd], /** ض -> ⴹ */
[Ar.TTa, Ti.Yatt], /** ط -> ⵟ */
[Ar.THa, Ti.Yaddh], /** ظ -> ⴺ */
[Ar.Ayn, Ti.Yaa], /** ع -> ⵄ */
[Ar.Ghayn, Ti.Yagh], /** غ -> ⵖ */
[Ar.Fa, Ti.Yaf], /** ف -> ⴼ */
[Ar.Qaf, Ti.Yaq], /** ق -> ⵇ */
[Ar.Kaf, Ti.Yak], /** ك -> ⴽ */
[Ar.Lam, Ti.Yal], /** ل -> ⵍ */
[Ar.Meem, Ti.Yam], /** م -> ⵎ */
[Ar.Noon, Ti.Yan], /** ن -> ⵏ */
[Ar.Ha, Ti.Yey], /** ه -> ⴻ */
[Ar.Waw, Ti.Yu], /** و -> ⵓ */
[Ar.AlefMaksura, Ti.Ya], /** ى -> ⴰ */
[Ar.Yaa, Ti.Yi], /** ي -> ⵉ */
]
)

public convert(text: string): string {
let result = ''
for (const letter of text) {
const u = this.map.get(letter) ?? ''
result += u
}
return result
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { IConverter } from './IConverter'
import { ArabicToImperialAramaicConverter } from './arabic/toImperialAramaic'
import { ArabicToPhoenicianConverter } from './arabic/toPhoenician'
import { ArabicToSyriacConverter } from './arabic/toSyriac'
import { ArabicToTifinaghConverter } from './arabic/toTifinagh'
import { ArabicToUgariticConverter } from './arabic/toUgaritic'
import { ImperialAramaicToArabicConverter } from './imperialAramaic/toArabic'
import { ImperialAramaicToPhoenicianConverter } from './imperialAramaic/toPhoenician'
Expand All @@ -11,6 +12,7 @@ import { PhoenicianToArabicConverter } from './phoenician/toArabic'
import { PhoenicianToImperialAramaicConverter } from './phoenician/toImperialAramaic'
import { PhoenicianToUgariticConverter } from './phoenician/toUgaritic'
import { SyriacToArabicConverter } from './syriac/toArabic'
import { TifinaghToArabicConverter } from './tifinagh/toArabic'
import { UgariticToArabicConverter } from './ugaritic/toArabic'
import { UgariticToImperialAramaicConverter } from './ugaritic/toImperialAramaic'
import { UgariticToPhoenicianConverter } from './ugaritic/toPhoenician'
Expand All @@ -19,6 +21,7 @@ const converters: IConverter[] = [
new ArabicToImperialAramaicConverter(),
new ArabicToPhoenicianConverter(),
new ArabicToSyriacConverter(),
new ArabicToTifinaghConverter(),
new ArabicToUgariticConverter(),
new ImperialAramaicToArabicConverter(),
new ImperialAramaicToPhoenicianConverter(),
Expand All @@ -27,6 +30,7 @@ const converters: IConverter[] = [
new PhoenicianToImperialAramaicConverter(),
new PhoenicianToUgariticConverter(),
new SyriacToArabicConverter(),
new TifinaghToArabicConverter(),
new UgariticToArabicConverter(),
new UgariticToImperialAramaicConverter(),
new UgariticToPhoenicianConverter(),
Expand Down
2 changes: 1 addition & 1 deletion packages/abjad-convert/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getConverter } from './ConverterFactory'
import { getConverter } from './converterFactory'
import { Abjad } from './types'

export function convert(source: string, from: Abjad, to: Abjad): string {
Expand Down
4 changes: 0 additions & 4 deletions packages/abjad-convert/src/phoenician/letters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ export const Ph = {
Waw: letters[5], // 𐤅
Zayin: letters[6], // 𐤆
Het: letters[7], // 𐤇

Tet: letters[8], // 𐤈
Yod: letters[9], // 𐤉
Kap: letters[10], // 𐤊
Expand All @@ -50,20 +49,17 @@ export const Ph = {
Nun: letters[13], // 𐤍
Semk: letters[14], // 𐤎
Ain: letters[15], // 𐤏

Pe: letters[16], // 𐤐
Sade: letters[17], // 𐤑
Qof: letters[18], // 𐤒
Ros: letters[19], // 𐤓
Shin: letters[20], // 𐤔
Tau: letters[21], // 𐤕

One: letters[22], // 𐤖
Ten: letters[23], // 𐤗
Twenty: letters[24], // 𐤘
OneHundred: letters[25], // 𐤙
Two: letters[26], // 𐤚
Three: letters[27], // 𐤛

WordSeparator: letters[28], // 𐤟
}
Binary file added packages/abjad-convert/src/tifinagh/U2D30.pdf
Binary file not shown.
Loading

0 comments on commit 577e0be

Please sign in to comment.