From f0df98f4e607e5e8253ecb0c397252137a9a22f0 Mon Sep 17 00:00:00 2001 From: dora56 Date: Fri, 22 Dec 2023 16:08:53 +0900 Subject: [PATCH] feat: add rules pluralization --- dict/auto-create-regular-rules.yml | 230 +++++++++++++++++++++++++++++ spec/src/rule/rules.test.ts | 29 ++++ src/rule/rules.ts | 62 ++++++++ test/index-test.ts | 26 ++++ 4 files changed, 347 insertions(+) diff --git a/dict/auto-create-regular-rules.yml b/dict/auto-create-regular-rules.yml index 7f8578b..848c440 100644 --- a/dict/auto-create-regular-rules.yml +++ b/dict/auto-create-regular-rules.yml @@ -156,6 +156,11 @@ rules: - AIServices options: wordBoundary: true + - expected: AI Services + patterns: + - AI Service + options: + wordBoundary: true - expected: AI Speech Services options: wordBoundary: true @@ -169,6 +174,11 @@ rules: - AISpeechServices options: wordBoundary: true + - expected: AI Speech Services + patterns: + - AI Speech Service + options: + wordBoundary: true - expected: AI Studio options: wordBoundary: true @@ -234,6 +244,11 @@ rules: - ActiveDirectoryDomainServices options: wordBoundary: true + - expected: Active Directory Domain Services + patterns: + - Active Directory Domain Service + options: + wordBoundary: true - expected: Active Directory External Identities options: wordBoundary: true @@ -247,6 +262,11 @@ rules: - ActiveDirectoryExternalIdentities options: wordBoundary: true + - expected: Active Directory External Identities + patterns: + - Active Directory External Identity + options: + wordBoundary: true - expected: Advisor options: wordBoundary: true @@ -268,6 +288,11 @@ rules: - AnalysisServices options: wordBoundary: true + - expected: Analysis Services + patterns: + - Analysis Service + options: + wordBoundary: true - expected: App Configuration options: wordBoundary: true @@ -415,6 +440,11 @@ rules: - Microsoft Blueprints options: wordBoundary: true + - expected: Azure Blueprints + patterns: + - Azure Blueprint + options: + wordBoundary: true - expected: Boards options: wordBoundary: true @@ -423,6 +453,11 @@ rules: - Microsoft Boards options: wordBoundary: true + - expected: Azure Boards + patterns: + - Azure Board + options: + wordBoundary: true - expected: CDN options: wordBoundary: true @@ -483,6 +518,11 @@ rules: - CommunicationServices options: wordBoundary: true + - expected: Communication Services + patterns: + - Communication Service + options: + wordBoundary: true - expected: Communications Gateway options: wordBoundary: true @@ -509,6 +549,11 @@ rules: - ContainerApps options: wordBoundary: true + - expected: Container Apps + patterns: + - Container App + options: + wordBoundary: true - expected: Container Instances options: wordBoundary: true @@ -522,6 +567,11 @@ rules: - ContainerInstances options: wordBoundary: true + - expected: Container Instances + patterns: + - Container Instance + options: + wordBoundary: true - expected: Container Registry options: wordBoundary: true @@ -786,6 +836,11 @@ rules: - DeploymentEnvironments options: wordBoundary: true + - expected: Deployment Environments + patterns: + - Deployment Environment + options: + wordBoundary: true - expected: DevOps options: wordBoundary: true @@ -815,6 +870,11 @@ rules: - Dev Test Labs options: wordBoundary: true + - expected: DevTest Labs + patterns: + - DevTest Lab + options: + wordBoundary: true - expected: Digital Twins options: wordBoundary: true @@ -828,6 +888,11 @@ rules: - DigitalTwins options: wordBoundary: true + - expected: Digital Twins + patterns: + - Digital Twin + options: + wordBoundary: true - expected: Disk Storage options: wordBoundary: true @@ -867,6 +932,11 @@ rules: - EventHubs options: wordBoundary: true + - expected: Event Hubs + patterns: + - Event Hub + options: + wordBoundary: true - expected: ExpressRoute options: wordBoundary: true @@ -889,6 +959,11 @@ rules: - Microsoft Files options: wordBoundary: true + - expected: Azure Files + patterns: + - Azure File + options: + wordBoundary: true - expected: Firewall options: wordBoundary: true @@ -944,6 +1019,11 @@ rules: - Microsoft Functions options: wordBoundary: true + - expected: Azure Functions + patterns: + - Azure Function + options: + wordBoundary: true - expected: HDInsight options: wordBoundary: true @@ -991,6 +1071,11 @@ rules: - HealthDataServices options: wordBoundary: true + - expected: Health Data Services + patterns: + - Health Data Service + options: + wordBoundary: true - expected: Information Protection options: wordBoundary: true @@ -1069,6 +1154,11 @@ rules: - IoTOperations options: wordBoundary: true + - expected: IoT Operations + patterns: + - IoT Operation + options: + wordBoundary: true - expected: Key Vault options: wordBoundary: true @@ -1121,6 +1211,11 @@ rules: - KubernetesServiceEdgeEssentials options: wordBoundary: true + - expected: Kubernetes Service Edge Essentials + patterns: + - Kubernetes Service Edge Essential + options: + wordBoundary: true - expected: Lab Services options: wordBoundary: true @@ -1134,6 +1229,11 @@ rules: - LabServices options: wordBoundary: true + - expected: Lab Services + patterns: + - Lab Service + options: + wordBoundary: true - expected: Lighthouse options: wordBoundary: true @@ -1181,6 +1281,11 @@ rules: - LogicApps options: wordBoundary: true + - expected: Logic Apps + patterns: + - Logic App + options: + wordBoundary: true - expected: Machine Learning options: wordBoundary: true @@ -1207,6 +1312,11 @@ rules: - ManagedApplications options: wordBoundary: true + - expected: Managed Applications + patterns: + - Managed Application + options: + wordBoundary: true - expected: Managed Confidential Consortium Framework options: wordBoundary: true @@ -1285,6 +1395,11 @@ rules: - MediaServices options: wordBoundary: true + - expected: Media Services + patterns: + - Media Service + options: + wordBoundary: true - expected: Migrate options: wordBoundary: true @@ -1342,6 +1457,11 @@ rules: - Net App Files options: wordBoundary: true + - expected: NetApp Files + patterns: + - NetApp File + options: + wordBoundary: true - expected: Network Function Manager options: wordBoundary: true @@ -1381,6 +1501,11 @@ rules: - NotificationHubs options: wordBoundary: true + - expected: Notification Hubs + patterns: + - Notification Hub + options: + wordBoundary: true - expected: Object Anchors options: wordBoundary: true @@ -1394,6 +1519,11 @@ rules: - ObjectAnchors options: wordBoundary: true + - expected: Object Anchors + patterns: + - Object Anchor + options: + wordBoundary: true - expected: Open Datasets options: wordBoundary: true @@ -1407,6 +1537,11 @@ rules: - OpenDatasets options: wordBoundary: true + - expected: Open Datasets + patterns: + - Open Dataset + options: + wordBoundary: true - expected: OpenAI Service options: wordBoundary: true @@ -1433,6 +1568,11 @@ rules: - OperatorInsights options: wordBoundary: true + - expected: Operator Insights + patterns: + - Operator Insight + options: + wordBoundary: true - expected: Operator Nexus options: wordBoundary: true @@ -1579,6 +1719,11 @@ rules: - Microsoft Repos options: wordBoundary: true + - expected: Azure Repos + patterns: + - Azure Repo + options: + wordBoundary: true - expected: Resource Manager options: wordBoundary: true @@ -1756,6 +1901,11 @@ rules: - SpatialAnchors options: wordBoundary: true + - expected: Spatial Anchors + patterns: + - Spatial Anchor + options: + wordBoundary: true - expected: Sphere options: wordBoundary: true @@ -1777,6 +1927,11 @@ rules: - SpotVirtualMachines options: wordBoundary: true + - expected: Spot Virtual Machines + patterns: + - Spot Virtual Machine + options: + wordBoundary: true - expected: Spring Apps options: wordBoundary: true @@ -1790,6 +1945,11 @@ rules: - SpringApps options: wordBoundary: true + - expected: Spring Apps + patterns: + - Spring App + options: + wordBoundary: true - expected: Stack options: wordBoundary: true @@ -1902,6 +2062,11 @@ rules: - TestPlans options: wordBoundary: true + - expected: Test Plans + patterns: + - Test Plan + options: + wordBoundary: true - expected: Time Series Insights options: wordBoundary: true @@ -1915,6 +2080,11 @@ rules: - TimeSeriesInsights options: wordBoundary: true + - expected: Time Series Insights + patterns: + - Time Series Insight + options: + wordBoundary: true - expected: Traffic Manager options: wordBoundary: true @@ -2060,6 +2230,11 @@ rules: - CloudServices options: wordBoundary: true + - expected: Cloud Services + patterns: + - Cloud Service + options: + wordBoundary: true - expected: Data Science Virtual Machines options: wordBoundary: true @@ -2073,6 +2248,11 @@ rules: - DataScienceVirtualMachines options: wordBoundary: true + - expected: Data Science Virtual Machines + patterns: + - Data Science Virtual Machine + options: + wordBoundary: true - expected: Defender External Attack Surface Management options: wordBoundary: true @@ -2101,6 +2281,11 @@ rules: - Dev Ops tool integrations options: wordBoundary: true + - expected: DevOps tool integrations + patterns: + - DevOps tool integration + options: + wordBoundary: true - expected: Event Grid options: wordBoundary: true @@ -2259,6 +2444,11 @@ rules: - EnergyDataServices options: wordBoundary: true + - expected: Energy Data Services + patterns: + - Energy Data Service + options: + wordBoundary: true - expected: Entra Domain Services options: wordBoundary: true @@ -2272,6 +2462,11 @@ rules: - EntraDomainServices options: wordBoundary: true + - expected: Entra Domain Services + patterns: + - Entra Domain Service + options: + wordBoundary: true - expected: Fabric options: wordBoundary: true @@ -2369,6 +2564,11 @@ rules: - SQLServeronAzureVirtualMachines options: wordBoundary: true + - expected: SQL Server on Azure Virtual Machines + patterns: + - SQL Server on Azure Virtual Machine + options: + wordBoundary: true - expected: Static Web Apps options: wordBoundary: true @@ -2382,6 +2582,11 @@ rules: - StaticWebApps options: wordBoundary: true + - expected: Static Web Apps + patterns: + - Static Web App + options: + wordBoundary: true - expected: Virtual Machine Scale Sets options: wordBoundary: true @@ -2395,6 +2600,11 @@ rules: - VirtualMachineScaleSets options: wordBoundary: true + - expected: Virtual Machine Scale Sets + patterns: + - Virtual Machine Scale Set + options: + wordBoundary: true - expected: Virtual Machines options: wordBoundary: true @@ -2408,6 +2618,11 @@ rules: - VirtualMachines options: wordBoundary: true + - expected: Virtual Machines + patterns: + - Virtual Machine + options: + wordBoundary: true - expected: Virtual WAN options: wordBoundary: true @@ -2473,6 +2688,11 @@ rules: - WebAppforContainers options: wordBoundary: true + - expected: Web App for Containers + patterns: + - Web App for Container + options: + wordBoundary: true - expected: Web Application Firewall options: wordBoundary: true @@ -2499,6 +2719,11 @@ rules: - Windows10IoTCoreServices options: wordBoundary: true + - expected: Windows 10 IoT Core Services + patterns: + - Windows 10 IoT Core Service + options: + wordBoundary: true - expected: Windows Virtual Machines options: wordBoundary: true @@ -2512,6 +2737,11 @@ rules: - WindowsVirtualMachines options: wordBoundary: true + - expected: Windows Virtual Machines + patterns: + - Windows Virtual Machine + options: + wordBoundary: true - expected: Windows for IoT options: wordBoundary: true diff --git a/spec/src/rule/rules.test.ts b/spec/src/rule/rules.test.ts index ec36532..9491aec 100644 --- a/spec/src/rule/rules.test.ts +++ b/spec/src/rule/rules.test.ts @@ -21,6 +21,10 @@ describe('rules', () => { name: 'DevOps', prefix: 'Azure', }; + const product5: AzureProductParams = { + name: 'Container Apps', + prefix: 'Azure', + }; it('createAzureProductRules', () => { const products: AzureProductParams[] = [ @@ -28,6 +32,7 @@ describe('rules', () => { product2, product3, product4, + product5 ]; const result = createAzureProductRules(products); expect(result).toEqual([ @@ -37,6 +42,11 @@ describe('rules', () => { patterns: ['Microsoft Functions'], options: { wordBoundary: true }, }, + { + expected: 'Azure Functions', + patterns: ['Azure Function'], + options: { wordBoundary: true }, + }, { expected: 'Dev Box', options: { wordBoundary: true }, @@ -79,6 +89,25 @@ describe('rules', () => { patterns: ['Devops', 'Dev Ops'], options: { wordBoundary: true }, }, + { + expected: 'Container Apps', + options: { wordBoundary: true }, + }, + { + expected: 'Azure Container Apps', + patterns: ['Microsoft Container Apps'], + options: { wordBoundary: true }, + }, + { + expected: 'Container Apps', + patterns: ['ContainerApps'], + options: { wordBoundary: true }, + }, + { + expected: 'Container Apps', + patterns: ['Container App'], + options: { wordBoundary: true }, + }, ]); }); }); diff --git a/src/rule/rules.ts b/src/rule/rules.ts index 0ad0c90..8a330c9 100644 --- a/src/rule/rules.ts +++ b/src/rule/rules.ts @@ -35,6 +35,10 @@ export function createAzureProductRules(product: AzureProductParams[]): Rules { if (maybeSpacingRule !== undefined) { rules.push(maybeSpacingRule); } + const singularToPluralRule = createSingularToPluralRule(product); + if (singularToPluralRule !== undefined) { + rules.push(singularToPluralRule); + } }); return rules; } @@ -108,3 +112,61 @@ function modifiedPascalCasePattern(name: string): string { .map((char: string, index: number) => index !== 0 && char === char.toUpperCase() ? char.toLowerCase() : char) .join(''); } + +type PluralAndSingular = Record; + +const patternsPluralAndSingularDict: PluralAndSingular = { + "Functions": "Function", + "Apps": "App", + "Containers": "Container", + "Identities": "Identity", + "Services": "Service", + "Blueprints": "Blueprint", + "Boards": "Board", + "Instances": "Instance", + "Environments": "Environment", + "Labs": "Lab", + "Twins": "Twin", + "Hubs": "Hub", + "Operations": "Operation", + "Essentials": "Essential", + "Applications": "Application", + "Files": "File", + "Anchors": "Anchor", + "Datasets": "Dataset", + "Insights": "Insight", + "Repos": "Repo", + "Machines": "Machine", + "Plans": "Plan", + "integrations": "integration", + "Sets": "Set", +}; + +function createSingularToPluralRule(product: AzureProductParams): RuleParam | undefined { + const patterns: string[] = []; + + const name = product.name; + const lastWord = name.split(" ").pop(); + + const fullName = getFullProductName(product); + const count = fullName.split(" ").length; + const expected = count > 2 ? name : fullName; + + if (lastWord === undefined) return undefined; + + const singular = patternsPluralAndSingularDict[lastWord]; + + if (singular !== undefined) { + const pattern = expected.replace(lastWord, singular); + patterns.push(pattern); + } + + if (patterns.length === 0) return undefined; + const rule: RuleParam = { + expected, + patterns: patterns.map((pattern) => escapePattern(pattern)), + options: { wordBoundary: true }, + }; + + return rule; +} diff --git a/test/index-test.ts b/test/index-test.ts index 338dac7..1094557 100644 --- a/test/index-test.ts +++ b/test/index-test.ts @@ -28,6 +28,32 @@ tester.run('AI Studio', report, { tester.run('Container Apps', report, { valid: ['Container Apps', 'Azure Container Apps'], + invalid: [ + { + text: 'Microsoft Container Apps', + errors: [ + { + message: 'Microsoft Container Apps => Azure Container Apps', + }, + ], + }, + { + text: 'ContainerApps', + errors: [ + { + message: 'ContainerApps => Container Apps', + }, + ], + }, + { + text: 'Container App', + errors: [ + { + message: 'Container App => Container Apps', + }, + ], + }, + ], }); tester.run('DevOps', report, {