diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b839e6c..2666ff2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,7 +41,7 @@ * Updated angel_serialize to 4.0.0 (0/0 tests passed) * Updated angel_serialize_generator to 4.0.0 (33/33 tests passed) * Updated angel_orm to 4.0.0 (0/0 tests passed) -* Updated angel_migration to 3.0.0 +* Updated angel_migration to 4.0.0 (0/0 tests passed) * Updated angel_orm_generator to 3.0.0 (use a fork of postgres) # 3.0.0 (Non NNBD) @@ -71,7 +71,7 @@ * Updated angel_serialize to 3.0.0 (0/0 tests passed) * Updated angel_serialize_generator to 3.0.0 (33/33 tests passed) * Updated angel_orm to 3.0.0 (0/0 tests passed) -* Updated angel_migration to 3.0.0 +* Updated angel_migration to 3.0.0 (0/0 tests passed) * Updated angel_orm_generator to 3.0.0 (use a fork of postgres) * Updated angel_migration_runner to 3.0.0 * Updated angel_orm_test to 1.0.0 diff --git a/packages/inflection2/AUTHORS.md b/packages/inflection2/AUTHORS.md new file mode 100644 index 00000000..a839c986 --- /dev/null +++ b/packages/inflection2/AUTHORS.md @@ -0,0 +1,3 @@ +George Moschovitis +Tobe O +Thomas Hii \ No newline at end of file diff --git a/packages/inflection2/CHANGELOG.md b/packages/inflection2/CHANGELOG.md new file mode 100644 index 00000000..9f0157ce --- /dev/null +++ b/packages/inflection2/CHANGELOG.md @@ -0,0 +1,40 @@ +# Changelog + +# 1.0.0 +* Migrated to support Dart SDK 2.12.x NNBD + +## 0.4.3 +- Add past tense support (thanks @phodonou !) + +## 0.4.2 +- Dart 2 compatibility. +- Hard fork. + +## 0.4.1 + +- Cleanup, follow latest conventions and developments in the Dartiverse. +- Added past inflections. + +## 0.3.2 + +- Cleanup. + +## 0.3.1 + +- Case conversion handles sentences delimited with whitespace. + +## 0.3.0 + +- Handle irregular plural nouns. +- Added shortcut functions. + +## 0.2.0 + +- Handle uncountable nouns. +- Added singular inflection. +- Added plural inflection. +- Refactored to use a dart:convert based API. + +## 0.1.0 + +- Initial version, convertToSnakeCase / convertToSpinalCase. diff --git a/packages/inflection2/LICENSE b/packages/inflection2/LICENSE new file mode 100644 index 00000000..235e7a01 --- /dev/null +++ b/packages/inflection2/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2015, George Moschovitis . +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/packages/inflection2/README.md b/packages/inflection2/README.md new file mode 100644 index 00000000..b57ccbeb --- /dev/null +++ b/packages/inflection2/README.md @@ -0,0 +1,49 @@ +# Forked +**IMPORTANT NOTE**: This is a *hard fork* of the original `inflection` package, +as the former is now archived, and abandoned. + +# Inflection + +[![Build Status](https://travis-ci.org/thosakwe/dart-inflection.svg)](https://travis-ci.org/thosakwe/dart-inflection) + +In grammar, inflection or inflexion is the modification of a word to express +different grammatical categories such as tense, mood, voice, aspect, person, +number, gender and case. + +A port of the Rails/ActiveSupport inflector library to Dart. + +## Usage + +A simple usage example: + +```dart +import 'package:inflection2/inflection2.dart'; + +main() { + // Using 'shortcut' functions. + + print(pluralize("house")); // => "houses" + print(convertToPlural("house")); // => "houses", alias for pluralize + print(pluralizeVerb("goes")); // => "go" + print(singularize("axes")); // => "axis" + print(convertToSingular("axes")); // => "axis", alias for pluralize + print(singularizeVerb("write")); // => "writes" + print(convertToSnakeCase("CamelCaseName")); // => "camel_case_name" + print(convertToSpinalCase("CamelCaseName")); // => "camel-case-name" + print(past("forgo")); // => "forwent" + + // Using default encoders. + + print(PLURAL.convert("virus")); // => "viri" + print(SINGULAR.convert("Matrices")); // => "Matrix" + print(SINGULAR.convert("species")); // => "species" + print(SNAKE_CASE.convert("CamelCaseName")); // => "camel_case_name" + print(SPINAL_CASE.convert("CamelCaseName")); // => "camel-case-name" + print(PAST.convert("miss")); // => "missed" +} +``` + +## Features and bugs + +Please file feature requests and bugs at the +[issue tracker](https://github.com/thosakwe/dart-inflection/issues). diff --git a/packages/inflection2/analysis_options.yaml b/packages/inflection2/analysis_options.yaml new file mode 100644 index 00000000..eae1e42a --- /dev/null +++ b/packages/inflection2/analysis_options.yaml @@ -0,0 +1,3 @@ +analyzer: + strong-mode: + implicit-casts: false \ No newline at end of file diff --git a/packages/inflection2/example/main.dart b/packages/inflection2/example/main.dart new file mode 100644 index 00000000..a11cd80e --- /dev/null +++ b/packages/inflection2/example/main.dart @@ -0,0 +1,24 @@ +import '../lib/inflection2.dart'; + +main() { + // Using 'shortcut' functions. + + print(pluralize("house")); // => "houses" + print(convertToPlural("house")); // => "houses", alias for pluralize + print(pluralizeVerb("goes")); // => "go" + print(singularize("axes")); // => "axis" + print(convertToSingular("axes")); // => "axis", alias for pluralize + print(singularizeVerb("write")); // => "writes" + print(convertToSnakeCase("CamelCaseName")); // => "camel_case_name" + print(convertToSpinalCase("CamelCaseName")); // => "camel-case-name" + print(past("forgo")); // => "forwent" + + // Using default encoders. + + print(PLURAL.convert("virus")); // => "viri" + print(SINGULAR.convert("Matrices")); // => "Matrix" + print(SINGULAR.convert("species")); // => "species" + print(SNAKE_CASE.convert("CamelCaseName")); // => "camel_case_name" + print(SPINAL_CASE.convert("CamelCaseName")); // => "camel-case-name" + print(PAST.convert("miss")); // => "missed" +} diff --git a/packages/inflection2/lib/inflection2.dart b/packages/inflection2/lib/inflection2.dart new file mode 100644 index 00000000..3af1618b --- /dev/null +++ b/packages/inflection2/lib/inflection2.dart @@ -0,0 +1,43 @@ +/// In grammar, inflection or inflexion is the modification of a word to express +/// different grammatical categories such as tense, mood, voice, aspect, person, +/// number, gender and case. +/// +/// [ActiveSupport Inflector](https://github.com/rails/rails/tree/master/activesupport/lib/active_support/inflector) +/// [Letter case](http://en.wikipedia.org/wiki/Letter_case#Special_case_styles) +library inflection2; + +import 'src/past.dart'; +import 'src/plural.dart'; +import 'src/plural_verb.dart'; +import 'src/singular.dart'; +import 'src/singular_verb.dart'; +import 'src/snake_case.dart'; +import 'src/spinal_case.dart'; + +export 'src/past.dart'; +export 'src/plural.dart'; +export 'src/plural_verb.dart'; +export 'src/singular.dart'; +export 'src/singular_verb.dart'; +export 'src/snake_case.dart'; +export 'src/spinal_case.dart'; +export 'src/is_tense.dart'; + +String convertToPlural(String word) => PLURAL.convert(word); +String pluralize(String word) => PLURAL.convert(word); + +String convertToPluralVerb(String word) => PLURALVERB.convert(word); +String pluralizeVerb(String word) => PLURALVERB.convert(word); + +String convertToSingular(String word) => SINGULAR.convert(word); +String singularize(String word) => SINGULAR.convert(word); + +String convertToSingularVerb(String word) => SINGULARVERB.convert(word); +String singularizeVerb(String word) => SINGULARVERB.convert(word); + +String convertToSnakeCase(String word) => SNAKE_CASE.convert(word); + +String convertToSpinalCase(String word) => SPINAL_CASE.convert(word); + +String convertToPast(String word) => PAST.convert(word); +String past(String word) => PAST.convert(word); diff --git a/packages/inflection2/lib/src/irregular_past_verbs.dart b/packages/inflection2/lib/src/irregular_past_verbs.dart new file mode 100644 index 00000000..c25c79b3 --- /dev/null +++ b/packages/inflection2/lib/src/irregular_past_verbs.dart @@ -0,0 +1,323 @@ +//library inflection2.irregular_past_verbs; + +/// A collection of verbs with irregular past. +final Map irregularPastVerbs = const { + "backslidden": "backslid", + "forbidden": "forbade", + "stridden": "strode", + "stricken": "struck", + "brought": "brought", + "striven": "strove", + "swollen": "swelled", + "thought": "thought", + "trodden": "trod", + "forbade": "forbade", + "arisen": "arose", + "awoken": "awoke", + "beaten": "beat", + "became": "became", + "become": "became", + "bidden": "bid", + "bitten": "bit", + "broken": "broke", + "bought": "bought", + "caught": "caught", + "choose": "chose", + "chosen": "chose", + "forbid": "forbade", + "dreamt": "dreamt", + "driven": "drove", + "fallen": "fell", + "fought": "fought", + "freeze": "froze", + "frozen": "froze", + "gotten": "got", + "ground": "ground", + "hidden": "hid", + "learnt": "learnt", + "proven": "proved", + "sought": "sought", + "shaken": "shook", + "shaven": "shaved", + "shrank": "shrank", + "shrink": "shrank", + "shrunk": "shrank", + "spoken": "spoke", + "spoilt": "spoilt", + "spread": "spread", + "sprang": "sprang", + "spring": "sprang", + "sprung": "sprang", + "stolen": "stole", + "strewn": "strewed", + "strode": "strode", + "stride": "strode", + "strike": "struck", + "strove": "strove", + "struck": "struck", + "string": "strung", + "strung": "strung", + "taught": "taught", + "thrown": "threw", + "thrust": "thrust", + "arise": "arose", + "arose": "arose", + "awake": "awoke", + "awoke": "awoke", + "borne": "bore", + "began": "began", + "begin": "began", + "begun": "began", + "bound": "bound", + "bleed": "bled", + "blown": "blew", + "break": "broke", + "breed": "bred", + "bring": "brought", + "broke": "broke", + "build": "built", + "built": "built", + "burnt": "burnt", + "catch": "caught", + "chose": "chose", + "cling": "clung", + "clung": "clung", + "creep": "crept", + "crept": "crept", + "dealt": "dealt", + "wound": "wound", + "wring": "wrung", + "wrung": "wrung", + "write": "wrote", + "wrote": "wrote", + "drawn": "drew", + "drank": "drank", + "drink": "drank", + "drunk": "drank", + "drive": "drove", + "drove": "drove", + "dwelt": "dwelt", + "eaten": "ate", + "fight": "fought", + "found": "found", + "fling": "flung", + "flung": "flung", + "flown": "flew", + "froze": "froze", + "given": "gave", + "grind": "ground", + "grown": "grew", + "heard": "heard", + "knelt": "knelt", + "known": "knew", + "leant": "leant", + "leapt": "leapt", + "leave": "left", + "meant": "meant", + "risen": "rose", + "shake": "shook", + "shorn": "sheared", + "shone": "shone", + "shook": "shook", + "shoot": "shot", + "shown": "showed", + "slain": "slew", + "sleep": "slept", + "slept": "slept", + "slide": "slid", + "sling": "slung", + "slung": "slung", + "slunk": "slunk", + "smelt": "smelt", + "snuck": "snuck", + "speak": "spoke", + "spelt": "spelt", + "spend": "spent", + "spent": "spent", + "spilt": "spilt", + "split": "split", + "spoke": "spoke", + "stand": "stood", + "stood": "stood", + "steal": "stole", + "stick": "stuck", + "stole": "stole", + "stuck": "stuck", + "sting": "stung", + "stung": "stung", + "stank": "stank", + "stink": "stank", + "stunk": "stank", + "swear": "swore", + "swore": "swore", + "sworn": "swore", + "sweep": "swept", + "swept": "swept", + "swing": "swung", + "swung": "swung", + "taken": "took", + "teach": "taught", + "think": "thought", + "threw": "threw", + "throw": "threw", + "tread": "trod", + "wake": "woke", + "woken": "woke", + "woven": "wove", + "bear": "bore", + "bore": "bore", + "born": "bore", + "beat": "beat", + "bend": "bent", + "bent": "bent", + "bind": "bound", + "bite": "bit", + "bled": "bled", + "blew": "blew", + "blow": "blew", + "bred": "bred", + "cast": "cast", + "clad": "clad", + "come": "came", + "cost": "cost", + "deal": "dealt", + "does": "did", + "done": "did", + "draw": "drew", + "drew": "drew", + "fall": "fell", + "feed": "fed", + "feel": "felt", + "fell": "fell", + "felt": "felt", + "find": "found", + "flee": "fled", + "fled": "fled", + "flew": "flew", + "gave": "gave", + "give": "gave", + "gone": "went", + "grew": "grew", + "grow": "grew", + "hang": "hung", + "hung": "hung", + "have": "had", + "hear": "heard", + "hewn": "hewed", + "hide": "hid", + "hold": "held", + "held": "held", + "hurt": "hurt", + "keep": "kept", + "kept": "kept", + "knew": "knew", + "know": "knew", + "laid": "laid", + "lead": "led", + "left": "left", + "lend": "lent", + "lent": "lent", + "lain": "lay", + "lose": "lost", + "lost": "lost", + "make": "made", + "made": "made", + "mean": "meant", + "meet": "met", + "mown": "mowed", + "paid": "paid", + "pled": "pled", + "read": "read", + "ride": "rode", + "rode": "rode", + "ring": "rang", + "rung": "rang", + "rise": "rose", + "rose": "rose", + "sang": "sang", + "sawn": "sawed", + "said": "said", + "seen": "saw", + "seek": "sought", + "sell": "sold", + "slew": "slew", + "sold": "sold", + "send": "sent", + "sent": "sent", + "sewn": "sewed", + "shed": "shed", + "shot": "shot", + "shut": "shut", + "sing": "sang", + "sung": "sang", + "slid": "slid", + "slit": "slit", + "sown": "sowed", + "sped": "sped", + "spin": "spun", + "spun": "spun", + "spit": "spit", + "spat": "spat", + "swam": "swam", + "swim": "swam", + "swum": "swam", + "take": "took", + "tear": "tore", + "tore": "tore", + "torn": "tore", + "tell": "told", + "told": "told", + "took": "took", + "trod": "trod", + "wear": "wore", + "wore": "wore", + "worn": "wore", + "weep": "wept", + "went": "went", + "wept": "wept", + "were": "were", + "wind": "wound", + "woke": "woke", + "wove": "wove", + "are": "were", + "ate": "ate", + "bet": "bet", + "bid": "bid", + "bit": "bit", + "buy": "bought", + "cut": "cut", + "did": "did", + "dig": "dug", + "dug": "dug", + "eat": "ate", + "fed": "fed", + "fly": "flew", + "get": "got", + "got": "got", + "had": "had", + "has": "had", + "hid": "hid", + "hit": "hit", + "lay": "laid", + "led": "led", + "let": "let", + "lit": "lit", + "met": "met", + "pay": "paid", + "put": "put", + "ran": "ran", + "rid": "rid", + "run": "ran", + "saw": "saw", + "say": "said", + "see": "saw", + "sit": "sat", + "sat": "sat", + "set": "set", + "was": "was", + "win": "won", + "won": "won", + "do": "did", + "go": "went", + "is": "was", +}; diff --git a/packages/inflection2/lib/src/irregular_plural_nouns.dart b/packages/inflection2/lib/src/irregular_plural_nouns.dart new file mode 100644 index 00000000..c420a714 --- /dev/null +++ b/packages/inflection2/lib/src/irregular_plural_nouns.dart @@ -0,0 +1,11 @@ +//library inflection2.irregular_plural_nouns; + +/// A collection of nouns with irregular plurals. +/// +/// [A List of 100 Irregular Plural Nouns in English](http://grammar.about.com/od/words/a/A-List-Of-Irregular-Plural-Nouns-In-English.htm) +final Map irregularPluralNouns = const { + "person": "people", + "man": "men", + "child": "children", + "sex": "sexes" +}; diff --git a/packages/inflection2/lib/src/irregular_plural_verbs.dart b/packages/inflection2/lib/src/irregular_plural_verbs.dart new file mode 100644 index 00000000..3a5561fd --- /dev/null +++ b/packages/inflection2/lib/src/irregular_plural_verbs.dart @@ -0,0 +1,9 @@ +//library inflection2.irregular_plural_verbs; + +/// A collection of verbs with irregular plurals. +final Map irregularPluralVerbs = const { + "is": "are", + "am": "are", + "was": "were", + "has": "have" +}; diff --git a/packages/inflection2/lib/src/is_tense.dart b/packages/inflection2/lib/src/is_tense.dart new file mode 100644 index 00000000..ec391e75 --- /dev/null +++ b/packages/inflection2/lib/src/is_tense.dart @@ -0,0 +1,6 @@ +import '../inflection2.dart'; + +/// returns true if this word is in the past tense +bool isPastTense(String word) { + return word.toLowerCase().trim() == past(word).toLowerCase().trim(); +} diff --git a/packages/inflection2/lib/src/past.dart b/packages/inflection2/lib/src/past.dart new file mode 100644 index 00000000..2301f1a4 --- /dev/null +++ b/packages/inflection2/lib/src/past.dart @@ -0,0 +1,68 @@ +//library inflection2.past; + +import 'dart:convert'; + +import 'irregular_past_verbs.dart'; +import 'verbs_ending_with_ed.dart'; +import 'util.dart'; + +class PastEncoder extends Converter { + final List _inflectionRules = []; + + PastEncoder() { + irregularPastVerbs.forEach((String presentOrParticiple, String past) { + addIrregularInflectionRule(presentOrParticiple, past); + }); + [ + [r'.+', (Match m) => '${m[0]}ed'], + [r'([^aeiou])y$', (Match m) => '${m[1]}ied'], + [r'([aeiou]e)$', (Match m) => '${m[1]}d'], + [r'[aeiou][^aeiou]e$', (Match m) => '${m[0]}d'] + ] + .reversed + .forEach((rule) => addInflectionRule(rule.first as String, rule.last)); + } + + void addInflectionRule(String presentOrParticiple, dynamic past) { + _inflectionRules + .add([new RegExp(presentOrParticiple, caseSensitive: false), past]); + } + + void addIrregularInflectionRule(String presentOrParticiple, String past) { + _inflectionRules.add([ + new RegExp( + r'^(back|dis|for|fore|in|inter|mis|off|over|out|par|pre|re|type|un|under|up)?' + + presentOrParticiple + + r'$', + caseSensitive: false), + (Match m) => (m[1] == null) ? past : m[1]! + past + ]); + } + + @override + String convert(String word) { + if (!word.isEmpty) { + if (word.contains("ed", word.length - 2)) { + RegExp reg = new RegExp( + r'^(back|dis|for|fore|in|inter|mis|off|over|out|par|pre|re|type|un|under|up)(.+)$'); + if (reg.hasMatch(word)) { + if (!verbsEndingWithEd.contains(reg.firstMatch(word)!.group(2))) + return word; + } else if (!verbsEndingWithEd.contains(word)) { + return word; + } + } + + for (var r in _inflectionRules) { + var pattern = r.first as RegExp; + if (pattern.hasMatch(word)) { + return word.replaceAllMapped(pattern, r.last as MatchToString); + } + } + } + + return word; + } +} + +final Converter PAST = new PastEncoder(); diff --git a/packages/inflection2/lib/src/plural.dart b/packages/inflection2/lib/src/plural.dart new file mode 100644 index 00000000..550d7291 --- /dev/null +++ b/packages/inflection2/lib/src/plural.dart @@ -0,0 +1,87 @@ +//library inflection2.plural; + +import 'dart:convert'; + +import 'uncountable_nouns.dart'; +import 'irregular_plural_nouns.dart'; +import 'util.dart'; + +class PluralEncoder extends Converter { + final List _inflectionRules = []; + + PluralEncoder() { + irregularPluralNouns.forEach((singular, plural) { + addIrregularInflectionRule(singular, plural); + }); + + [ + [r'$', (Match m) => 's'], + [r's$', (Match m) => 's'], + [r'^(ax|test)is$', (Match m) => '${m[1]}es'], + [r'(octop|vir)us$', (Match m) => '${m[1]}i'], + [r'(octop|vir)i$', (Match m) => m[0]], + [r'(alias|status)$', (Match m) => '${m[1]}es'], + [r'(bu)s$', (Match m) => '${m[1]}ses'], + [r'(buffal|tomat)o$', (Match m) => '${m[1]}oes'], + [r'([ti])um$', (Match m) => '${m[1]}a'], + [r'([ti])a$', (Match m) => m[0]], + [r'sis$', (Match m) => 'ses'], + [r'(?:([^f])fe|([lr])f)$', (Match m) => '${m[1]}${m[2]}ves'], + [r'([^aeiouy]|qu)y$', (Match m) => '${m[1]}ies'], + [r'(x|ch|ss|sh)$', (Match m) => '${m[1]}es'], + [r'(matr|vert|ind)(?:ix|ex)$', (Match m) => '${m[1]}ices'], + [r'^(m|l)ouse$', (Match m) => '${m[1]}ice'], + [r'^(m|l)ice$', (Match m) => m[0]], + [r'^(ox)$', (Match m) => '${m[1]}en'], + [r'^(oxen)$', (Match m) => m[1]], + [r'(quiz)$', (Match m) => '${m[1]}zes'] + ] + .reversed + .forEach((rule) => addInflectionRule(rule.first as String, rule.last)); + } + + void addInflectionRule(String singular, dynamic plural) { + _inflectionRules.add([new RegExp(singular, caseSensitive: false), plural]); + } + + void addIrregularInflectionRule(String singular, String plural) { + final s0 = singular.substring(0, 1); + final srest = singular.substring(1); + final p0 = plural.substring(0, 1); + final prest = plural.substring(1); + + if (s0.toUpperCase() == p0.toUpperCase()) { + addInflectionRule('(${s0})${srest}\$', (Match m) => '${m[1]}${prest}'); + addInflectionRule('(${p0})${prest}\$', (Match m) => '${m[1]}${prest}'); + } else { + addInflectionRule('${s0.toUpperCase()}(?i)${srest}\$', + (Match m) => '${p0.toUpperCase()}${prest}'); + addInflectionRule('${s0.toLowerCase()}(?i)${srest}\$', + (Match m) => '${p0.toUpperCase()}${prest}'); + addInflectionRule('${p0.toUpperCase()}(?i)${prest}\$', + (Match m) => '${p0.toUpperCase()}${prest}'); + addInflectionRule('${p0.toLowerCase()}(?i)${prest}\$', + (Match m) => '${p0.toLowerCase()}${prest}'); + } + } + + @override + String convert(String word) { + if (!word.isEmpty) { + if (uncountableNouns.contains(word.toLowerCase())) { + return word; + } else { + for (var r in _inflectionRules) { + var pattern = r.first as RegExp; + if (pattern.hasMatch(word)) { + return word.replaceAllMapped(pattern, r.last as MatchToString); + } + } + } + } + + return word; + } +} + +final Converter PLURAL = new PluralEncoder(); diff --git a/packages/inflection2/lib/src/plural_verb.dart b/packages/inflection2/lib/src/plural_verb.dart new file mode 100644 index 00000000..9c9895ee --- /dev/null +++ b/packages/inflection2/lib/src/plural_verb.dart @@ -0,0 +1,49 @@ +//library inflection2.plural_verb; + +import 'dart:convert'; + +import 'irregular_plural_verbs.dart'; +import 'util.dart'; + +class PluralVerbEncoder extends Converter { + final List _inflectionRules = []; + + PluralVerbEncoder() { + irregularPluralVerbs.forEach((singular, plural) { + addInflectionRule(singular, (Match m) => plural); + }); + + [ + [r'e?s$', (Match m) => ''], + [r'ies$', (Match m) => 'y'], + [r'([^h|z|o|i])es$', (Match m) => '${m[1]}e'], + [r'ses$', (Match m) => 's'], + [r'zzes$', (Match m) => 'zz'], + [r'([cs])hes$', (Match m) => '${m[1]}h'], + [r'xes$', (Match m) => 'x'], + [r'sses$', (Match m) => 'ss'] + ] + .reversed + .forEach((rule) => addInflectionRule(rule.first as String, rule.last)); + } + + void addInflectionRule(String singular, dynamic plural) { + _inflectionRules.add([new RegExp(singular, caseSensitive: false), plural]); + } + + @override + String convert(String word) { + if (!word.isEmpty) { + for (var r in _inflectionRules) { + var pattern = r.first as RegExp; + if (pattern.hasMatch(word)) { + return word.replaceAllMapped(pattern, r.last as MatchToString); + } + } + } + + return word; + } +} + +final Converter PLURALVERB = new PluralVerbEncoder(); diff --git a/packages/inflection2/lib/src/singular.dart b/packages/inflection2/lib/src/singular.dart new file mode 100644 index 00000000..60785c45 --- /dev/null +++ b/packages/inflection2/lib/src/singular.dart @@ -0,0 +1,95 @@ +//library inflection2.singular; + +import 'dart:convert'; + +import 'uncountable_nouns.dart'; +import 'irregular_plural_nouns.dart'; +import 'util.dart'; + +class SingularEncoder extends Converter { + final List _inflectionRules = []; + + SingularEncoder() { + irregularPluralNouns.forEach((singular, plural) { + addIrregularInflectionRule(singular, plural); + }); + + [ + [r's$', (Match m) => ''], + [r'(ss)$', (Match m) => m[1]], + [r'(n)ews$', (Match m) => '${m[1]}ews'], // TODO: uncountable? + [r'([ti])a$', (Match m) => '${m[1]}um'], + [ + r'((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(sis|ses)$', + (Match m) => '${m[1]}sis' + ], + [r'(^analy)(sis|ses)$', (Match m) => '${m[1]}sis'], // TODO: not needed? + [r'([^f])ves$', (Match m) => '${m[1]}fe'], + [r'(hive|tive)s$', (Match m) => m[1]], + [r'([lr])ves$', (Match m) => '${m[1]}f'], + [r'([^aeiouy]|qu)ies$', (Match m) => '${m[1]}y'], + [r'(s)eries$', (Match m) => '${m[1]}eries'], // TODO: uncountable + [r'(m)ovies$', (Match m) => '${m[1]}ovie'], + [r'(x|ch|ss|sh)es$', (Match m) => m[1]], + [r'^(m|l)ice$', (Match m) => '${m[1]}ouse'], + [r'(bus)(es)?$', (Match m) => m[1]], + [r'(shoe)s$', (Match m) => m[1]], + [r'(cris|test)(is|es)$', (Match m) => '${m[1]}is'], + [r'^(a)x[ie]s$', (Match m) => '${m[1]}xis'], + [r'(octop|vir)(us|i)$', (Match m) => '${m[1]}us'], + [r'(alias|status)(es)?$', (Match m) => m[1]], + [r'^(ox)en', (Match m) => m[1]], + [r'(vert|ind)ices$', (Match m) => '${m[1]}ex'], + [r'(matr)ices$', (Match m) => '${m[1]}ix'], + [r'(quiz)zes$', (Match m) => m[1]], + [r'(database)s$', (Match m) => m[1]] + ] + .reversed + .forEach((rule) => addInflectionRule(rule.first as String, rule.last)); + } + + void addInflectionRule(String plural, dynamic singular) { + _inflectionRules.add([new RegExp(plural, caseSensitive: false), singular]); + } + + void addIrregularInflectionRule(String singular, String plural) { + final s0 = singular.substring(0, 1); + final srest = singular.substring(1); + final p0 = plural.substring(0, 1); + final prest = plural.substring(1); + + if (s0.toUpperCase() == p0.toUpperCase()) { + addInflectionRule('(${s0})${srest}\$', (Match m) => '${m[1]}${srest}'); + addInflectionRule('(${p0})${prest}\$', (Match m) => '${m[1]}${srest}'); + } else { + addInflectionRule('${s0.toUpperCase()}(?i)${srest}\$', + (Match m) => '${s0.toUpperCase()}${srest}'); + addInflectionRule('${s0.toLowerCase()}(?i)${srest}\$', + (Match m) => '${s0.toUpperCase()}${srest}'); + addInflectionRule('${p0.toUpperCase()}(?i)${prest}\$', + (Match m) => '${s0.toUpperCase()}${srest}'); + addInflectionRule('${p0.toLowerCase()}(?i)${prest}\$', + (Match m) => '${s0.toLowerCase()}${srest}'); + } + } + + @override + String convert(String word) { + if (!word.isEmpty) { + if (uncountableNouns.contains(word.toLowerCase())) { + return word; + } else { + for (var r in _inflectionRules) { + var pattern = r.first as RegExp; + if (pattern.hasMatch(word)) { + return word.replaceAllMapped(pattern, r.last as MatchToString); + } + } + } + } + + return word; + } +} + +final Converter SINGULAR = new SingularEncoder(); diff --git a/packages/inflection2/lib/src/singular_verb.dart b/packages/inflection2/lib/src/singular_verb.dart new file mode 100644 index 00000000..4588152f --- /dev/null +++ b/packages/inflection2/lib/src/singular_verb.dart @@ -0,0 +1,46 @@ +//library inflection2.singular_verb; + +import 'dart:convert'; + +import 'irregular_plural_verbs.dart'; +import 'util.dart'; + +class SingularVerbEncoder extends Converter { + final List _inflectionRules = []; + + SingularVerbEncoder() { + irregularPluralVerbs.forEach((singular, plural) { + addInflectionRule(plural, (Match m) => singular); + }); + + [ + [r'$', (Match m) => 's'], + [r'([^aeiou])y$', (Match m) => '${m[1]}ies'], + [r'(z)$', (Match m) => '${m[1]}es'], + [r'(ss|zz|x|h|o|us)$', (Match m) => '${m[1]}es'], + [r'(ed)$', (Match m) => '${m[1]}'] + ] + .reversed + .forEach((rule) => addInflectionRule(rule.first as String, rule.last)); + } + + void addInflectionRule(String singular, dynamic plural) { + _inflectionRules.add([new RegExp(singular, caseSensitive: false), plural]); + } + + @override + String convert(String word) { + if (!word.isEmpty) { + for (var r in _inflectionRules) { + var pattern = r.first as RegExp; + if (pattern.hasMatch(word)) { + return word.replaceAllMapped(pattern, r.last as MatchToString); + } + } + } + + return word; + } +} + +final Converter SINGULARVERB = new SingularVerbEncoder(); diff --git a/packages/inflection2/lib/src/snake_case.dart b/packages/inflection2/lib/src/snake_case.dart new file mode 100644 index 00000000..2e0fc74f --- /dev/null +++ b/packages/inflection2/lib/src/snake_case.dart @@ -0,0 +1,24 @@ +//library inflection2.snake_case; + +import 'dart:convert'; + +final _underscoreRE0 = new RegExp(r'''([A-Z\d]+)([A-Z][a-z])'''); +final _underscoreRE1 = new RegExp(r'''([a-z\d])([A-Z])'''); +final _underscoreRE2 = new RegExp(r'[-\s]'); + +class SnakeCaseEncoder extends Converter { + const SnakeCaseEncoder(); + + /// Converts the input [phrase] to 'spinal case', i.e. a hyphen-delimited, + /// lowercase form. Also known as 'kebab case' or 'lisp case'. + @override + String convert(String phrase) { + return phrase + .replaceAllMapped(_underscoreRE0, (match) => "${match[1]}_${match[2]}") + .replaceAllMapped(_underscoreRE1, (match) => "${match[1]}_${match[2]}") + .replaceAll(_underscoreRE2, "_") + .toLowerCase(); + } +} + +const Converter SNAKE_CASE = const SnakeCaseEncoder(); diff --git a/packages/inflection2/lib/src/spinal_case.dart b/packages/inflection2/lib/src/spinal_case.dart new file mode 100644 index 00000000..99bd3bb9 --- /dev/null +++ b/packages/inflection2/lib/src/spinal_case.dart @@ -0,0 +1,24 @@ +//library inflection2.spinal_case; + +import 'dart:convert'; + +final _underscoreRE0 = new RegExp(r'''([A-Z\d]+)([A-Z][a-z])'''); +final _underscoreRE1 = new RegExp(r'''([a-z\d])([A-Z])'''); +final _underscoreRE2 = new RegExp(r'[_\s]'); + +class SpinalCaseEncoder extends Converter { + const SpinalCaseEncoder(); + + /// Converts the input [phrase] to 'spinal case', i.e. a hyphen-delimited, + /// lowercase form. Also known as 'kebab case' or 'lisp case'. + @override + String convert(String phrase) { + return phrase + .replaceAllMapped(_underscoreRE0, (match) => "${match[1]}-${match[2]}") + .replaceAllMapped(_underscoreRE1, (match) => "${match[1]}-${match[2]}") + .replaceAll(_underscoreRE2, "-") + .toLowerCase(); + } +} + +const Converter SPINAL_CASE = const SpinalCaseEncoder(); diff --git a/packages/inflection2/lib/src/uncountable_nouns.dart b/packages/inflection2/lib/src/uncountable_nouns.dart new file mode 100644 index 00000000..022d6df9 --- /dev/null +++ b/packages/inflection2/lib/src/uncountable_nouns.dart @@ -0,0 +1,16 @@ +//library inflection2.uncountable; + +/// Uncountable nouns are substances, concepts etc that we cannot divide into +/// separate elements. We cannot "count" them. +final Set uncountableNouns = new Set.from(const [ + "equipment", + "information", + "rice", + "money", + "species", + "series", + "fish", + "sheep", + "jeans", + "police" +]); diff --git a/packages/inflection2/lib/src/util.dart b/packages/inflection2/lib/src/util.dart new file mode 100644 index 00000000..0f738eff --- /dev/null +++ b/packages/inflection2/lib/src/util.dart @@ -0,0 +1 @@ +typedef MatchToString = String Function(Match m); diff --git a/packages/inflection2/lib/src/verbs_ending_with_ed.dart b/packages/inflection2/lib/src/verbs_ending_with_ed.dart new file mode 100644 index 00000000..8d7aab56 --- /dev/null +++ b/packages/inflection2/lib/src/verbs_ending_with_ed.dart @@ -0,0 +1,21 @@ +//library inflection2.verbs_ending_with_ed; + +/// A collection of verbs ending with -ed. +final List verbsEndingWithEd = const [ + "bed", + "bleed", + "breed", + "embed", + "exceed", + "feed", + "heed", + "need", + "proceed", + "seed", + "shred" + "speed", + "succeed", + "ted", + "wed", + "weed" +]; diff --git a/packages/inflection2/pubspec.yaml b/packages/inflection2/pubspec.yaml new file mode 100644 index 00000000..22f716b0 --- /dev/null +++ b/packages/inflection2/pubspec.yaml @@ -0,0 +1,9 @@ +name: inflection2 +version: 1.0.0 +description: Grammatical Inflection encoders. +homepage: https://github.com/thosakwe/dart-inflection +publish_to: none +environment: + sdk: '>=2.12.0 <3.0.0' +dev_dependencies: + test: ^1.17.3 diff --git a/packages/inflection2/test/all_test.dart b/packages/inflection2/test/all_test.dart new file mode 100644 index 00000000..f13f2150 --- /dev/null +++ b/packages/inflection2/test/all_test.dart @@ -0,0 +1,21 @@ +import 'inflection_test.dart' as inflection_test; +import 'past_test.dart' as past_test; +import 'plural_test.dart' as plural_test; +import 'plural_verb_test.dart' as plural_verb_test; +import 'singular_test.dart' as singular_test; +import 'singular_verb_test.dart' as singular_verb_test; +import 'snake_case_test.dart' as snake_case_test; +import 'spinal_case_test.dart' as spinal_case_test; +import 'is_tense_test.dart' as is_tense_test; + +void main() { + inflection_test.main(); + past_test.main(); + plural_test.main(); + plural_verb_test.main(); + singular_test.main(); + singular_verb_test.main(); + snake_case_test.main(); + spinal_case_test.main(); + is_tense_test.main(); +} diff --git a/packages/inflection2/test/inflection_test.dart b/packages/inflection2/test/inflection_test.dart new file mode 100644 index 00000000..1fd3f33e --- /dev/null +++ b/packages/inflection2/test/inflection_test.dart @@ -0,0 +1,18 @@ +library inflection.test; + +import 'package:test/test.dart'; + +import '../lib/inflection2.dart'; + +void main() { + group("The inflection library", () { + test("provides a few convenient helper functions", () { + expect(pluralize("axis"), equals("axes")); + expect(convertToPlural("axis"), equals("axes")); + expect(singularize("Houses"), equals("House")); + expect(convertToSingular("Houses"), equals("House")); + expect(convertToSnakeCase("CamelCase"), equals("camel_case")); + expect(convertToSpinalCase("CamelCase"), equals("camel-case")); + }); + }); +} diff --git a/packages/inflection2/test/is_tense_test.dart b/packages/inflection2/test/is_tense_test.dart new file mode 100644 index 00000000..51ff35b9 --- /dev/null +++ b/packages/inflection2/test/is_tense_test.dart @@ -0,0 +1,16 @@ +library inflection.is_tense.test; + +import 'package:test/test.dart'; + +import '../lib/inflection2.dart'; + +void main() { + group("isTense", () { + test('correctly identifies if a word is in past tense', () { + expect(isPastTense('run'), false); + expect(isPastTense('ran'), true); + expect(isPastTense('PusHed'), true); + expect(isPastTense('PusH'), false); + }); + }); +} diff --git a/packages/inflection2/test/past_test.dart b/packages/inflection2/test/past_test.dart new file mode 100644 index 00000000..fd466b48 --- /dev/null +++ b/packages/inflection2/test/past_test.dart @@ -0,0 +1,46 @@ +library inflection.past.test; + +import 'package:test/test.dart'; + +import '../lib/src/irregular_past_verbs.dart'; +import '../lib/src/past.dart'; + +void main() { + group("The PastEncoder", () { + test("converts verbs from present or participle to past", () { + expect(PAST.convert(""), equals("")); + expect(PAST.convert("ask"), equals("asked")); + expect(PAST.convert("close"), equals("closed")); + expect(PAST.convert("die"), equals("died")); + expect(PAST.convert("phone"), equals("phoned")); + expect(PAST.convert("play"), equals("played")); + expect(PAST.convert("destroy"), equals("destroyed")); + expect(PAST.convert("show"), equals("showed")); + expect(PAST.convert("marry"), equals("married")); + expect(PAST.convert("study"), equals("studied")); + expect(PAST.convert("visit"), equals("visited")); + expect(PAST.convert("miss"), equals("missed")); + expect(PAST.convert("watch"), equals("watched")); + expect(PAST.convert("finish"), equals("finished")); + expect(PAST.convert("fix"), equals("fixed")); + expect(PAST.convert("buzz"), equals("buzzed")); + expect(PAST.convert("asked"), equals("asked")); + expect(PAST.convert("closed"), equals("closed")); + expect(PAST.convert("reopened"), equals("reopened")); + expect(PAST.convert("unseed"), equals("unseeded")); + }); + + test("handles irregular past verbs", () { + irregularPastVerbs.forEach((String presentOrParticiple, String past) { + expect(PAST.convert(presentOrParticiple), equals(past)); + }); + expect(PAST.convert("forgo"), equals("forwent")); + expect(PAST.convert("undo"), equals("undid")); + expect(PAST.convert("outsell"), equals("outsold")); + expect(PAST.convert("rebreed"), equals("rebred")); + expect(PAST.convert("arose"), equals("arose")); + expect(PAST.convert("backslid"), equals("backslid")); + expect(PAST.convert("forbade"), equals("forbade")); + }); + }); +} diff --git a/packages/inflection2/test/plural_test.dart b/packages/inflection2/test/plural_test.dart new file mode 100644 index 00000000..fba9dabe --- /dev/null +++ b/packages/inflection2/test/plural_test.dart @@ -0,0 +1,66 @@ +library inflection.plural.test; + +import 'package:test/test.dart'; + +import '../lib/inflection2.dart'; +import '../lib/src/uncountable_nouns.dart'; + +void main() { + group("The PluralEncoder", () { + test("converts nouns from singular to plural", () { + expect(PLURAL.convert(""), equals("")); + expect(PLURAL.convert("House"), equals("Houses")); + expect(PLURAL.convert("house"), equals("houses")); + expect(PLURAL.convert("dog"), equals("dogs")); + expect(PLURAL.convert("axis"), equals("axes")); + expect(PLURAL.convert("testis"), equals("testes")); + expect(PLURAL.convert("octopus"), equals("octopi")); + expect(PLURAL.convert("virus"), equals("viri")); + expect(PLURAL.convert("octopi"), equals("octopi")); + expect(PLURAL.convert("viri"), equals("viri")); + expect(PLURAL.convert("alias"), equals("aliases")); + expect(PLURAL.convert("status"), equals("statuses")); + expect(PLURAL.convert("bus"), equals("buses")); + expect(PLURAL.convert("buffalo"), equals("buffaloes")); + expect(PLURAL.convert("tomato"), equals("tomatoes")); + expect(PLURAL.convert("ultimatum"), equals("ultimata")); + expect(PLURAL.convert("pentium"), equals("pentia")); + expect(PLURAL.convert("ultimata"), equals("ultimata")); + expect(PLURAL.convert("pentia"), equals("pentia")); + expect(PLURAL.convert("nemesis"), equals("nemeses")); + expect(PLURAL.convert("hive"), equals("hives")); + expect(PLURAL.convert("fly"), equals("flies")); + expect(PLURAL.convert("dish"), equals("dishes")); + expect(PLURAL.convert("bench"), equals("benches")); + expect(PLURAL.convert("matrix"), equals("matrices")); + expect(PLURAL.convert("vertex"), equals("vertices")); + expect(PLURAL.convert("index"), equals("indices")); + expect(PLURAL.convert("mouse"), equals("mice")); + expect(PLURAL.convert("louse"), equals("lice")); + expect(PLURAL.convert("mice"), equals("mice")); + expect(PLURAL.convert("lice"), equals("lice")); + expect(PLURAL.convert("ox"), equals("oxen")); + expect(PLURAL.convert("ox"), equals("oxen")); + expect(PLURAL.convert("oxen"), equals("oxen")); + expect(PLURAL.convert("quiz"), equals("quizzes")); + }); + + test("handles uncountable nouns", () { + uncountableNouns.forEach((noun) { + expect(PLURAL.convert(noun), equals(noun)); + }); + + uncountableNouns.forEach((noun) { + final upperNoun = noun.toUpperCase(); + expect(PLURAL.convert(upperNoun), equals(upperNoun)); + }); + }); + + test("handles irregular plural nouns", () { + expect(PLURAL.convert("person"), equals("people")); + expect(PLURAL.convert("Child"), equals("Children")); + expect(PLURAL.convert("children"), equals("children")); + expect(PLURAL.convert("man"), equals("men")); + }); + }); +} diff --git a/packages/inflection2/test/plural_verb_test.dart b/packages/inflection2/test/plural_verb_test.dart new file mode 100644 index 00000000..9d7c3539 --- /dev/null +++ b/packages/inflection2/test/plural_verb_test.dart @@ -0,0 +1,35 @@ +library inflection.plural_verb.test; + +import 'package:test/test.dart'; + +import '../lib/src/plural_verb.dart'; + +void main() { + group("The PluralVerbEncoder", () { + test("converts verbs from singular to plural", () { + expect(PLURALVERB.convert(""), equals("")); + expect(PLURALVERB.convert("eats"), equals("eat")); + expect(PLURALVERB.convert("goes"), equals("go")); + expect(PLURALVERB.convert("boxes"), equals("box")); + expect(PLURALVERB.convert("pays"), equals("pay")); + expect(PLURALVERB.convert("rides"), equals("ride")); + expect(PLURALVERB.convert("writes"), equals("write")); + expect(PLURALVERB.convert("wears"), equals("wear")); + expect(PLURALVERB.convert("steals"), equals("steal")); + expect(PLURALVERB.convert("springs"), equals("spring")); + expect(PLURALVERB.convert("speaks"), equals("speak")); + expect(PLURALVERB.convert("sings"), equals("sing")); + expect(PLURALVERB.convert("buses"), equals("bus")); + expect(PLURALVERB.convert("knows"), equals("know")); + expect(PLURALVERB.convert("hides"), equals("hide")); + expect(PLURALVERB.convert("catches"), equals("catch")); + }); + + test("handles irregular plural verbs", () { + expect(PLURALVERB.convert("am"), equals("are")); + expect(PLURALVERB.convert("is"), equals("are")); + expect(PLURALVERB.convert("was"), equals("were")); + expect(PLURALVERB.convert("has"), equals("have")); + }); + }); +} diff --git a/packages/inflection2/test/singular_test.dart b/packages/inflection2/test/singular_test.dart new file mode 100644 index 00000000..f55cc7eb --- /dev/null +++ b/packages/inflection2/test/singular_test.dart @@ -0,0 +1,65 @@ +library inflection.singular.test; + +import 'package:test/test.dart'; + +import '../lib/src/singular.dart'; +import '../lib/src/uncountable_nouns.dart'; + +void main() { + group("The SingularEncoder", () { + test("converts nouns from plural to singular", () { + expect(SINGULAR.convert(""), equals("")); + expect(SINGULAR.convert("Houses"), equals("House")); + expect(SINGULAR.convert("houses"), equals("house")); + expect(SINGULAR.convert("ultimata"), equals("ultimatum")); + expect(SINGULAR.convert("pentia"), equals("pentium")); + expect(SINGULAR.convert("analyses"), equals("analysis")); + expect(SINGULAR.convert("diagnoses"), equals("diagnosis")); + expect(SINGULAR.convert("Parentheses"), equals("Parenthesis")); + expect(SINGULAR.convert("lives"), equals("life")); + expect(SINGULAR.convert("hives"), equals("hive")); + expect(SINGULAR.convert("tives"), equals("tive")); + expect(SINGULAR.convert("shelves"), equals("shelf")); + expect(SINGULAR.convert("qualities"), equals("quality")); + expect(SINGULAR.convert("series"), equals("series")); + expect(SINGULAR.convert("movies"), equals("movie")); + expect(SINGULAR.convert("benches"), equals("bench")); + expect(SINGULAR.convert("fishes"), equals("fish")); + expect(SINGULAR.convert("mice"), equals("mouse")); + expect(SINGULAR.convert("lice"), equals("louse")); + expect(SINGULAR.convert("buses"), equals("bus")); + expect(SINGULAR.convert("shoes"), equals("shoe")); + expect(SINGULAR.convert("testis"), equals("testis")); + expect(SINGULAR.convert("crisis"), equals("crisis")); + expect(SINGULAR.convert("axes"), equals("axis")); + expect(SINGULAR.convert("axis"), equals("axis")); + expect(SINGULAR.convert("viri"), equals("virus")); + expect(SINGULAR.convert("octopi"), equals("octopus")); + expect(SINGULAR.convert("aliases"), equals("alias")); + expect(SINGULAR.convert("statuses"), equals("status")); + expect(SINGULAR.convert("vertices"), equals("vertex")); + expect(SINGULAR.convert("indices"), equals("index")); + expect(SINGULAR.convert("Matrices"), equals("Matrix")); + expect(SINGULAR.convert("quizzes"), equals("quiz")); + expect(SINGULAR.convert("databases"), equals("database")); + }); + + test("handles uncountable nouns", () { + uncountableNouns.forEach((noun) { + expect(SINGULAR.convert(noun), equals(noun)); + }); + + uncountableNouns.forEach((noun) { + final upperNoun = noun.toUpperCase(); + expect(SINGULAR.convert(upperNoun), equals(upperNoun)); + }); + }); + + test("handles irregular plural nouns", () { + expect(SINGULAR.convert("people"), equals("person")); + expect(SINGULAR.convert("Children"), equals("Child")); + expect(SINGULAR.convert("child"), equals("child")); + expect(SINGULAR.convert("men"), equals("man")); + }); + }); +} diff --git a/packages/inflection2/test/singular_verb_test.dart b/packages/inflection2/test/singular_verb_test.dart new file mode 100644 index 00000000..de1dcf41 --- /dev/null +++ b/packages/inflection2/test/singular_verb_test.dart @@ -0,0 +1,34 @@ +library inflection.singular_verb.test; + +import 'package:test/test.dart'; + +import '../lib/src/singular_verb.dart'; + +void main() { + group("The SingularVerbEncoder", () { + test("converts verbs from singular to plural", () { + expect(SINGULARVERB.convert(""), equals("")); + expect(SINGULARVERB.convert("eat"), equals("eats")); + expect(SINGULARVERB.convert("go"), equals("goes")); + expect(SINGULARVERB.convert("box"), equals("boxes")); + expect(SINGULARVERB.convert("pay"), equals("pays")); + expect(SINGULARVERB.convert("ride"), equals("rides")); + expect(SINGULARVERB.convert("write"), equals("writes")); + expect(SINGULARVERB.convert("wear"), equals("wears")); + expect(SINGULARVERB.convert("steal"), equals("steals")); + expect(SINGULARVERB.convert("spring"), equals("springs")); + expect(SINGULARVERB.convert("speak"), equals("speaks")); + expect(SINGULARVERB.convert("sing"), equals("sings")); + expect(SINGULARVERB.convert("bus"), equals("buses")); + expect(SINGULARVERB.convert("know"), equals("knows")); + expect(SINGULARVERB.convert("hide"), equals("hides")); + expect(SINGULARVERB.convert("catch"), equals("catches")); + }); + + test("handles irregular plural verbs", () { + expect(SINGULARVERB.convert("are"), equals("is")); + expect(SINGULARVERB.convert("were"), equals("was")); + expect(SINGULARVERB.convert("have"), equals("has")); + }); + }); +} diff --git a/packages/inflection2/test/snake_case_test.dart b/packages/inflection2/test/snake_case_test.dart new file mode 100644 index 00000000..94492f4b --- /dev/null +++ b/packages/inflection2/test/snake_case_test.dart @@ -0,0 +1,19 @@ +library inflection.snake_case.test; + +import 'package:test/test.dart'; + +import '../lib/src/snake_case.dart'; + +void main() { + group("The SnakeCaseEncoder", () { + test("converts phrases to 'snake_case'", () { + expect(SNAKE_CASE.convert(''), equals('')); + expect(SNAKE_CASE.convert("CamelCaseName"), equals("camel_case_name")); + expect(SNAKE_CASE.convert("propertyName"), equals("property_name")); + expect(SNAKE_CASE.convert("property"), equals("property")); + expect(SNAKE_CASE.convert("lisp-case"), equals("lisp_case")); + expect(SNAKE_CASE.convert("This is a nice article"), + equals("this_is_a_nice_article")); + }); + }); +} diff --git a/packages/inflection2/test/spinal_case_test.dart b/packages/inflection2/test/spinal_case_test.dart new file mode 100644 index 00000000..d140b677 --- /dev/null +++ b/packages/inflection2/test/spinal_case_test.dart @@ -0,0 +1,19 @@ +library inflection.spinal_case.test; + +import 'package:test/test.dart'; + +import '../lib/src/spinal_case.dart'; + +void main() { + group("The SpinalCaseEncoder", () { + test("converts phrases to 'spinal-case'", () { + expect(SPINAL_CASE.convert(''), equals('')); + expect(SPINAL_CASE.convert("CamelCaseName"), equals("camel-case-name")); + expect(SPINAL_CASE.convert("propertyName"), equals("property-name")); + expect(SPINAL_CASE.convert("property"), equals("property")); + expect(SPINAL_CASE.convert("snake_case"), equals("snake-case")); + expect(SPINAL_CASE.convert("This is a nice article"), + equals("this-is-a-nice-article")); + }); + }); +} diff --git a/packages/orm/angel_migration/pubspec.yaml b/packages/orm/angel_migration/pubspec.yaml index cd2b2739..38194526 100755 --- a/packages/orm/angel_migration/pubspec.yaml +++ b/packages/orm/angel_migration/pubspec.yaml @@ -1,7 +1,7 @@ name: angel_migration version: 4.0.0 description: Database migration runtime for Angel's ORM. Use this package to define schemas. -homepage: https://github.com/angel-dart/migration +homepage: https://github.com/dukefirehawk/angel publish_to: none environment: sdk: '>=2.12.0 <3.0.0' diff --git a/packages/orm/angel_orm/pubspec.yaml b/packages/orm/angel_orm/pubspec.yaml index 3c9a9aea..24c233af 100644 --- a/packages/orm/angel_orm/pubspec.yaml +++ b/packages/orm/angel_orm/pubspec.yaml @@ -1,8 +1,7 @@ name: angel_orm version: 4.0.0 description: Runtime support for Angel's ORM. Includes base classes for queries. -homepage: https://github.com/angel-dart/orm -environment: +homepage: https://github.com/dukefirehawk/angel sdk: '>=2.12.0 <3.0.0' dependencies: charcode: ^1.2.0 diff --git a/packages/orm/angel_orm_generator/pubspec.yaml b/packages/orm/angel_orm_generator/pubspec.yaml index effdd669..c2e9a7b8 100644 --- a/packages/orm/angel_orm_generator/pubspec.yaml +++ b/packages/orm/angel_orm_generator/pubspec.yaml @@ -1,8 +1,7 @@ name: angel_orm_generator -version: 3.0.0 +version: 4.0.0 description: Code generators for Angel's ORM. Generates query builder classes. -author: Tobe O -homepage: https://github.com/angel-dart/orm +homepage: https://github.com/dukefirehawk/angel publish_to: none environment: sdk: '>=2.10.0 <3.0.0' @@ -52,7 +51,7 @@ dev_dependencies: build_runner: ^1.11.5 collection: ^1.0.0 pedantic: ^1.11.0 - postgres: - git: - url: https://github.com/dukefirehawk/postgresql-dart + postgres: ^2.2.0 + # git: + # url: https://github.com/dukefirehawk/postgresql-dart test: ^1.16.5