|
1 | 1 | /*! |
2 | | - * Bootstrap Table of Contents v1.0.0 (http://afeld.github.io/bootstrap-toc/) |
| 2 | + * Bootstrap Table of Contents v1.0.1 (http://afeld.github.io/bootstrap-toc/) |
3 | 3 | * Copyright 2015 Aidan Feldman |
4 | 4 | * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ |
5 | 5 | (function($) { |
6 | | - 'use strict'; |
| 6 | + "use strict"; |
7 | 7 |
|
8 | 8 | window.Toc = { |
9 | 9 | helpers: { |
|
12 | 12 | // http://danielnouri.org/notes/2011/03/14/a-jquery-find-that-also-finds-the-root-element/ |
13 | 13 | // http://stackoverflow.com/a/12731439/358804 |
14 | 14 | var $descendants = $el.find(selector); |
15 | | - return $el.filter(selector).add($descendants).filter(':not([data-toc-skip])'); |
| 15 | + return $el |
| 16 | + .filter(selector) |
| 17 | + .add($descendants) |
| 18 | + .filter(":not([data-toc-skip])"); |
16 | 19 | }, |
17 | 20 |
|
18 | 21 | generateUniqueIdBase: function(el) { |
19 | 22 | var text = $(el).text(); |
20 | | - var anchor = text.trim().toLowerCase().replace(/[^A-Za-z0-9]+/g, '-'); |
21 | | - return anchor || el.tagName.toLowerCase(); |
| 23 | + |
| 24 | + // adapted from |
| 25 | + // https://github.com/bryanbraun/anchorjs/blob/65fede08d0e4a705f72f1e7e6284f643d5ad3cf3/anchor.js#L237-L257 |
| 26 | + |
| 27 | + // Regex for finding the non-safe URL characters (many need escaping): & +$,:;=?@"#{}|^~[`%!'<>]./()*\ (newlines, tabs, backspace, & vertical tabs) |
| 28 | + var nonsafeChars = /[& +$,:;=?@"#{}|^~[`%!'<>\]\.\/\(\)\*\\\n\t\b\v]/g, |
| 29 | + urlText; |
| 30 | + |
| 31 | + // Note: we trim hyphens after truncating because truncating can cause dangling hyphens. |
| 32 | + // Example string: // " ⚡⚡ Don't forget: URL fragments should be i18n-friendly, hyphenated, short, and clean." |
| 33 | + urlText = text |
| 34 | + .trim() // "⚡⚡ Don't forget: URL fragments should be i18n-friendly, hyphenated, short, and clean." |
| 35 | + .replace(/\'/gi, "") // "⚡⚡ Dont forget: URL fragments should be i18n-friendly, hyphenated, short, and clean." |
| 36 | + .replace(nonsafeChars, "-") // "⚡⚡-Dont-forget--URL-fragments-should-be-i18n-friendly--hyphenated--short--and-clean-" |
| 37 | + .replace(/-{2,}/g, "-") // "⚡⚡-Dont-forget-URL-fragments-should-be-i18n-friendly-hyphenated-short-and-clean-" |
| 38 | + .substring(0, 64) // "⚡⚡-Dont-forget-URL-fragments-should-be-i18n-friendly-hyphenated-" |
| 39 | + .replace(/^-+|-+$/gm, "") // "⚡⚡-Dont-forget-URL-fragments-should-be-i18n-friendly-hyphenated" |
| 40 | + .toLowerCase(); // "⚡⚡-dont-forget-url-fragments-should-be-i18n-friendly-hyphenated" |
| 41 | + |
| 42 | + return urlText || el.tagName.toLowerCase(); |
22 | 43 | }, |
23 | 44 |
|
24 | 45 | generateUniqueId: function(el) { |
|
27 | 48 | var anchor = anchorBase; |
28 | 49 | if (i > 0) { |
29 | 50 | // add suffix |
30 | | - anchor += '-' + i; |
| 51 | + anchor += "-" + i; |
31 | 52 | } |
32 | 53 | // check if ID already exists |
33 | 54 | if (!document.getElementById(anchor)) { |
|
58 | 79 |
|
59 | 80 | generateNavEl: function(anchor, text) { |
60 | 81 | var $a = $('<a class="nav-link"></a>'); |
61 | | - $a.attr('href', '#' + anchor); |
| 82 | + $a.attr("href", "#" + anchor); |
62 | 83 | $a.text(text); |
63 | | - var $li = $('<li></li>'); |
| 84 | + var $li = $("<li></li>"); |
64 | 85 | $li.append($a); |
65 | 86 | return $li; |
66 | 87 | }, |
67 | 88 |
|
68 | 89 | generateNavItem: function(headingEl) { |
69 | 90 | var anchor = this.generateAnchor(headingEl); |
70 | 91 | var $heading = $(headingEl); |
71 | | - var text = $heading.data('toc-text') || $heading.text(); |
| 92 | + var text = $heading.data("toc-text") || $heading.text(); |
72 | 93 | return this.generateNavEl(anchor, text); |
73 | 94 | }, |
74 | 95 |
|
75 | 96 | // Find the first heading level (`<h1>`, then `<h2>`, etc.) that has more than one element. Defaults to 1 (for `<h1>`). |
76 | 97 | getTopLevel: function($scope) { |
77 | 98 | for (var i = 1; i <= 6; i++) { |
78 | | - var $headings = this.findOrFilter($scope, 'h' + i); |
| 99 | + var $headings = this.findOrFilter($scope, "h" + i); |
79 | 100 | if ($headings.length > 1) { |
80 | 101 | return i; |
81 | 102 | } |
|
86 | 107 |
|
87 | 108 | // returns the elements for the top level, and the next below it |
88 | 109 | getHeadings: function($scope, topLevel) { |
89 | | - var topSelector = 'h' + topLevel; |
| 110 | + var topSelector = "h" + topLevel; |
90 | 111 |
|
91 | 112 | var secondaryLevel = topLevel + 1; |
92 | | - var secondarySelector = 'h' + secondaryLevel; |
| 113 | + var secondarySelector = "h" + secondaryLevel; |
93 | 114 |
|
94 | | - return this.findOrFilter($scope, topSelector + ',' + secondarySelector); |
| 115 | + return this.findOrFilter($scope, topSelector + "," + secondarySelector); |
95 | 116 | }, |
96 | 117 |
|
97 | 118 | getNavLevel: function(el) { |
|
141 | 162 | opts = this.helpers.parseOps(opts); |
142 | 163 |
|
143 | 164 | // ensure that the data attribute is in place for styling |
144 | | - opts.$nav.attr('data-toggle', 'toc'); |
| 165 | + opts.$nav.attr("data-toggle", "toc"); |
145 | 166 |
|
146 | 167 | var $topContext = this.helpers.createChildNavList(opts.$nav); |
147 | 168 | var topLevel = this.helpers.getTopLevel(opts.$scope); |
|
0 commit comments