首页 文章

Stack Overflow如何生成其SEO友好的URL?

提问于
浏览
240

什么是好的完整regular expression或其他一些可以获得 Headers 的流程:

如何将 Headers 更改为Stack Overflow等URL的一部分?

把它变成

how-do-you-change-a-title-to-be-part-of-the-url-like-stack-overflow

Stack Overflow上的SEO友好URL中使用了哪些?

我正在使用的开发环境是Ruby on Rails,但如果还有其他一些特定于平台的解决方案(.NET,PHP,Django),我也很乐意看到它们 .

我相信我(或其他读者)会在不同的平台上遇到同样的问题 .

我正在使用自定义路由,我主要想知道如何更改字符串以删除所有特殊字符,它全部小写,并且所有空格都被替换 .

20 回答

  • 281

    这是我们如何做到的 . 请注意,乍看之下可能存在比边缘条件更多的边缘条件 .

    这是第二个版本,展开了5倍以上的性能(是的,我对它进行了基准测试) . 我想我会优化它,因为这个函数每页可以被调用数百次 .

    /// <summary>
    /// Produces optional, URL-friendly version of a title, "like-this-one". 
    /// hand-tuned for speed, reflects performance refactoring contributed
    /// by John Gietzen (user otac0n) 
    /// </summary>
    public static string URLFriendly(string title)
    {
        if (title == null) return "";
    
        const int maxlen = 80;
        int len = title.Length;
        bool prevdash = false;
        var sb = new StringBuilder(len);
        char c;
    
        for (int i = 0; i < len; i++)
        {
            c = title[i];
            if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'))
            {
                sb.Append(c);
                prevdash = false;
            }
            else if (c >= 'A' && c <= 'Z')
            {
                // tricky way to convert to lowercase
                sb.Append((char)(c | 32));
                prevdash = false;
            }
            else if (c == ' ' || c == ',' || c == '.' || c == '/' || 
                c == '\\' || c == '-' || c == '_' || c == '=')
            {
                if (!prevdash && sb.Length > 0)
                {
                    sb.Append('-');
                    prevdash = true;
                }
            }
            else if ((int)c >= 128)
            {
                int prevlen = sb.Length;
                sb.Append(RemapInternationalCharToAscii(c));
                if (prevlen != sb.Length) prevdash = false;
            }
            if (i == maxlen) break;
        }
    
        if (prevdash)
            return sb.ToString().Substring(0, sb.Length - 1);
        else
            return sb.ToString();
    }
    

    要查看此代码的先前版本(已在功能上等效,并且速度提高了5倍),请查看此帖子的修订历史记录(单击日期链接) .

    此外, RemapInternationalCharToAscii 方法源代码可以找到here .

  • 30

    这是我的杰夫代码版本 . 我做了以下更改:

    • 连字符的附加方式可以添加一个,然后需要删除,因为它是字符串中的最后一个字符 . 也就是说,我们从不想要“my-slug-” . 这意味着额外的字符串分配将在此边缘情况下删除它 . 我通过推迟延迟来解决这个问题 . 如果你将我的代码与Jeff的代码进行比较,那么这个逻辑很容易理解 .

    • 他的方法纯粹基于查找,错过了我在研究Stack Overflow时在实例中发现的很多字符 . 为了解决这个问题,我首先执行规范化传递(元堆栈溢出问题Non US-ASCII characters dropped from full (profile) URL中提到的AKA整理),然后忽略可接受范围之外的任何字符 . 这大部分时间都有效......

    • ...如果没有,我还必须添加查找表 . 如上所述,某些字符在规范化时不会映射到低ASCII值 . 而不是删除这些,我有一个手册的异常列表,无疑是充满漏洞,但它总比没有好 . 标准化代码的灵感来自于Jon Hanna在Stack Overflow问题How can I remove accents on a string?中的精彩帖子 .

    • 案例转换现在也是可选的 .

    public static class Slug
    {
        public static string Create(bool toLower, params string[] values)
        {
            return Create(toLower, String.Join("-", values));
        }
    
        /// <summary>
        /// Creates a slug.
        /// References:
        /// http://www.unicode.org/reports/tr15/tr15-34.html
        /// https://meta.stackexchange.com/questions/7435/non-us-ascii-characters-dropped-from-full-profile-url/7696#7696
        /// https://stackoverflow.com/questions/25259/how-do-you-include-a-webpage-title-as-part-of-a-webpage-url/25486#25486
        /// https://stackoverflow.com/questions/3769457/how-can-i-remove-accents-on-a-string
        /// </summary>
        /// <param name="toLower"></param>
        /// <param name="normalised"></param>
        /// <returns></returns>
        public static string Create(bool toLower, string value)
        {
            if (value == null)
                return "";
    
            var normalised = value.Normalize(NormalizationForm.FormKD);
    
            const int maxlen = 80;
            int len = normalised.Length;
            bool prevDash = false;
            var sb = new StringBuilder(len);
            char c;
    
            for (int i = 0; i < len; i++)
            {
                c = normalised[i];
                if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'))
                {
                    if (prevDash)
                    {
                        sb.Append('-');
                        prevDash = false;
                    }
                    sb.Append(c);
                }
                else if (c >= 'A' && c <= 'Z')
                {
                    if (prevDash)
                    {
                        sb.Append('-');
                        prevDash = false;
                    }
                    // Tricky way to convert to lowercase
                    if (toLower)
                        sb.Append((char)(c | 32));
                    else
                        sb.Append(c);
                }
                else if (c == ' ' || c == ',' || c == '.' || c == '/' || c == '\\' || c == '-' || c == '_' || c == '=')
                {
                    if (!prevDash && sb.Length > 0)
                    {
                        prevDash = true;
                    }
                }
                else
                {
                    string swap = ConvertEdgeCases(c, toLower);
    
                    if (swap != null)
                    {
                        if (prevDash)
                        {
                            sb.Append('-');
                            prevDash = false;
                        }
                        sb.Append(swap);
                    }
                }
    
                if (sb.Length == maxlen)
                    break;
            }
            return sb.ToString();
        }
    
        static string ConvertEdgeCases(char c, bool toLower)
        {
            string swap = null;
            switch (c)
            {
                case 'ı':
                    swap = "i";
                    break;
                case 'ł':
                    swap = "l";
                    break;
                case 'Ł':
                    swap = toLower ? "l" : "L";
                    break;
                case 'đ':
                    swap = "d";
                    break;
                case 'ß':
                    swap = "ss";
                    break;
                case 'ø':
                    swap = "o";
                    break;
                case 'Þ':
                    swap = "th";
                    break;
            }
            return swap;
        }
    }
    

    有关详细信息,单元测试,以及为什么FacebookURL方案比Stack Overflows更聪明,我有一个expanded version of this on my blog .

  • 2

    您将需要设置自定义路由以将URL指向将处理它的控制器 . 由于您使用的是Ruby on Rails,因此使用其路由引擎时introduction .

    在Ruby中,您将需要一个您已经知道的正则表达式,这里是要使用的正则表达式:

    def permalink_for(str)
        str.gsub(/[^\w\/]|[!\(\)\.]+/, ' ').strip.downcase.gsub(/\ +/, '-')
    end
    
  • 5

    你也可以使用这个JavaScript函数来生成slug的形式(这个是基于/复制自Django):

    function makeSlug(urlString, filter) {
        // Changes, e.g., "Petty theft" to "petty_theft".
        // Remove all these words from the string before URLifying
    
        if(filter) {
            removelist = ["a", "an", "as", "at", "before", "but", "by", "for", "from",
            "is", "in", "into", "like", "of", "off", "on", "onto", "per",
            "since", "than", "the", "this", "that", "to", "up", "via", "het", "de", "een", "en",
            "with"];
        }
        else {
            removelist = [];
        }
        s = urlString;
        r = new RegExp('\\b(' + removelist.join('|') + ')\\b', 'gi');
        s = s.replace(r, '');
        s = s.replace(/[^-\w\s]/g, ''); // Remove unneeded characters
        s = s.replace(/^\s+|\s+$/g, ''); // Trim leading/trailing spaces
        s = s.replace(/[-\s]+/g, '-'); // Convert spaces to hyphens
        s = s.toLowerCase(); // Convert to lowercase
        return s; // Trim to first num_chars characters
    }
    
  • 3

    为了更好的衡量,这里是WordPress中的PHP函数,它做到了......我认为WordPress是使用花哨链接的更受欢迎的平台之一 .

    function sanitize_title_with_dashes($title) {
                $title = strip_tags($title);
                // Preserve escaped octets.
                $title = preg_replace('|%([a-fA-F0-9][a-fA-F0-9])|', '---$1---', $title);
                // Remove percent signs that are not part of an octet.
                $title = str_replace('%', '', $title);
                // Restore octets.
                $title = preg_replace('|---([a-fA-F0-9][a-fA-F0-9])---|', '%$1', $title);
                $title = remove_accents($title);
                if (seems_utf8($title)) {
                        if (function_exists('mb_strtolower')) {
                                $title = mb_strtolower($title, 'UTF-8');
                        }
                        $title = utf8_uri_encode($title, 200);
                }
                $title = strtolower($title);
                $title = preg_replace('/&.+?;/', '', $title); // kill entities
                $title = preg_replace('/[^%a-z0-9 _-]/', '', $title);
                $title = preg_replace('/\s+/', '-', $title);
                $title = preg_replace('|-+|', '-', $title);
                $title = trim($title, '-');
                return $title;
        }
    

    这个函数以及一些支持函数可以在wp-includes / formatting.php中找到 .

  • 4

    如果您正在使用Rails边缘,您可以依赖Inflector.parametrize - 这是文档中的示例:

    class Person
        def to_param
          "#{id}-#{name.parameterize}"
        end
      end
    
      @person = Person.find(1)
      # => #<Person id: 1, name: "Donald E. Knuth">
    
      <%= link_to(@person.name, person_path(@person)) %>
      # => <a href="/person/1-donald-e-knuth">Donald E. Knuth</a>
    

    此外,如果您需要在以前版本的Rails中处理更多异国情调的角色,例如口音(éphémère),您可以使用PermalinkFuDiacriticsFu的混合:

    DiacriticsFu::escape("éphémère")
    => "ephemere"
    
    DiacriticsFu::escape("räksmörgås")
    => "raksmorgas"
    
  • 2

    我不熟悉Ruby on Rails,但以下是(未经测试的)PHP代码 . 如果你觉得它很有用,你可以很快地将它翻译成Ruby on Rails .

    $sURL = "This is a title to convert to URL-format. It has 1 number in it!";
    // To lower-case
    $sURL = strtolower($sURL);
    
    // Replace all non-word characters with spaces
    $sURL = preg_replace("/\W+/", " ", $sURL);
    
    // Remove trailing spaces (so we won't end with a separator)
    $sURL = trim($sURL);
    
    // Replace spaces with separators (hyphens)
    $sURL = str_replace(" ", "-", $sURL);
    
    echo $sURL;
    // outputs: this-is-a-title-to-convert-to-url-format-it-has-1-number-in-it
    

    我希望这有帮助 .

  • 5

    我对Ruby或Rails不太了解,但在Perl中,这就是我要做的:

    my $title = "How do you change a title to be part of the url like Stackoverflow?";
    
    my $url = lc $title;   # Change to lower case and copy to URL.
    $url =~ s/^\s+//g;     # Remove leading spaces.
    $url =~ s/\s+$//g;     # Remove trailing spaces.
    $url =~ s/\s+/\-/g;    # Change one or more spaces to single hyphen.
    $url =~ s/[^\w\-]//g;  # Remove any non-word characters.
    
    print "$title\n$url\n";
    

    我只是做了一个快速测试,它似乎工作 . 希望这相对容易转换为Ruby .

  • 0

    T-SQL实现,改编自dbo.UrlEncode

    CREATE FUNCTION dbo.Slug(@string varchar(1024))
    RETURNS varchar(3072)
    AS
    BEGIN
        DECLARE @count int, @c char(1), @i int, @slug varchar(3072)
    
        SET @string = replace(lower(ltrim(rtrim(@string))),' ','-')
    
        SET @count = Len(@string)
        SET @i = 1
        SET @slug = ''
    
        WHILE (@i <= @count)
        BEGIN
            SET @c = substring(@string, @i, 1)
    
            IF @c LIKE '[a-z0-9--]'
                SET @slug = @slug + @c
    
            SET @i = @i +1
        END
    
        RETURN @slug
    END
    
  • 8

    假设您的模型类具有title属性,您可以简单地覆盖模型中的to_param方法,如下所示:

    def to_param
      title.downcase.gsub(/ /, '-')
    end
    

    This Railscast episode有所有细节 . 您还可以使用以下命令确保 Headers 仅包含有效字符:

    validates_format_of :title, :with => /^[a-z0-9-]+$/,
                        :message => 'can only contain letters, numbers and hyphens'
    
  • 1

    一世知道这是一个非常古老的问题但是因为现在大多数浏览器都在 support unicode urls 找到了一个很好的解决方案,它可以转换除字母以外的所有内容(在所有语言中都转换为'-') .

    这可以用几种编程语言完成 .

    该模式是 \\p{^L}+ 然后您只需要使用它将所有非字母替换为'-' .

    node.js中带有xregex模块的工作示例 .

    var text = 'This ! can @ have # several $ letters % from different languages such as עברית or Español';
    
    var slugRegEx = XRegExp('((?!\\d)\\p{^L})+', 'g');
    
    var slug = XRegExp.replace(text, slugRegEx, '-').toLowerCase();
    
    console.log(slug) ==> "this-can-have-several-letters-from-different-languages-such-as-עברית-or-español"
    
  • 3

    Brian的代码,在Ruby中:

    title.downcase.strip.gsub(/\ /, '-').gsub(/[^\w\-]/, '')
    

    downcase 将字符串转换为小写, strip 删除前导和尾随空格,第一个 gsub 调用全局用空格替换空格,第二个删除不是字母或短划线的所有内容 .

  • 16

    有一个名为PermalinkFu的小型Ruby on Rails插件,可以做到这一点 . escape method转换为适合URL的字符串 . 看看代码;那个方法很简单 .

    要删除非ASCII字符,它使用iconv lib从'utf-8'转换为'ascii//ignore//translit' . 然后空间变成破折号,一切都是羽绒状的,等等 .

  • 11

    您可以使用以下帮助程序方法 . 它可以转换Unicode字符 .

    public static string ConvertTextToSlug(string s)
    {
        StringBuilder sb = new StringBuilder();
    
        bool wasHyphen = true;
    
        foreach (char c in s)
        {
            if (char.IsLetterOrDigit(c))
            {
                sb.Append(char.ToLower(c));
                wasHyphen = false;
            }
            else
                if (char.IsWhiteSpace(c) && !wasHyphen)
                {
                    sb.Append('-');
                    wasHyphen = true;
                }
        }
    
        // Avoid trailing hyphens
        if (wasHyphen && sb.Length > 0)
            sb.Length--;
    
        return sb.ToString().Replace("--","-");
    }
    
  • 2

    这是我的(较慢但很有趣的)版本的Jeff代码:

    public static string URLFriendly(string title)
    {
        char? prevRead = null,
            prevWritten = null;
    
        var seq = 
            from c in title
            let norm = RemapInternationalCharToAscii(char.ToLowerInvariant(c).ToString())[0]
            let keep = char.IsLetterOrDigit(norm)
            where prevRead.HasValue || keep
            let replaced = keep ? norm
                :  prevWritten != '-' ? '-'
                :  (char?)null
            where replaced != null
            let s = replaced + (prevRead == null ? ""
                : norm == '#' && "cf".Contains(prevRead.Value) ? "sharp"
                : norm == '+' ? "plus"
                : "")
            let _ = prevRead = norm
            from written in s
            let __ = prevWritten = written
            select written;
    
        const int maxlen = 80;  
        return string.Concat(seq.Take(maxlen)).TrimEnd('-');
    }
    
    public static string RemapInternationalCharToAscii(string text)
    {
        var seq = text.Normalize(NormalizationForm.FormD)
            .Where(c => CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark);
    
        return string.Concat(seq).Normalize(NormalizationForm.FormC);
    }
    

    我的测试字符串:

    " I love C#, F#, C++, and... Crème brûlée!!! They see me codin'... they hatin'... tryin' to catch me codin' dirty... "

  • 2

    stackoverflow solution很棒,但现代浏览器(不包括IE,像往常一样)现在可以很好地处理utf8编码:

    enter image description here

    所以我升级了提议的解决方案:

    public static string ToFriendlyUrl(string title, bool useUTF8Encoding = false)
    {
        ...
    
            else if (c >= 128)
            {
                int prevlen = sb.Length;
                if (useUTF8Encoding )
                {
                    sb.Append(HttpUtility.UrlEncode(c.ToString(CultureInfo.InvariantCulture),Encoding.UTF8));
                }
                else
                {
                    sb.Append(RemapInternationalCharToAscii(c));
                }
        ...
    }
    

    Full Code on Pastebin

    编辑:Here's the code for RemapInternationalCharToAscii 方法(在pastebin中缺少) .

  • 1

    我喜欢不使用regular expressions的方式,所以我把它移植到PHP . 我刚刚添加了一个名为 is_between 的函数来检查字符:

    function is_between($val, $min, $max)
    {
        $val = (int) $val; $min = (int) $min; $max = (int) $max;
    
        return ($val >= $min && $val <= $max);
    }
    
    function international_char_to_ascii($char)
    {
        if (mb_strpos('àåáâäãåa', $char) !== false)
        {
            return 'a';
        }
    
        if (mb_strpos('èéêëe', $char) !== false)
        {
            return 'e';
        }
    
        if (mb_strpos('ìíîïi', $char) !== false)
        {
            return 'i';
        }
    
        if (mb_strpos('òóôõö', $char) !== false)
        {
            return 'o';
        }
    
        if (mb_strpos('ùúûüuu', $char) !== false)
        {
            return 'u';
        }
    
        if (mb_strpos('çccc', $char) !== false)
        {
            return 'c';
        }
    
        if (mb_strpos('zzž', $char) !== false)
        {
            return 'z';
        }
    
        if (mb_strpos('ssšs', $char) !== false)
        {
            return 's';
        }
    
        if (mb_strpos('ñn', $char) !== false)
        {
            return 'n';
        }
    
        if (mb_strpos('ýÿ', $char) !== false)
        {
            return 'y';
        }
    
        if (mb_strpos('gg', $char) !== false)
        {
            return 'g';
        }
    
        if (mb_strpos('r', $char) !== false)
        {
            return 'r';
        }
    
        if (mb_strpos('l', $char) !== false)
        {
            return 'l';
        }
    
        if (mb_strpos('d', $char) !== false)
        {
            return 'd';
        }
    
        if (mb_strpos('ß', $char) !== false)
        {
            return 'ss';
        }
    
        if (mb_strpos('Þ', $char) !== false)
        {
            return 'th';
        }
    
        if (mb_strpos('h', $char) !== false)
        {
            return 'h';
        }
    
        if (mb_strpos('j', $char) !== false)
        {
            return 'j';
        }
        return '';
    }
    
    function url_friendly_title($url_title)
    {
        if (empty($url_title))
        {
            return '';
        }
    
        $url_title = mb_strtolower($url_title);
    
        $url_title_max_length   = 80;
        $url_title_length       = mb_strlen($url_title);
        $url_title_friendly     = '';
        $url_title_dash_added   = false;
        $url_title_char = '';
    
        for ($i = 0; $i < $url_title_length; $i++)
        {
            $url_title_char     = mb_substr($url_title, $i, 1);
    
            if (strlen($url_title_char) == 2)
            {
                $url_title_ascii    = ord($url_title_char[0]) * 256 + ord($url_title_char[1]) . "\r\n";
            }
            else
            {
                $url_title_ascii    = ord($url_title_char);
            }
    
            if (is_between($url_title_ascii, 97, 122) || is_between($url_title_ascii, 48, 57))
            {
                $url_title_friendly .= $url_title_char;
    
                $url_title_dash_added = false;
            }
            elseif(is_between($url_title_ascii, 65, 90))
            {
                $url_title_friendly .= chr(($url_title_ascii | 32));
    
                $url_title_dash_added = false;
            }
            elseif($url_title_ascii == 32 || $url_title_ascii == 44 || $url_title_ascii == 46 || $url_title_ascii == 47 || $url_title_ascii == 92 || $url_title_ascii == 45 || $url_title_ascii == 47 || $url_title_ascii == 95 || $url_title_ascii == 61)
            {
                if (!$url_title_dash_added && mb_strlen($url_title_friendly) > 0)
                {
                    $url_title_friendly .= chr(45);
    
                    $url_title_dash_added = true;
                }
            }
            else if ($url_title_ascii >= 128)
            {
                $url_title_previous_length = mb_strlen($url_title_friendly);
    
                $url_title_friendly .= international_char_to_ascii($url_title_char);
    
                if ($url_title_previous_length != mb_strlen($url_title_friendly))
                {
                    $url_title_dash_added = false;
                }
            }
    
            if ($i == $url_title_max_length)
            {
                break;
            }
        }
    
        if ($url_title_dash_added)
        {
            return mb_substr($url_title_friendly, 0, -1);
        }
        else
        {
            return $url_title_friendly;
        }
    }
    
  • 0

    现在所有的浏览器都能很好地处理utf8编码,所以你可以使用WebUtility.UrlEncode方法,就像@giamin使用的HttpUtility.UrlEncode,但它在Web应用程序之外的工作 .

  • 2

    不不不 . 你们都错了 . 除了diacritics-fu之外,你已经到了那里,但是亚洲人物呢(对于不考虑他们的nihonjin兄弟的Ruby开发人员感到羞耻) .

    Firefox和Safari都在URL中显示非ASCII字符,坦率地说它们看起来很棒 . 很高兴支持像'http://somewhere.com/news/read/お前たちはアホじゃないかい'这样的链接 .

    所以这里有一些PHP代码可以做到,但我只是编写它并且没有对它进行压力测试 .

    <?php
        function slug($str)
        {
            $args = func_get_args();
            array_filter($args);  //remove blanks
            $slug = mb_strtolower(implode('-', $args));
    
            $real_slug = '';
            $hyphen = '';
            foreach(SU::mb_str_split($slug) as $c)
            {
                if (strlen($c) > 1 && mb_strlen($c)===1)
                {
                    $real_slug .= $hyphen . $c;
                    $hyphen = '';
                }
                else
                {
                    switch($c)
                    {
                        case '&':
                            $hyphen = $real_slug ? '-and-' : '';
                            break;
                        case 'a':
                        case 'b':
                        case 'c':
                        case 'd':
                        case 'e':
                        case 'f':
                        case 'g':
                        case 'h':
                        case 'i':
                        case 'j':
                        case 'k':
                        case 'l':
                        case 'm':
                        case 'n':
                        case 'o':
                        case 'p':
                        case 'q':
                        case 'r':
                        case 's':
                        case 't':
                        case 'u':
                        case 'v':
                        case 'w':
                        case 'x':
                        case 'y':
                        case 'z':
    
                        case 'A':
                        case 'B':
                        case 'C':
                        case 'D':
                        case 'E':
                        case 'F':
                        case 'G':
                        case 'H':
                        case 'I':
                        case 'J':
                        case 'K':
                        case 'L':
                        case 'M':
                        case 'N':
                        case 'O':
                        case 'P':
                        case 'Q':
                        case 'R':
                        case 'S':
                        case 'T':
                        case 'U':
                        case 'V':
                        case 'W':
                        case 'X':
                        case 'Y':
                        case 'Z':
    
                        case '0':
                        case '1':
                        case '2':
                        case '3':
                        case '4':
                        case '5':
                        case '6':
                        case '7':
                        case '8':
                        case '9':
                            $real_slug .= $hyphen . $c;
                            $hyphen = '';
                            break;
    
                        default:
                           $hyphen = $hyphen ? $hyphen : ($real_slug ? '-' : '');
                    }
                }
            }
            return $real_slug;
        }
    

    例:

    $str = "~!@#$%^&*()_+-=[]\{}|;':\",./<>?\n\r\t\x07\x00\x04 コリン ~!@#$%^&*()_+-=[]\{}|;':\",./<>?\n\r\t\x07\x00\x04 トーマス ~!@#$%^&*()_+-=[]\{}|;':\",./<>?\n\r\t\x07\x00\x04 アーノルド ~!@#$%^&*()_+-=[]\{}|;':\",./<>?\n\r\t\x07\x00\x04";
    echo slug($str);
    

    输出:コリン-and-トーマス-and-アーノルド

    ' - 和 - 是因为&'变为' - 和 - ' .

  • 4

    我将代码移植到TypeScript . 它可以很容易地适应JavaScript .

    我正在为 String 原型添加 .contains 方法,如果您定位到最新的浏览器或ES6,则可以使用 .includes .

    if (!String.prototype.contains) {
        String.prototype.contains = function (check) {
            return this.indexOf(check, 0) !== -1;
        };
    }
    
    declare interface String {
        contains(check: string): boolean;
    }
    
    export function MakeUrlFriendly(title: string) {
                if (title == null || title == '')
                    return '';
    
                const maxlen = 80;
                let len = title.length;
                let prevdash = false;
                let result = '';
                let c: string;
                let cc: number;
                let remapInternationalCharToAscii = function (c: string) {
                    let s = c.toLowerCase();
                    if ("àåáâäãåą".contains(s)) {
                        return "a";
                    }
                    else if ("èéêëę".contains(s)) {
                        return "e";
                    }
                    else if ("ìíîïı".contains(s)) {
                        return "i";
                    }
                    else if ("òóôõöøőð".contains(s)) {
                        return "o";
                    }
                    else if ("ùúûüŭů".contains(s)) {
                        return "u";
                    }
                    else if ("çćčĉ".contains(s)) {
                        return "c";
                    }
                    else if ("żźž".contains(s)) {
                        return "z";
                    }
                    else if ("śşšŝ".contains(s)) {
                        return "s";
                    }
                    else if ("ñń".contains(s)) {
                        return "n";
                    }
                    else if ("ýÿ".contains(s)) {
                        return "y";
                    }
                    else if ("ğĝ".contains(s)) {
                        return "g";
                    }
                    else if (c == 'ř') {
                        return "r";
                    }
                    else if (c == 'ł') {
                        return "l";
                    }
                    else if (c == 'đ') {
                        return "d";
                    }
                    else if (c == 'ß') {
                        return "ss";
                    }
                    else if (c == 'Þ') {
                        return "th";
                    }
                    else if (c == 'ĥ') {
                        return "h";
                    }
                    else if (c == 'ĵ') {
                        return "j";
                    }
                    else {
                        return "";
                    }
                };
    
                for (let i = 0; i < len; i++) {
                    c = title[i];
                    cc = c.charCodeAt(0);
    
                    if ((cc >= 97 /* a */ && cc <= 122 /* z */) || (cc >= 48 /* 0 */ && cc <= 57 /* 9 */)) {
                        result += c;
                        prevdash = false;
                    }
                    else if ((cc >= 65 && cc <= 90 /* A - Z */)) {
                        result += c.toLowerCase();
                        prevdash = false;
                    }
                    else if (c == ' ' || c == ',' || c == '.' || c == '/' || c == '\\' || c == '-' || c == '_' || c == '=') {
                        if (!prevdash && result.length > 0) {
                            result += '-';
                            prevdash = true;
                        }
                    }
                    else if (cc >= 128) {
                        let prevlen = result.length;
                        result += remapInternationalCharToAscii(c);
                        if (prevlen != result.length) prevdash = false;
                    }
                    if (i == maxlen) break;
                }
    
                if (prevdash)
                    return result.substring(0, result.length - 1);
                else
                    return result;
            }
    

相关问题