diff --git a/npm/ng-packs/packages/schematics/src/models/method.ts b/npm/ng-packs/packages/schematics/src/models/method.ts index 036392e0a1..c2833a7bfd 100644 --- a/npm/ng-packs/packages/schematics/src/models/method.ts +++ b/npm/ng-packs/packages/schematics/src/models/method.ts @@ -1,5 +1,5 @@ -import { strings } from '@angular-devkit/core'; import { eBindingSourceId, eMethodModifier } from '../enums'; +import { camel } from '../utils'; import { ParameterInBody } from './api-definition'; import { Property } from './model'; import { Omissible } from './util'; @@ -42,7 +42,7 @@ export class Body { registerActionParameter = (param: ParameterInBody) => { const { bindingSourceId, descriptorName, name, nameOnMethod } = param; - const camelName = strings.camelize(name); + const camelName = camel(name); const value = descriptorName ? `${descriptorName}.${camelName}` : nameOnMethod; switch (bindingSourceId) { diff --git a/npm/ng-packs/packages/schematics/src/utils/model.ts b/npm/ng-packs/packages/schematics/src/utils/model.ts index 0e472e64d3..f68aa9b181 100644 --- a/npm/ng-packs/packages/schematics/src/utils/model.ts +++ b/npm/ng-packs/packages/schematics/src/utils/model.ts @@ -1,8 +1,8 @@ -import { strings } from '@angular-devkit/core'; import { VOLO_NAME_VALUE, VOLO_REGEX } from '../constants'; import { Interface, Model, Property, Type, TypeWithEnum } from '../models'; import { parseNamespace } from './namespace'; import { relativePathToModel } from './path'; +import { camel } from './text'; import { parseGenerics } from './tree'; import { createTypeParser, @@ -118,7 +118,7 @@ export function createImportRefToInterfaceReducerCreator(params: ModelGeneratorP const _interface = new Interface({ identifier, base, namespace, ref }); typeDef.properties?.forEach(prop => { - const name = strings.camelize(prop.name); + const name = camel(prop.name); const optional = prop.typeSimple.endsWith('?') ? '?' : ''; const type = simplifyType(prop.typeSimple); const refs = parseType(prop.type).reduce( diff --git a/npm/ng-packs/packages/schematics/src/utils/text.ts b/npm/ng-packs/packages/schematics/src/utils/text.ts index a3c177c1a4..379ea78601 100644 --- a/npm/ng-packs/packages/schematics/src/utils/text.ts +++ b/npm/ng-packs/packages/schematics/src/utils/text.ts @@ -2,7 +2,7 @@ import { strings } from '@angular-devkit/core'; export const lower = (text: string) => text.toLowerCase(); export const upper = (text: string) => text.toUpperCase(); -export const camel = (text: string) => strings.camelize(_(text)); +export const camel = (text: string) => toCamelCase(_(text)); export const pascal = (text: string) => strings.classify(_(text)); export const kebab = (text: string) => strings.dasherize(_(text)); export const snake = (text: string) => strings.underscore(_(text)); @@ -13,3 +13,41 @@ export const dir = (text: string) => function _(text: string): string { return text.replace(/\./g, '_'); } + +// https://github.com/JamesNK/Newtonsoft.Json/blob/master/Src/Newtonsoft.Json/Utilities/StringUtils.cs#L155 +function toCamelCase(str: string) { + if (!str || !isUpperCase(str[0])) return str; + + const chars = str.split(''); + const { length } = chars; + + for (let i = 0; i < length; i++) { + if (i === 1 && !isUpperCase(chars[i])) break; + + const hasNext = i + 1 < length; + + if (i > 0 && hasNext && !isUpperCase(chars[i + 1])) { + if (isSeparator(chars[i + 1])) { + chars[i] = toLowerCase(chars[i]); + } + + break; + } + + chars[i] = toLowerCase(chars[i]); + } + + return chars.join(''); +} + +function isSeparator(str = '') { + return /[\s\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,\-.\/:;<=>?@\[\]^_`{|}~]+/.test(str); +} + +function isUpperCase(str = '') { + return /[A-Z]+/.test(str); +} + +function toLowerCase(str = '') { + return str.toLowerCase(); +}