From 37a5306bd9d8170bb6880bd05a37f6c9cd771d2c Mon Sep 17 00:00:00 2001 From: Ankur Singh Date: Thu, 28 Dec 2023 19:03:31 +0530 Subject: [PATCH 1/6] docs: adds C++ constraint docs (#1696) --- docs/constraints/Cplusplus.md | 41 +++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 docs/constraints/Cplusplus.md diff --git a/docs/constraints/Cplusplus.md b/docs/constraints/Cplusplus.md new file mode 100644 index 0000000000..e95c1e484e --- /dev/null +++ b/docs/constraints/Cplusplus.md @@ -0,0 +1,41 @@ +# C++ Constraints + +These are the C++ specific constraints applied to the MetaModel before reaching the presets. [Read here to get a more general idea on the overall process](../input-processing.md) of converting a MetaModel to a ConstrainedMetaModel. + +## Model Naming +These are the constraints that is applied to model naming. The `Rule key` is what you can use in the options to overwrite the default behavior. See [constraint customization](./README.md#Customization). + +|Rule key|Rule|Resolution| +|---|---|---| +|NO_SPECIAL_CHAR|No special characters| Special characters are replaced by their name, for example `!` is replaced with `exclamation`. For C++ `_` are an exception to this rule. | +|NO_NUMBER_START_CHAR|No numbers as starting characters|Default behavior is pre pending `number_` in front of the first character| +|NO_EMPTY_VALUE|No empty values|Default behavior is to use `empty` as name. | +|NO_RESERVED_KEYWORDS|No reserved keywords|C++ has a list of reserved keywords ([see the full list here](../../src/generators/cplusplus/Constants.ts))| +|NAMING_FORMATTER|Must be formatted equally|Model name is formatted using snake case| + +## Property naming +These are the constraints that is applied to object properties and the naming of them. The `Rule key` is what you can use in the options to overwrite the default behavior. See [constraint customization](./README.md#Customization). +|Rule key|Rule|Resolution| +|---|---|---| +|NO_SPECIAL_CHAR|No special characters| Special characters are replaced by their name, for example `!` is replaced with `exclamation`. For C++ `_` are an exception to this rule. | +|NO_NUMBER_START_CHAR|No numbers as starting characters|Default behavior is pre pending `number_` in front of the first character| +|NO_EMPTY_VALUE|No empty values|Default behavior is to use `empty` as name. | +|NO_RESERVED_KEYWORDS|No reserved keywords|C++ has a list of reserved keywords ([see the full list here](../../src/generators/cplusplus/Constants.ts))| +|NAMING_FORMATTER|Must be formatted equally|Property naming is formatted using snake case| +|NO_DUPLICATE_PROPERTIES|No duplicate properties|If any of the above constraints changes the property name, we must make sure that no duplicates exist within the same object. If any is encountered `reserved_` is pre-pended. This is done recursively until no duplicates are found.| + + +## Enum key constraints +These are the constraints that is applied to enum keys. The `Rule key` is what you can use in the options to overwrite the default behavior. See [constraint customization](./README.md#Customization). + +|Rule key|Rule|Resolution| +|---|---|---| +|NO_SPECIAL_CHAR|No special characters| Special characters are replaced by their name, for example `!` is replaced with `exclamation`. For C++ `_` are an exception to this rule. | +|NO_NUMBER_START_CHAR|No numbers as starting characters|Default behavior is pre pending `number_` in front of the first character| +|NO_EMPTY_VALUE|No empty values|Default behavior is to use `empty` as name. | +|NO_RESERVED_KEYWORDS|No reserved keywords|C++ has a list of reserved keywords ([see the full list here](../../src/generators/cplusplus/Constants.ts))| +|NAMING_FORMATTER|Must be formatted equally|Enum key is formatted using snake case| +|NO_DUPLICATE_KEYS|No duplicate enum keys|If any of the above constraints changes the enum key, we must make sure that no duplicates exist within the same enum. If any is encountered `reserved_` is pre-pended. This is done recursively until no duplicates are found.| + +## Constant +These are the constraints that are applied to constants. Currently, there are no hooks one can overwrite inside it. From ad36dfb842039f0b162c7c3a5e08f310a825064c Mon Sep 17 00:00:00 2001 From: sheshe1 <92985478+anchalpanwar17@users.noreply.github.com> Date: Thu, 28 Dec 2023 21:48:08 +0530 Subject: [PATCH 2/6] chore(website): update the store link in footer (#1705) Co-authored-by: Ashmit JaiSarita Gupta <43639341+devilkiller-ag@users.noreply.github.com>%0ACo-authored-by: Jonas Lagoni --- modelina-website/src/components/layouts/Footer.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modelina-website/src/components/layouts/Footer.tsx b/modelina-website/src/components/layouts/Footer.tsx index 34fd458060..a9bdd37231 100644 --- a/modelina-website/src/components/layouts/Footer.tsx +++ b/modelina-website/src/components/layouts/Footer.tsx @@ -58,7 +58,7 @@ export default function Footer() {
  • Date: Fri, 29 Dec 2023 00:33:54 +0530 Subject: [PATCH 3/6] test: added test for PHP constraint (#1695) --- .../constrainer/ConstantConstrainer.spec.ts | 19 ++ .../php/constrainer/EnumConstrainer.spec.ts | 167 ++++++++++++++++ .../constrainer/ModelNameConstrainer.spec.ts | 75 ++++++++ .../PropertyKeyConstrainer.spec.ts | 179 ++++++++++++++++++ 4 files changed, 440 insertions(+) create mode 100644 test/generators/php/constrainer/ConstantConstrainer.spec.ts create mode 100644 test/generators/php/constrainer/EnumConstrainer.spec.ts create mode 100644 test/generators/php/constrainer/ModelNameConstrainer.spec.ts create mode 100644 test/generators/php/constrainer/PropertyKeyConstrainer.spec.ts diff --git a/test/generators/php/constrainer/ConstantConstrainer.spec.ts b/test/generators/php/constrainer/ConstantConstrainer.spec.ts new file mode 100644 index 0000000000..71202cdf05 --- /dev/null +++ b/test/generators/php/constrainer/ConstantConstrainer.spec.ts @@ -0,0 +1,19 @@ +import { defaultConstantConstraints } from '../../../../src/generators/php/constrainer/ConstantConstrainer'; + +const mockConstantContext = { + constrainedMetaModel: {} as any +}; + +describe('defaultConstantConstraints', () => { + it('should return a function that returns undefined', () => { + const constantConstraintsFunction = defaultConstantConstraints(); + const result = constantConstraintsFunction(mockConstantContext); + expect(result).toBeUndefined(); + }); + + it('should return a ConstantConstraint type', () => { + const constantConstraintsFunction = defaultConstantConstraints(); + const result = constantConstraintsFunction; + expect(typeof result).toBe('function'); + }); +}); diff --git a/test/generators/php/constrainer/EnumConstrainer.spec.ts b/test/generators/php/constrainer/EnumConstrainer.spec.ts new file mode 100644 index 0000000000..6295e5407b --- /dev/null +++ b/test/generators/php/constrainer/EnumConstrainer.spec.ts @@ -0,0 +1,167 @@ +import { PhpDefaultConstraints } from '../../../../src/generators/php/PhpConstrainer'; +import { EnumModel } from '../../../../src/models/MetaModel'; +import { + ConstrainedEnumModel, + ConstrainedEnumValueModel +} from '../../../../src'; +import { + defaultEnumKeyConstraints, + ModelEnumKeyConstraints +} from '../../../../src/generators/php/constrainer/EnumConstrainer'; + +describe('Php EnumConstrainer', () => { + const enumModel = new EnumModel('test', undefined, {}, []); + const constrainedEnumModel = new ConstrainedEnumModel( + 'test', + undefined, + {}, + '', + [] + ); + + describe('enum keys', () => { + test('should never render special chars', () => { + const constrainedKey = PhpDefaultConstraints.enumKey({ + enumModel, + constrainedEnumModel, + enumKey: '%' + }); + expect(constrainedKey).toEqual('PERCENT'); + }); + + test('should not render number as start char', () => { + const constrainedKey = PhpDefaultConstraints.enumKey({ + enumModel, + constrainedEnumModel, + enumKey: '1' + }); + expect(constrainedKey).toEqual('NUMBER_1'); + }); + + test('should not contain duplicate keys', () => { + const existingConstrainedEnumValueModel = new ConstrainedEnumValueModel( + 'EMPTY', + 'return', + 'return' + ); + const constrainedEnumModel = new ConstrainedEnumModel( + 'test', + undefined, + {}, + '', + [existingConstrainedEnumValueModel] + ); + const constrainedKey = PhpDefaultConstraints.enumKey({ + enumModel, + constrainedEnumModel, + enumKey: '' + }); + expect(constrainedKey).toEqual('RESERVED_EMPTY'); + }); + + test('should never contain empty keys', () => { + const constrainedKey = PhpDefaultConstraints.enumKey({ + enumModel, + constrainedEnumModel, + enumKey: '' + }); + expect(constrainedKey).toEqual('RESERVED_EMPTY'); + }); + + test('should use constant naming format', () => { + const constrainedKey = PhpDefaultConstraints.enumKey({ + enumModel, + constrainedEnumModel, + enumKey: 'some weird_value!"#2' + }); + expect(constrainedKey).toEqual( + 'SOME_WEIRD_VALUE_EXCLAMATION_QUOTATION_HASH_2' + ); + }); + + test('should never render reserved keywords', () => { + const constrainedKey = PhpDefaultConstraints.enumKey({ + enumModel, + constrainedEnumModel, + enumKey: 'return' + }); + expect(constrainedKey).toEqual('RESERVED_RETURN'); + }); + }); + + describe('enum values', () => { + test('should render string values', () => { + const constrainedValue = PhpDefaultConstraints.enumValue({ + enumModel, + constrainedEnumModel, + enumValue: 'string value' + }); + expect(constrainedValue).toEqual('"string value"'); + }); + test('should render boolean values', () => { + const constrainedBooleanValue = PhpDefaultConstraints.enumValue({ + enumModel, + constrainedEnumModel, + enumValue: true + }); + expect(constrainedBooleanValue).toEqual('"true"'); + }); + + test('should render numbers', () => { + const constrainedNumberValue = PhpDefaultConstraints.enumValue({ + enumModel, + constrainedEnumModel, + enumValue: 123 + }); + expect(constrainedNumberValue).toEqual(123); + }); + + test('should render object values', () => { + const constrainedObjectValue = PhpDefaultConstraints.enumValue({ + enumModel, + constrainedEnumModel, + enumValue: { test: 'test' } + }); + expect(constrainedObjectValue).toEqual('"{\\"test\\":\\"test\\"}"'); + }); + + test('should render unknown value', () => { + const constrainedUnknownValue = PhpDefaultConstraints.enumValue({ + enumModel, + constrainedEnumModel, + enumValue: undefined + }); + expect(constrainedUnknownValue).toEqual(`"undefined"`); + }); + }); + + describe('custom constraints', () => { + test('should be able to overwrite all hooks for enum key', () => { + const mockedConstraintCallbacks: Partial = { + NAMING_FORMATTER: jest.fn().mockReturnValue(''), + NO_SPECIAL_CHAR: jest.fn().mockReturnValue(''), + NO_NUMBER_START_CHAR: jest.fn().mockReturnValue(''), + NO_EMPTY_VALUE: jest.fn().mockReturnValue(''), + NO_RESERVED_KEYWORDS: jest.fn().mockReturnValue('') + }; + const constrainFunction = defaultEnumKeyConstraints( + mockedConstraintCallbacks + ); + constrainFunction({ enumModel, constrainedEnumModel, enumKey: '' }); + for (const jestMockCallback of Object.values(mockedConstraintCallbacks)) { + expect(jestMockCallback).toHaveBeenCalled(); + } + }); + test('should be able to overwrite specific hooks for enum key', () => { + const mockedConstraintCallbacks: Partial = { + NAMING_FORMATTER: jest.fn().mockReturnValue('') + }; + const constrainFunction = defaultEnumKeyConstraints( + mockedConstraintCallbacks + ); + constrainFunction({ enumModel, constrainedEnumModel, enumKey: '' }); + + expect(mockedConstraintCallbacks.NAMING_FORMATTER).toHaveBeenCalled(); + }); + }); +}); diff --git a/test/generators/php/constrainer/ModelNameConstrainer.spec.ts b/test/generators/php/constrainer/ModelNameConstrainer.spec.ts new file mode 100644 index 0000000000..5eb4e22de5 --- /dev/null +++ b/test/generators/php/constrainer/ModelNameConstrainer.spec.ts @@ -0,0 +1,75 @@ +import { + DefaultModelNameConstraints, + defaultModelNameConstraints, + ModelNameConstraints +} from '../../../../src/generators/php/constrainer/ModelNameConstrainer'; + +describe('PHP ModelNameConstrainer', () => { + const PhpDefaultConstraints: ModelNameConstraints = + DefaultModelNameConstraints; + + test('should replace special characters with underscores', () => { + const constrainedName = PhpDefaultConstraints.NO_SPECIAL_CHAR('name%$test'); + expect(constrainedName).toEqual('name_percent_dollar_test'); + }); + + test('should handle number start characters', () => { + const constrainedName = PhpDefaultConstraints.NO_NUMBER_START_CHAR('1Test'); + expect(constrainedName).toEqual('number_1Test'); + }); + + test('should handle empty value by default', () => { + const constrainedName = PhpDefaultConstraints.NO_EMPTY_VALUE(''); + expect(constrainedName).toEqual('empty'); + }); + + test('should convert to PascalCase by default', () => { + const constrainedName = PhpDefaultConstraints.NAMING_FORMATTER('test_name'); + expect(constrainedName).toEqual('TestName'); + }); + + test('should handle reserved PHP keywords', () => { + const constrainedName = + PhpDefaultConstraints.NO_RESERVED_KEYWORDS('return'); + expect(constrainedName).toEqual('reserved_return'); + }); + + describe('Custom PHP constraints', () => { + test('should be able to overwrite all hooks for PHP', () => { + const mockedConstraintCallbacks: Partial = { + NAMING_FORMATTER: jest.fn().mockReturnValue(''), + NO_SPECIAL_CHAR: jest.fn().mockReturnValue(''), + NO_NUMBER_START_CHAR: jest.fn().mockReturnValue(''), + NO_EMPTY_VALUE: jest.fn().mockReturnValue(''), + NO_RESERVED_KEYWORDS: jest.fn().mockReturnValue('') + }; + const constrainFunction = defaultModelNameConstraints( + mockedConstraintCallbacks + ); + constrainFunction({ modelName: '' }); + // Expect all callbacks to be called + for (const jestMockCallback of Object.values(mockedConstraintCallbacks)) { + expect(jestMockCallback).toHaveBeenCalled(); + } + }); + + test('should be able to overwrite one hook for PHP', () => { + // All but NAMING_FORMATTER, as we customize that + const spies = [ + jest.spyOn(DefaultModelNameConstraints, 'NO_SPECIAL_CHAR'), + jest.spyOn(DefaultModelNameConstraints, 'NO_NUMBER_START_CHAR'), + jest.spyOn(DefaultModelNameConstraints, 'NO_EMPTY_VALUE'), + jest.spyOn(DefaultModelNameConstraints, 'NO_RESERVED_KEYWORDS') + ]; + const jestCallback = jest.fn().mockReturnValue(''); + const constrainFunction = defaultModelNameConstraints({ + NAMING_FORMATTER: jestCallback + }); + const constrainedValue = constrainFunction({ modelName: '' }); + expect(constrainedValue).toEqual(''); + for (const jestMockCallback of spies) { + expect(jestMockCallback).toHaveBeenCalled(); + } + }); + }); +}); diff --git a/test/generators/php/constrainer/PropertyKeyConstrainer.spec.ts b/test/generators/php/constrainer/PropertyKeyConstrainer.spec.ts new file mode 100644 index 0000000000..3547b6f40c --- /dev/null +++ b/test/generators/php/constrainer/PropertyKeyConstrainer.spec.ts @@ -0,0 +1,179 @@ +import { PhpDefaultConstraints } from '../../../../src/generators/php/PhpConstrainer'; +import { + ConstrainedObjectModel, + ObjectModel, + ConstrainedObjectPropertyModel, + ObjectPropertyModel +} from '../../../../src'; +import { + defaultPropertyKeyConstraints, + PropertyKeyConstraintOptions +} from '../../../../src/generators/php/constrainer/PropertyKeyConstrainer'; + +describe('PropertyKeyConstrainer for PHP', () => { + const objectModel = new ObjectModel('test', undefined, {}, {}); + const constrainedObjectModel = new ConstrainedObjectModel( + 'test', + undefined, + {}, + '', + {} + ); + + const constrainPropertyName = (propertyName: string) => { + const objectPropertyModel = new ObjectPropertyModel( + propertyName, + false, + objectModel + ); + const constrainedObjectPropertyModel = new ConstrainedObjectPropertyModel( + '', + '', + objectPropertyModel.required, + constrainedObjectModel + ); + return PhpDefaultConstraints.propertyKey({ + constrainedObjectModel, + objectModel, + objectPropertyModel, + constrainedObjectPropertyModel + }); + }; + + afterEach(() => { + jest.restoreAllMocks(); + }); + + test('should never render special chars for PHP', () => { + const constrainedKey = constrainPropertyName('%'); + expect(constrainedKey).toEqual('percent'); + }); + + test('should not render number as start char for PHP', () => { + const constrainedKey = constrainPropertyName('1'); + expect(constrainedKey).toEqual('number_1'); + }); + + test('should never contain empty name for PHP', () => { + const constrainedKey = constrainPropertyName(''); + expect(constrainedKey).toEqual('reservedEmpty'); + }); + + test('should use camelCase naming format for PHP', () => { + const constrainedKey = constrainPropertyName('some weird_value!"#2'); + expect(constrainedKey).toEqual('someWeirdValueExclamationQuotationHash_2'); + }); + + test('should never render reserved keywords for PHP', () => { + const constrainedKey = constrainPropertyName('return'); + expect(constrainedKey).toEqual('reservedReturn'); + }); + + describe('custom constraints for PHP', () => { + test('should be able to overwrite all hooks for PHP', () => { + const mockedConstraintCallbacks: Partial = { + NAMING_FORMATTER: jest.fn().mockReturnValue(''), + NO_SPECIAL_CHAR: jest.fn().mockReturnValue(''), + NO_NUMBER_START_CHAR: jest.fn().mockReturnValue(''), + NO_EMPTY_VALUE: jest.fn().mockReturnValue(''), + NO_RESERVED_KEYWORDS: jest.fn().mockReturnValue('') + }; + const constrainFunction = defaultPropertyKeyConstraints( + mockedConstraintCallbacks + ); + const objectPropertyModel = new ObjectPropertyModel( + '', + false, + objectModel + ); + const constrainedObjectPropertyModel = new ConstrainedObjectPropertyModel( + '', + '', + objectPropertyModel.required, + constrainedObjectModel + ); + constrainFunction({ + constrainedObjectModel, + objectModel, + objectPropertyModel, + constrainedObjectPropertyModel + }); + for (const jestMockCallback of Object.values(mockedConstraintCallbacks)) { + expect(jestMockCallback).toHaveBeenCalled(); + } + }); + test('should be able to overwrite NO_SPECIAL_CHAR hook for PHP', () => { + const mockedConstraintCallbacks: Partial = { + NO_SPECIAL_CHAR: jest.fn().mockImplementation((value: string) => { + return value.replace(/[@#$%^&*]/g, ''); + }), + NAMING_FORMATTER: jest.fn().mockReturnValue(''), + NO_NUMBER_START_CHAR: jest.fn().mockReturnValue(''), + NO_EMPTY_VALUE: jest.fn().mockReturnValue(''), + NO_RESERVED_KEYWORDS: jest.fn().mockReturnValue('') + }; + + const constrainFunction = defaultPropertyKeyConstraints( + mockedConstraintCallbacks + ); + + const objectPropertyModel = new ObjectPropertyModel( + '', + false, + objectModel + ); + const constrainedObjectPropertyModel = new ConstrainedObjectPropertyModel( + '', + '', + objectPropertyModel.required, + constrainedObjectModel + ); + + const result = constrainFunction({ + constrainedObjectModel, + objectModel, + objectPropertyModel, + constrainedObjectPropertyModel + }); + expect(result).toEqual(''); + expect(mockedConstraintCallbacks.NO_SPECIAL_CHAR).toHaveBeenCalled(); + }); + + test('should be able to overwrite NO_EMPTY_VALUE hook for PHP', () => { + const mockedConstraintCallbacks: Partial = { + NO_EMPTY_VALUE: jest.fn().mockImplementation((value: string) => { + return value.trim(); + }), + NAMING_FORMATTER: jest.fn().mockReturnValue(''), + NO_SPECIAL_CHAR: jest.fn().mockReturnValue(''), + NO_NUMBER_START_CHAR: jest.fn().mockReturnValue(''), + NO_RESERVED_KEYWORDS: jest.fn().mockReturnValue('') + }; + + const constrainFunction = defaultPropertyKeyConstraints( + mockedConstraintCallbacks + ); + + const objectPropertyModel = new ObjectPropertyModel( + '', + false, + objectModel + ); + const constrainedObjectPropertyModel = new ConstrainedObjectPropertyModel( + '', + '', + objectPropertyModel.required, + constrainedObjectModel + ); + + const result = constrainFunction({ + constrainedObjectModel, + objectModel, + objectPropertyModel, + constrainedObjectPropertyModel + }); + expect(result).toEqual(''); + expect(mockedConstraintCallbacks.NO_EMPTY_VALUE).toHaveBeenCalled(); + }); + }); +}); From ec745f53e066c05e465c2f87fc61f17357ec9b29 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Fri, 29 Dec 2023 14:46:36 -1000 Subject: [PATCH 4/6] docs: add ankur0904 as a contributor for doc (#1709) * update README.md * update .all-contributorsrc --------- Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ README.md | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 2f19c78ed9..01dbc45b09 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -826,6 +826,15 @@ "contributions": [ "doc" ] + }, + { + "login": "ankur0904", + "name": "Ankur Singh", + "avatar_url": "https://avatars.githubusercontent.com/u/98346896?v=4", + "profile": "https://github.com/ankur0904", + "contributions": [ + "doc" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 093b1a8e19..0b1ee3ba45 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ [![Discussions](https://img.shields.io/github/discussions/asyncapi/modelina)](https://github.com/asyncapi/modelina/discussions) [![Website](https://img.shields.io/website?label=website&url=https%3A%2F%2Fwww.modelina.org)](https://www.modelina.org) [![Playground](https://img.shields.io/website?label=playground&url=https%3A%2F%2Fwww.modelina.org%2Fplayground)](https://www.modelina.org/playground) -[![All Contributors](https://img.shields.io/badge/all_contributors-76-orange.svg?style=flat-square)](#contributors-) +[![All Contributors](https://img.shields.io/badge/all_contributors-77-orange.svg?style=flat-square)](#contributors-) Your one-stop tool for generating accurate and well-tested models for representing the message payloads. Use it as a tool in your development workflow, or a library in a larger integrations, entirely in your control. @@ -420,6 +420,7 @@ Thanks go out to these wonderful people ([emoji key](https://allcontributors.org Mintu Gogoi
    Mintu Gogoi

    ⚠️ Devansh Mahant
    Devansh Mahant

    📖 Asish Kumar
    Asish Kumar

    📖 + Ankur Singh
    Ankur Singh

    📖 From 3df0fe39fc420ff9cfc2c0bf1734286dcc8b41f3 Mon Sep 17 00:00:00 2001 From: Jonas Lagoni Date: Sat, 30 Dec 2023 14:24:31 -1000 Subject: [PATCH 5/6] chore: add artur-ciocanu as scala champion (#1686) --- CODEOWNERS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CODEOWNERS b/CODEOWNERS index ea345570f9..fd26d550f1 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -52,3 +52,6 @@ # Language Champions for PHP and it's presets */generators/php @ferror + +# Language Champions for Scala and it's presets +*/generators/scala @artur-ciocanu \ No newline at end of file From 4d9a55cf9b1c9a1cba39ea6eb039b1dd2c84c9fb Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Sat, 30 Dec 2023 14:25:38 -1000 Subject: [PATCH 6/6] docs: add artur-ciocanu as a contributor for maintenance (#1714) * update README.md * update .all-contributorsrc --------- Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 3 ++- README.md | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 01dbc45b09..589f0b1105 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -344,7 +344,8 @@ "bug", "example", "doc", - "test" + "test", + "maintenance" ] }, { diff --git a/README.md b/README.md index 0b1ee3ba45..31d00001c2 100644 --- a/README.md +++ b/README.md @@ -361,7 +361,7 @@ Thanks go out to these wonderful people ([emoji key](https://allcontributors.org PanMan
    PanMan

    📖 - artur-ciocanu
    artur-ciocanu

    💻 🐛 💡 📖 ⚠️ + artur-ciocanu
    artur-ciocanu

    💻 🐛 💡 📖 ⚠️ 🚧 Cyprian Gracz
    Cyprian Gracz

    💻 ⚠️ 🐛 Leigh Johnson
    Leigh Johnson

    💻 ⚠️ 💡 📖 🚧 👀 Nitin Tejuja
    Nitin Tejuja

    ⚠️ 💡