protected virtual string CleanString(string text, CleanStringType stringType, string?culture, char?separator)
        {
            // be safe
            if (text == null)
            {
                throw new ArgumentNullException(nameof(text));
            }

            culture = culture ?? string.Empty;

            // get config
            DefaultShortStringHelperConfig.Config config = _config.For(stringType, culture);
            stringType = config.StringTypeExtend(stringType);

            // apply defaults
            if ((stringType & CleanStringType.CaseMask) == CleanStringType.None)
            {
                stringType |= CleanStringType.CamelCase;
            }

            if ((stringType & CleanStringType.CodeMask) == CleanStringType.None)
            {
                stringType |= CleanStringType.Ascii;
            }

            // use configured unless specified
            separator = separator ?? config.Separator;

            // apply pre-filter
            if (config.PreFilter != null)
            {
                text = config.PreFilter(text);
            }

            // apply replacements
            //if (config.Replacements != null)
            //    text = ReplaceMany(text, config.Replacements);

            // recode
            CleanStringType codeType = stringType & CleanStringType.CodeMask;

            switch (codeType)
            {
            case CleanStringType.Ascii:
                text = Utf8ToAsciiConverter.ToAsciiString(text);
                break;

            case CleanStringType.TryAscii:
                const char ESC   = (char)27;
                var        ctext = Utf8ToAsciiConverter.ToAsciiString(text, ESC);
                if (ctext.Contains(ESC) == false)
                {
                    text = ctext;
                }

                break;

            default:
                text = RemoveSurrogatePairs(text);
                break;
            }

            // clean
            text = CleanCodeString(text, stringType, separator.Value, culture, config);

            // apply post-filter
            if (config.PostFilter != null)
            {
                text = config.PostFilter(text);
            }

            return(text);
        }