Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jobs:
- run: deno fmt --check
- run: deno lint
- run: deno test --coverage=cov/
- run: deno doc --lint src/index.ts
- run: deno coverage --lcov cov/ > cov.lcov

- uses: coverallsapp/github-action@v2.3.6
Expand Down
2 changes: 1 addition & 1 deletion deno.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@voldemortas/flection",
"version": "0.0.5",
"version": "0.0.6",
"exports": "./src/index.ts",
"tasks": {
"dev": "deno test --watch"
Expand Down
26 changes: 24 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ endpoint shall be made public in the near future as well.

## Release notes

There is version 0.0.5 release which features Verb conjugation that includes
There is version 0.0.6 release which features Verb conjugation that includes
inflection of the following:

- infinitive
Expand All @@ -36,7 +36,7 @@ all of them can be inflected for reflexivness, carry prefixes; the adjectival
participles can also be pronominal.

> [!NOTE]\
> As this is version 0.0.5 nothing is yet set in stone and things may change!
> As this is version 0.0.6 nothing is yet set in stone and things may change!

---

Expand Down Expand Up @@ -115,3 +115,25 @@ const soktiConjugated2 = Verb.pastFrequentativeIndicative
.conjugateBasicPrefixed(['sokti', 'soka', 'soko'], 'ne')
//both results are the same :)
```

### Helpers

The library exposes some helpers that are useful when using the library.

#### normaliseAccents()`

The library operates using the
[combining unicode characters](https://en.wikipedia.org/wiki/Combining_character)
for stress marks, however, one may be tempted to use letters with diacritics
from different languages, such as a singel character `ñ` found in Spanish
instead of 2 characters: `n`+`u+0303` (`ñ`). Thus, if you aren't controlling the
user input, make sure to `normaliseAccents`

```ts
import { normaliseAccents } from '@voldemortas/flection'

const principalParts = `gésti-geñda-gẽdo`

// single letters becomes simple letter + combining character
const normalisedPrincipalParts = normaliseAccents(principalParts)
```
174 changes: 160 additions & 14 deletions src/Verb.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import Verbal from './Verbal.ts'
import type {
ConjugationType,
DeclinedType,
Expand Down Expand Up @@ -33,71 +32,149 @@ import type { PadalyvisType } from '~conjugators/PadalyvisInflector.ts'
import BudinysInflector from '~conjugators/BudinysInflector.ts'
import type { BudinysType } from '~conjugators/BudinysInflector.ts'
import NecessityParticipleDecliner from './flectors/conjugators/NecessityParticipleDecliner.ts'
import {
badFormatError,
parsingInputError,
threeRootsError,
unmatchingPrefixesError,
unmatchingReflexivesError,
} from './errors.ts'
import { isEverythingEqual } from './utils.ts'

/**
* Class which lets you derive various forms such as various moods, -imas action deverbal and various
* participle forms, presents *constructor* where you can pass certain options such as prefix or reflexivity if you want
* all the inflected forms to contain them. The derivation methods are also exposed *statically*.
* **Respects accentuation and metatony.**
*/
export default class Verb extends Verbal {
export default class Verb {
static readonly #PRINCIPAL_PARTS_COUNT = 3
static readonly #WORD_DiLIMIER = '-'

/**
* the 3 principal parts consisting of infinitive, 3rd person present indicative and 3rd person past simple indicative
*/
public readonly principalParts: PrincipalPartsType
/**
* the provided prefix(es) - optional
*/
public readonly prefix: string | undefined
/**
* whether the verb should be reflexive
*/
public readonly isReflexive: boolean

/**
* static member for the past frequentative indicative
*/
public static readonly pastFrequentativeIndicative: Inflector<
ConjugationType
> = new PastFrequentativeIndicativeConjugator()
/**
* static member for the future indicative
*/
public static readonly futureIndicative: Inflector<ConjugationType> =
new FutureIndicativeConjugator()
/**
* static member for the past simple indicative
*/
public static readonly pastSimpleIndicative: Inflector<ConjugationType> =
new PastSimpleIndicativeConjugator()
/**
* static member for the present indicative
*/
public static readonly presentIndicative: Inflector<ConjugationType> =
new PresentIndicativeConjugator()
/**
* static member for the conditional
*/
public static readonly conditional: Inflector<ConjugationType> =
new ConditionalConjugator()
/**
* static member for the imperative
*/
public static readonly imperative: Inflector<ConjugationType> =
new ImperativeConjugator()
/**
* static member for the infinitive
*/
public static readonly infinitive: Inflector<InfinitiveType> =
new InfinitiveConjugator()
/**
* static member for the -imas noun
*/
public static readonly imasNoun: Inflector<DeclinedType> = new ImasDecliner()
/**
* static member for the pusdalyvis
*/
public static readonly pusdalyvis: Inflector<PusdalyvisType> =
new PusdalyvisDecliner()
/**
* static member for the passive past participle
*/
public static readonly passivePastParticiple: ParticipleDecliner =
new PassivePastParticipleDecliner()
/**
* static member for the passive future participle
*/
public static readonly passiveFutureParticiple: ParticipleDecliner =
new PassiveFutureParticipleDecliner()
/**
* static member for the passive present participle
*/
public static readonly passivePresentParticiple: ParticipleDecliner =
new PassivePresentParticipleDecliner()
/**
* static member for the active past simple participle
*/
public static readonly activePastSimpleParticiple: ParticipleDecliner =
new ActivePastSimpleParticipleDecliner()
/**
* static member for the active past frequentative participle
*/
public static readonly activePastFrequentativeParticiple: ParticipleDecliner =
new ActivePastFrequentativeParticipleDecliner()
/**
* static member for the active future participle
*/
public static readonly activeFutureParticiple: ParticipleDecliner =
new ActiveFutureParticipleDecliner()
/**
* static member for the active present participle
*/
public static readonly activePresentParticiple: ParticipleDecliner =
new ActivePresentParticipleDecliner()
/**
* static member for the past simple padalyvis
*/
public static readonly pastSimplePadalyvis: InflectorInterface<
PadalyvisType
> = new PadalyvisInflector(Verb.activePastSimpleParticiple)
/**
* static member for the past frequentative padalyvis
*/
public static readonly pastFrequentativePadalyvis: InflectorInterface<
PadalyvisType
> = new PadalyvisInflector(Verb.activePastFrequentativeParticiple)
/**
* static member for the future padalyvis
*/
public static readonly futurePadalyvis: InflectorInterface<PadalyvisType> =
new PadalyvisInflector(Verb.activeFutureParticiple)
/**
* static member for the present padalyvis
*/
public static readonly presentPadalyvis: InflectorInterface<PadalyvisType> =
new PadalyvisInflector(Verb.activePresentParticiple)
/**
* static member for the budinys
*/
public static readonly budinys: BudinysInflector = new BudinysInflector()
public static readonly necessityParticiple: ParticipleDecliner =
new NecessityParticipleDecliner()

/**
* Wrapper to call all the static methods with the same options
* @param {[string, string, string] | string} roots - single string with principal parts separated with a dash or array of 3 principal part strings
* @param {{reflexive?: boolean; prefix?: string}={}} options - options with optional prefix and optional reflexiveness
* static member for the necessity articiple
*/
public constructor(
roots: string | PrincipalPartsType,
options: { reflexive?: boolean; prefix?: string | undefined } = {},
) {
super(roots, options)
}
public static readonly necessityParticiple: ParticipleDecliner =
new NecessityParticipleDecliner()

/**
* conjugates past frequentative tense based on the data passed to the verb's constructor
Expand Down Expand Up @@ -394,6 +471,68 @@ export default class Verb extends Verbal {
)
}

/**
* Wrapper to call all the static methods with the same options
* @param {[string, string, string] | string} roots - single string with principal parts separated with a dash or array of 3 principal part strings
* @param {{reflexive?: boolean; prefix?: string}={}} options - options with optional prefix and optional reflexiveness
* @example
* ```ts
* const firstVerb = new Verb([`dėti`, `deda`, `dėjo`])//same as secondVerb
* const secondVerb = new Verb(`dėti-deda-dėjo`)//same as firstVerb
* const thirdVerb = new Verb([`dėti`, `deda`, `dėjo`], {prefix: `pa`})//same as fourthVerb
* const fourthVerb = new Verb(`pa=dėti-pa=deda-pa=dėjo`)//same as thirdVerb
* const sixthVerb = new Verb([`dėti`, `deda`, `dėjo`], {prefix: `pa`, reflexive: true})//same as seventhVerb
* const seventhVerb = new Verb(`pasi=dėti-pasi=deda-pasi=dėjo`)//same as sixthVerb
* const eightVerb = new Verb([`dėti`, `deda`, `dėjo`], {reflexive: true})//same as ninthVerb
* const ninthVerb = new Verb(`dėtis-dedasi-dėjosi`)//same as eightVerb
* ```
*/
public constructor(
roots: string | PrincipalPartsType,
options: { reflexive?: boolean; prefix?: string | undefined } = {},
) {
const rootArray = Array.isArray(roots)
? roots
: roots.split(Verb.#WORD_DiLIMIER)
if (rootArray.length !== Verb.#PRINCIPAL_PARTS_COUNT) {
throw threeRootsError
}
const regexMagicGroup = rootArray.map((root) => {
const regexMatches =
/(^(?<prefix>[^=]+?)=(?<root>.+?)(?<reflexive>si?)?$|(^(?<root>.+?)(?<reflexive>si?)?$))/
.exec(root)
// deno-coverage-ignore-start
if (!regexMatches) {
throw badFormatError(root)
}
if (!regexMatches.groups) {
throw parsingInputError
}
// deno-coverage-ignore-stop
const groups = regexMatches.groups
return [
trimReflexiveFromPrefix(groups['prefix'] ?? options.prefix),
groups['root']!,
!!options.reflexive || !!groups['reflexive'] ||
/si$/.test(groups['prefix'] ?? options.prefix ?? ''),
] as [string, string, boolean]
})

this.principalParts = regexMagicGroup.map((g) => g[1]) as [
string,
string,
string,
]
if (!isEverythingEqual(regexMagicGroup.map((g) => g[0]))) {
throw unmatchingPrefixesError
}
this.prefix = regexMagicGroup[0][0]
if (!isEverythingEqual(regexMagicGroup.map((g) => g[2]))) {
throw unmatchingReflexivesError
}
this.isReflexive = regexMagicGroup[0][2]
}

#inflectBasedOnOptions<
T extends Record<string, string | Record<string, string>>,
>(
Expand Down Expand Up @@ -445,3 +584,10 @@ export default class Verb extends Verbal {
) as unknown as T
}
}

function trimReflexiveFromPrefix(prefix: string | undefined) {
if (!prefix) {
return prefix
}
return prefix.replace(/si$/, '')
}
71 changes: 0 additions & 71 deletions src/Verbal.ts

This file was deleted.

6 changes: 6 additions & 0 deletions src/flectors/conjugators/BudinysInflector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ import {
} from '~src/utils.ts'
import AccentedInflector from '~decliners/AccentedInflector.ts'

/**
* type for Padalyvis, it only has 1 type named `budinys`
* ```ts
* const eitiBudinys: BudinysType = {budinys: `eite`}
* ```
*/
export type BudinysType = {
budinys: string
}
Expand Down
Loading