URL-Friendly Titles

JavaScript (ES6), 90 82 79 75 bytes

This is an attempt to do the job with a single replace(). This code extracts only the characters that we're interested in and ignores everything else. There's some additional logic to process the hyphens.

s=>(s.toLowerCase().replace(/[ a-z,-9]/g,c=>S=c<'0'?s+'-':s=s?S+c:c,s=0),s)

Test cases

let f =

s=>(s.toLowerCase().replace(/[ a-z,-9]/g,c=>S=c<'0'?s+'-':s=s?S+c:c,s=0),s)

console.log(f(`Loading... Forever`));                         // -> loading-forever
console.log(f(`N(e(s(t))) a string`));                        // -> nest-a-string
console.log(f(`"Hello, World!"`));                            // -> hello-world
console.log(f(`URL-Friendly titles`));                        // -> url-friendly-titles
console.log(f(`C.U.S.R.S`));                                  // -> c-u-s-r-s
console.log(f(`1+2+3+4+...+n = -1/12?`));                     // -> 1234-n-1-12
console.log(f(`How can I use cmp(a,b)`));                     // -> how-can-i-use-cmpa-b
console.log(f(`Export The $PATH Variable, Line-By-Line`));    // -> export-the-path-variable-line-by-line
console.log(f(`Do n and n^3 have the same set of digits?`));  // -> do-n-and-n3-have-the-same-set-of-digits
console.log(f(`Quine Anagrams! (Cops' Thread)`));             // -> quine-anagrams-cops-thread
console.log(f(`The Golfer Adventure - Chapter 1`));           // -> the-golfer-adventure-chapter-1
console.log(f(`Bootloader golf: Brainf***`));                 // -> bootloader-golf-brainf
console.log(f(`0123`));                                       // -> 0123
console.log(f(`a a1`));                                       // -> a-a1
console.log(f(`2-1=1`));                                      // -> 2-11
console.log(f(',a^a,'));                                      // -> aa


V, 41, 40, 37, 36 bytes

VuÍ[ .,\/]/-
Í0-9a-z­]
Í-«/-
Í^-ü-$

Try it online! or Check all test cases at once!

As usual, here this contains a bunch of unprintable and non-ASCII characters, so here is a hexdump:

0000000: 5675 cd5b 202e 2c5c 2f5d 2f2d 0acd 8430  Vu.[ .,\/]/-...0
0000010: 2d39 612d 7aad 5d0a cd2d ab2f 2d0a cd5e  -9a-z.]..-./-..^
0000020: 2dfc 2d24                                -.-$

It's challenges like these where V's "Compressed regex" system come in handy.

Explanation

First things first, we will convert everything to lowercase. Fortunately there is a really convenient way to do this in two bytes. I wrote a tip about that here. So we do

V           " Visually select this whole line
 u          " Convert this whole line to lowercase

After that we do a bunch of compressed substitute commands. A nice overview of how V's compressed regex works can be foud here, but the basic idea is we can set the high-bit to avoid having to escape certain characters. Another convenience is that ranges (like :%) and flags (like /g) are automagically filled in. But in the end, it all translates to vim substitute commands. In fact, we could even directly translate the rest of the program to vim. That would give us this:

:%s/[ .,/]/-/g
:%s/[^0-9a-z\-]//g
:%s/-\+/-
:%s/^-\|-$//g

If you speak vim-regex, it should be more clear what the rest of the program does now. So here is the rest of the program:

Í               " Substitute:
 [ .,\/]        "   a space, period, comma or forward slash. (Due to a strange bug, this needs to be escaped)
        /-      "   with a dash
Í               " Remove:
 [^0-9a-z­]     "   Any character that is not a dash or alpha-numeric
Í               " Substitute:
 -«             "   One or more dashes
   /-           "   with one dash
Í               " Remove:
 ^-             "   A dash at the beginning of a line
   ü            "   OR
    -$          "   a dash at the end of a line

JavaScript (ES6) 91 96

1 bytes saved thx @ETHproductions

s=>s.toLowerCase().replace(/([ .,/-])|\W|_/g,(c,d)=>d?'-':'').replace(/^-*|-*$|-(?=-)/g,'')

Test

F=
s=>s.toLowerCase().replace(/([ .,/-])|\W|_/g,(c,d)=>d?'-':'').replace(/^-*|-*$|-(?=-)/g,'')

;[['Loading... Forever.....', 'loading-forever'],
['N(e(s(t))) a string', 'nest-a-string'],
['"Hello, World!"', 'hello-world'],
['URL-Friendly titles', 'url-friendly-titles'],
['C.U.S.R.S','c-u-s-r-s'],
['1+2+3+4+...+n = -1/12?', '1234-n-1-12'],
['How can I use cmp(a,b)', 'how-can-i-use-cmpa-b'],
['Export The $PATH Variable, Line-By-Line', 'export-the-path-variable-line-by-line'],
['Do n and n^3 have the same set of digits?', 'do-n-and-n3-have-the-same-set-of-digits'],
['Quine Anagrams! (Cops\' Thread)', 'quine-anagrams-cops-thread'],
['The Golfer Adventure - Chapter 1', 'the-golfer-adventure-chapter-1'],
['Bootloader golf: Brainf***', 'bootloader-golf-brainf'],
['0123', '0123'],
['a a1', 'a-a1'],
['2-1=1', '2-11']]
.forEach(t=>{
  var i=t[0],k=t[1],r=F(i)
  console.log(r==k?'OK':'KO',i+' -> '+r,r==k?'':k)
})