Skip to main content
January 5, 2023
Question

Bug Report: proper() doesn't capitalize the first letter of words preceded by punctuation.

  • January 5, 2023
  • 3 replies
  • 1 view

My teammate found a bug when using proper() to display a label; a word preceded by a non-alphabetic character will not be converted to proper case.

If the 11th floor is home to the HR department.

  • Floor.id = 11
  • Floor.department.name = "human resources"

We would expect:

Floor 11 (Human Resources)

but instead get:

Floor 11 (human Resources)

To reproduce the issue, I used this expression to check capitalization:

proper(
  "I am reporting that ""proper() coNverts each [alphabetic] cHaRacter into ProPeR caSe " & "(unless a non-alphabetic character precedes it)"""
),

Where I would expect:

I Am Reporting That "Proper() Converts Each [Alphabetic] Character Into Proper Case (Unless A Non-alphabetic Character Precedes It)

It's returning:

I Am Reporting That "proper() Converts Each [alphabetic] Character Into Proper Case (unless A Non-alphabetic Character Precedes It)

Is proper() working as designed?

Side note: 22.4 documentation reads, "Converts each character in the text into proper case, meaning it will capitalize the first first letter of every word and convert the rest into lowercase. (https://docs.appian.com/suite/help/22.4/fnc_text_proper.html")

3 replies

konduruc733182
January 9, 2023

Hello robinf6498,

Can you please show us how you are trying to achieve this?

  • Floor.id = 11
  • Floor.department.name = "human resources"

Floor 11 (Human Resources)

mikes0011
Brainy
January 9, 2023

I'm not sure this is a "bug" so much as a constraint, possibly crossed with a lack of specificity in the documention (re: the snippet you copied).  I suppose the documentation should be rephrased to something more like, "capatialize the first non-whitespace character, where applicable, of every whole word in the string".  I suppose you could argue that the function should specifically exclude non-alphabet characters from its logic, though it seems like that might be expecting too much from a function like this.

csteward
January 9, 2023

I agree that you will get what you get with fn!proper().  However, we can create a more robust rule that removes and replaces certain preceding characters to allow proper() to function more intuitively.  This could be optimized, quick and dirty solution to get you going:

a!localVariables(
  local!data: "I am reporting that ""proper() coNverts each [alphabetic] cHaRacter into ProPeR caSe " & "(unless a non-alphabetic character precedes it)""",
  local!ignore: {"(",")","""","[","]","-"}, /* preceding characters you want to ignore */
  local!removals: a!flatten(
    a!forEach(
      items: 1+enumerate(len(local!data)),
      expression: a!localVariables(
        local!currentChar: charat(local!data,fv!item),
        if(
          contains(local!ignore,local!currentChar),
          {
            index: fv!item,
            char: local!currentChar
          },
          {}
        )
      )
    )
  ),
  local!replaced: if(
    rule!APN_isEmpty(local!removals),
    local!data,
    joinarray(
      a!forEach(
        items: 1+enumerate(len(local!data)),
        expression: if(
          contains(tointeger(local!removals.index),fv!item),
          " ",
          charat(local!data,fv!item)
        )
      )
    )
  ),

  local!proper: proper(local!replaced),

  joinarray(
    a!forEach(
      items: 1+enumerate(len(local!proper)),
      expression: a!localVariables(
        local!replacementIndex: wherecontains(fv!item,tointeger(local!removals.index)),
        if(
          rule!APN_isBlank(local!replacementIndex),
          charat(local!proper,fv!item),
          property(index(local!removals,local!replacementIndex,{}),"char")
        )
      )
    )
  )
)