Comparing version 1.0.0 to 1.0.1
@@ -0,0 +0,0 @@ var paths = { |
@@ -0,0 +0,0 @@ var gulp = require('gulp'); |
@@ -8,4 +8,5 @@ var gulp = require('gulp'); | ||
'docs-browserify', | ||
'docs-browserify-test', // temp | ||
'docs-browser-sync', | ||
'docs-watch', | ||
]); |
@@ -12,3 +12,3 @@ var gulp = require('gulp'); | ||
}, | ||
port: 4000, | ||
port: 4100, | ||
server: { | ||
@@ -15,0 +15,0 @@ baseDir: paths.build, |
@@ -0,0 +0,0 @@ var path = require('path'); |
var gulp = require('gulp'); | ||
gulp.task('build', [ | ||
gulp.task('docs-build', [ | ||
'docs-markdown', | ||
@@ -5,0 +5,0 @@ 'docs-copy-files', |
@@ -0,0 +0,0 @@ var gulp = require('gulp'); |
@@ -0,1 +1,2 @@ | ||
var path = require('path'); | ||
var gulp = require('gulp'); | ||
@@ -2,0 +3,0 @@ var ghPages = require('gulp-gh-pages'); |
@@ -11,3 +11,4 @@ var gulp = require('gulp'); | ||
var handleErrors = require('../util/handleErrors'); | ||
var paths = require('../../config').paths; | ||
var config = require('../../config'); | ||
var paths = config.paths; | ||
@@ -18,5 +19,3 @@ // Swig config. | ||
loader: swig.loaders.fs(paths.src), | ||
locals: { | ||
paths: paths | ||
} | ||
locals: config | ||
}); | ||
@@ -35,3 +34,3 @@ | ||
path.join('README.md'), | ||
path.join('docs/**/*.md') | ||
path.join(paths.docs, '**/*.md') | ||
// path.join('*.md') | ||
@@ -38,0 +37,0 @@ ]) |
@@ -0,0 +0,0 @@ var gulp = require('gulp'); |
@@ -14,2 +14,5 @@ var gulp = require('gulp'); | ||
.on('error', handleErrors); | ||
// Watch task for test js | ||
gulp.watch(path.join(paths.test + '**/*.js'), ['docs-browserify-test']) | ||
.on('error', handleErrors); | ||
@@ -16,0 +19,0 @@ // Watch tasks for html |
@@ -0,0 +0,0 @@ var gulp = require('gulp'); |
var gulp = require('gulp'); | ||
var electronMocha = require('gulp-electron-mocha'); | ||
var mochatron = require('mochatron'); | ||
var paths = require('../../config').paths; | ||
gulp.task('test', function() { | ||
return gulp.src(paths.test, { read: false }) | ||
.pipe(electronMocha({ | ||
renderer: true, | ||
})); | ||
mochatron({ | ||
url: 'http://localhost:4100/test/test.html', | ||
silent: true, | ||
window: false | ||
}); | ||
}); |
@@ -0,0 +0,0 @@ /* bundleLogger |
@@ -0,0 +0,0 @@ var notify = require("gulp-notify"); |
@@ -0,0 +0,0 @@ /* |
{ | ||
"name": "tocbot", | ||
"version": "1.0.0", | ||
"version": "1.0.1", | ||
"description": "Generate a table of contents based on the heading structure of a html document.", | ||
@@ -11,3 +11,3 @@ "main": "gulpfile.js", | ||
"type": "git", | ||
"url": "git+https://github.com/optimizely/tocbot.git" | ||
"url": "git+https://github.com/tscanlin/tocbot.git" | ||
}, | ||
@@ -28,11 +28,13 @@ "keywords": [ | ||
"bugs": { | ||
"url": "https://github.com/optimizely/tocbot/issues" | ||
"url": "https://github.com/tscanlin/tocbot/issues" | ||
}, | ||
"homepage": "https://github.com/optimizely/tocbot#readme", | ||
"homepage": "https://github.com/tscanlin/tocbot#readme", | ||
"devDependencies": { | ||
"babel-eslint": "^5.0.0", | ||
"babel-runtime": "^6.3.19", | ||
"browser-sync": "^2.10.1", | ||
"browserify": "^12.0.1", | ||
"chai": "^3.4.1", | ||
"del": "^2.2.0", | ||
"eslint": "^1.10.3", | ||
"eslint": "^2.4.0", | ||
"gulp": "^3.9.0", | ||
@@ -52,2 +54,5 @@ "gulp-changed": "^1.3.0", | ||
"js-yaml": "^3.4.6", | ||
"mocha": "^2.3.4", | ||
"mochatron": "^1.0.7", | ||
"optimizely-oui": "github:optimizely/oui", | ||
"require-dir": "^0.3.0", | ||
@@ -60,5 +65,4 @@ "swig": "^1.4.2", | ||
"dependencies": { | ||
"optimizely-oui": "github:optimizely/oui", | ||
"smooth-scroll": "cferdinandi/smooth-scroll" | ||
} | ||
} |
@@ -6,4 +6,6 @@ --- | ||
## Introduction | ||
<h1 class="display--none"><a href="http://tscanlin.github.io/tocbot">Tocbot</a></h1> | ||
<h2 id="introduction" class="hard flush">Introduction</h2> | ||
tocbot is a small script to build a table of contents (TOC) from headings in an HTML document. tocbot works well with [Smooth Scroll](https://github.com/cferdinandi/smooth-scroll) and together they provide an experience very similar to [Tocify](http://gregfranko.com/jquery.tocify.js/). | ||
@@ -14,5 +16,2 @@ | ||
### Checkout the [**Demo**](/) | ||
## Get Started | ||
@@ -25,6 +24,7 @@ | ||
Include the script at the bottom of the page before the closing body tag | ||
Include the script at the bottom of the page before the closing body tag. | ||
```html | ||
<script src="http://optimizely.github.io/tocbot/js/tocbot.js"></script> | ||
<script src="/js/tocbot.js"></script> | ||
<script src="/js/smooth-scroll.js"></script> | ||
``` | ||
@@ -34,3 +34,3 @@ | ||
Install it with npm | ||
Install it with npm. | ||
@@ -41,6 +41,13 @@ ```sh | ||
And require it | ||
And optionally. | ||
```sh | ||
npm install --save cferdinandi/smooth-scroll | ||
``` | ||
Then require them. | ||
```javascript | ||
var tocbot = require('tocbot'); | ||
var smoothScroll = require('smooth-scroll'); | ||
``` | ||
@@ -51,6 +58,6 @@ | ||
CSS is used for expanding & collapsing groupings and some basic styling. The core of what's required is **only 24 lines unminified**. | ||
CSS is used for expanding & collapsing groupings and some basic styling. The core of what's required is only 24 lines unminified. | ||
```html | ||
<link rel="stylesheet" href="http://optimizely.github.io/tocbot/css/style.css"> | ||
<link rel="stylesheet" href="http://tscanlin.github.io/tocbot/css/style.css"> | ||
``` | ||
@@ -91,3 +98,3 @@ | ||
There is no need for jQuery as this library uses **vanilla javascript**. | ||
There is no need for jQuery as this library uses **vanilla javascript** and is only about 500 lines unminified. | ||
@@ -134,4 +141,4 @@ There are no external dependencies for this script, besides [**Smooth Scroll**](https://github.com/cferdinandi/smooth-scroll) (which also has no dependencies) should you choose to include it. | ||
activeLinkClass: 'is-active-link', | ||
// Headings that match the excludeSelector will be skipped. | ||
excludeSelector: '.skip-toc', | ||
// Headings that match the ignoreSelector will be skipped. | ||
ignoreSelector: '.skip-toc', | ||
// Fixed position class to add to make sidebar fixed after scrolling down past the fixedSidebarOffset. | ||
@@ -190,15 +197,10 @@ positionFixedClass: 'is-position-fixed', | ||
## Running Tests | ||
gulp test | ||
## Roadmap | ||
- Tests | ||
- List size of js and css | ||
- Split into smaller files (core, util/data, util/dom) | ||
- Blog post to announce it!!! | ||
- Eventually, a place to drop in markdown to preview it. | ||
- React.js support. | ||
- Debounce option. | ||
- More tests | ||
- Blog post to announce it | ||
- Eventually, a place to drop in markdown to preview it | ||
- Debounce option | ||
- React.js support | ||
@@ -214,4 +216,10 @@ | ||
Contributions and suggestions are welcome. Please feel free to open an issue if you run into a problem or have a feature request. I'll do my best to respond in a timely fashion. | ||
Contributions and suggestions are welcome! Please feel free to open an issue if you run into a problem or have a feature request. I'll do my best to respond in a timely fashion. | ||
If you want to open a pull request just fork the repo but please make sure all tests and lint pass first. | ||
### Running Tests | ||
`gulp test` | ||
[//]: # (FAQ) | ||
@@ -218,0 +226,0 @@ |
/** | ||
* tocbot | ||
* tocbot is similar to tocify (http://gregfranko.com/jquery.tocify.js/) (except its native w/ no need for jquery UI) | ||
* This creates a toble of contents base on headings that allows users to easily jump to different sections. | ||
* tocbot is similar to tocify (http://gregfranko.com/jquery.tocify.js/) (except its native w/ no need for jquery) | ||
* This creates a toble of contents based on HTML headings which allows users to easily jump to different sections. | ||
* | ||
* @author Tim Scanlin (tim.scanlin@optimizely.com) | ||
* @author Tim Scanlin | ||
*/ | ||
@@ -21,3 +21,15 @@ | ||
var tocbot = {}; // Object for public APIs. | ||
// Default options. | ||
var defaultOptions = require('./default-options.js'); | ||
// Object to store current options. | ||
var options = {}; | ||
// Object for public APIs. | ||
var tocbot = {}; | ||
var BuildHtml = require('./build-html.js'); | ||
var ParseContent = require('./parse-content.js'); | ||
// Keep these variables at top scope once options are passed in. | ||
var buildHtml; | ||
var parseContent; | ||
var doc = root.document; | ||
@@ -27,6 +39,2 @@ var body = document.body; | ||
// Helpers. | ||
var forEach = [].forEach; | ||
var reduce = [].reduce; | ||
var some = [].some; | ||
// From: https://github.com/Raynos/xtend | ||
@@ -48,59 +56,2 @@ var hasOwnProperty = Object.prototype.hasOwnProperty; | ||
// Default options. | ||
var options = {}; | ||
var defaultOptions = { | ||
// Where to render the table of contents. | ||
tocSelector: '.js-toc', | ||
// Where to grab the headings to build the table of contents. | ||
contentSelector: '.js-content', | ||
// Reference to smoothScroll | ||
smoothScroll: undefined, | ||
// smoothScroll Options | ||
smoothScrollOptions: { | ||
easing: 'easeInOutCubic', | ||
offset: 0, | ||
speed: 300, // animation duration. | ||
updateURL: true, | ||
}, | ||
// Which headings to grab inside of the contentSelector element. | ||
headingsToSelect: [ | ||
'h1', | ||
'h2', | ||
'h3', | ||
'h4', | ||
'h5', | ||
], | ||
// Class to add to active links (the link corresponding to the top most heading on the page). | ||
activeLinkClass: 'is-active-link', | ||
// Headings that match the excludeSelector will be skipped. | ||
excludeSelector: '.skip-toc', | ||
// Fixed position class to add to make sidebar fixed after scrolling down past the fixedSidebarOffset. | ||
positionFixedClass: 'is-position-fixed', | ||
// fixedSidebarOffset can be any number but by default is set to auto which sets the fixedSidebarOffset to the sidebar element's offsetTop from the top of the document on init. | ||
fixedSidebarOffset: 'auto', | ||
// Main class to add to links. | ||
linkClass: 'toc-link', | ||
// Extra classes to add to links. | ||
extraLinkClasses: 'color--base', | ||
// Main class to add to lists. | ||
listClass: 'toc-list', | ||
// Extra classes to add to lists. | ||
extraListClasses: 'soft--left', | ||
// Headings offset between the headings and the top of the document (helps with weird rounding bugs that pop up). | ||
headingsOffset: 2, | ||
// Class that gets added when a list should be collapsed. | ||
isCollapsedClass: 'is-collapsed', | ||
// Class that gets added when a list should be able to be collapsed but isn't necessarily collpased. | ||
collapsibleClass: 'collapsible', | ||
// How many heading levels should not be collpased. For example, number 6 will show everything since there are only 6 heading levels and number 0 will collpase them all. | ||
collapseDepth: 0, | ||
// This is storing current state and not really a setting... | ||
// TODO: Handle this better, maybe bring back a state object?? | ||
_currentlyHighlighting: true, | ||
}; | ||
/** | ||
@@ -111,9 +62,11 @@ * Destroy tocbot. | ||
// Remove event listeners | ||
doc.removeEventListener('scroll'); | ||
doc.removeEventListener('resize'); | ||
removeTocLinkListeners(); | ||
document.removeEventListener('scroll'); | ||
document.removeEventListener('resize'); | ||
if (buildHtml) { | ||
document.removeEventListener('click', buildHtml.disableTocAnimation); | ||
} | ||
// Destroy smoothScroll if it exists. | ||
if (options.smoothScroll) { | ||
this.smoothScroll.destroy(); | ||
options.smoothScroll.destroy(); | ||
} | ||
@@ -132,5 +85,2 @@ }; | ||
// Destroy it if it exists first. | ||
tocbot.destroy(); | ||
// Merge defaults with user options. | ||
@@ -142,28 +92,40 @@ // Set to options variable at the top. | ||
// Pass options to these modules. | ||
buildHtml = BuildHtml(options); | ||
parseContent = ParseContent(options); | ||
// For testing purposes. | ||
this._buildHtml = buildHtml; | ||
this._parseContent = parseContent; | ||
// Destroy it if it exists first. | ||
tocbot.destroy(); | ||
// Get headings array | ||
var headingsArray = selectHeadings('body', options.headingsToSelect, { | ||
excludeSelector: options.excludeSelector | ||
}); | ||
var headingsArray = parseContent.selectHeadings(options.contentSelector, options.headingsToSelect); | ||
// Build nested headings array. | ||
var nestedHeadingsObj = nestHeadingsArray(headingsArray); | ||
var nestedHeadingsObj = parseContent.nestHeadingsArray(headingsArray); | ||
var nestedHeadings = nestedHeadingsObj.nest; | ||
/////////////////////////////////////////////////////////////////////////////////////////////////// | ||
// USE CALLBACK TO BUILD NODE TREE IN MEMORY | ||
// APPEND NODE TREE | ||
// Render. | ||
render(options.tocSelector, nestedHeadings); | ||
buildHtml.render(options.tocSelector, nestedHeadings); | ||
// Update Sidebar and bind listeners. | ||
updateToc(headingsArray); | ||
doc.addEventListener('scroll', function() { | ||
updateToc(headingsArray); | ||
buildHtml.updateToc(headingsArray); | ||
document.addEventListener('scroll', function() { | ||
buildHtml.updateToc(headingsArray); | ||
}); | ||
doc.addEventListener('resize', function() { | ||
updateToc(headingsArray); | ||
document.addEventListener('resize', function() { | ||
buildHtml.updateToc(headingsArray); | ||
}); | ||
// Bind click listeners to disable animation. | ||
document.addEventListener('click', buildHtml.disableTocAnimation); | ||
// Initialize smoothscroll if it exists. | ||
if (options.smoothScroll) { | ||
this.smoothScroll = options.smoothScroll.init(options.smoothScrollOptions); | ||
this.smoothScroll = options.smoothScroll.init(extend(options.smoothScrollOptions, { | ||
callback: buildHtml.enableTocAnimation | ||
})); | ||
} | ||
@@ -179,282 +141,9 @@ | ||
tocbot.destroy(); | ||
tocbot.init(customOptions); | ||
tocbot.init(customOptions || this.options); | ||
}; | ||
/** | ||
* Select headings in content area, exclude any selector in options.excludeSelector | ||
* @param {String} contentSelector | ||
* @param {Array} headingsToSelect | ||
* @param {Object} options | ||
* @return {Array} | ||
*/ | ||
function selectHeadings(contentSelector, headingsToSelect, options) { | ||
if (options.excludeSelector) { | ||
headingsToSelect = headingsToSelect.map(function(selector) { | ||
return selector + ':not(' + options.excludeSelector + ')'; | ||
}); | ||
} | ||
return doc.querySelector(contentSelector) | ||
.querySelectorAll(headingsToSelect.join(', ')); | ||
} | ||
// Make tocbot available globally. | ||
root.tocbot = tocbot; | ||
/** | ||
* Nest headings array into nested arrays with 'children' property. | ||
* @param {Array} headingsArray | ||
* @param {Function} callback | ||
* @return {Object} | ||
*/ | ||
function nestHeadingsArray(headingsArray, callback) { | ||
return reduce.call(headingsArray, function(prev, curr, index) { | ||
var currentHeading = getHeadingObject(curr); | ||
if (prev.lastItem) { | ||
if (getHeadingLevel(curr) < getHeadingLevel(prev.lastItem)) { | ||
// Allows going back up multiple levels. | ||
prev.depth -= getHeadingLevel(prev.lastItem) - getHeadingLevel(curr); | ||
} | ||
if (getHeadingLevel(curr) > getHeadingLevel(prev.lastItem)) { | ||
prev.depth++; | ||
} | ||
} | ||
appendNodeAtDepth(currentHeading, prev.depth, prev.nest) | ||
prev.lastItem = curr; | ||
return prev; | ||
}, { | ||
lastItem: undefined, | ||
depth: 0, | ||
nest: [], | ||
}); | ||
} | ||
/** | ||
* Append node at a specific depth in the nested array. | ||
* @param {Object} node | ||
* @param {Number} depth | ||
* @param {Array} array | ||
* @return {Array} | ||
*/ | ||
function appendNodeAtDepth(node, depth, array) { | ||
var counter = depth; | ||
while(counter > 0) { | ||
array = getLastItem(array).children; | ||
counter--; | ||
} | ||
// console.log(depth, options.collapseDepth, depth < options.collapseDepth) | ||
if (depth > options.collapseDepth) { | ||
node.isCollapsed = true; | ||
} | ||
// collapsedClass: 'is-collapsed', | ||
// collapseDepth: 1, | ||
array.push(node); | ||
return array; | ||
} | ||
/** | ||
* Get the last item in an array and return a reference to it. | ||
* @param {Array} array | ||
* @return {Object} | ||
*/ | ||
function getLastItem(array) { | ||
return array[array.length - 1]; | ||
} | ||
/** | ||
* Get heading level for a heading dom node. | ||
* @param {HTMLElement} heading | ||
* @return {Number} | ||
*/ | ||
function getHeadingLevel(heading) { | ||
return +heading.nodeName.split('H').join(''); | ||
} | ||
/** | ||
* Get important properties from a heading element and store in a plain object. | ||
* @param {HTMLElement} heading | ||
* @return {Object} | ||
*/ | ||
function getHeadingObject(heading) { | ||
return { | ||
id: heading.id, | ||
children: [], | ||
nodeName: heading.nodeName, | ||
textContent: heading.textContent.trim(), | ||
}; | ||
} | ||
// HTML | ||
/** | ||
* Render nested heading array data into a given selector. | ||
* @param {String} selector | ||
* @param {Array} data | ||
* @return {HTMLElement} | ||
*/ | ||
function render(selector, data) { | ||
var self = this; | ||
var collapsed = false; | ||
var container = createList(collapsed); | ||
function createEl(d, container) { | ||
var link = container.appendChild(createLink(d)); | ||
if (d.children.length) { | ||
var list = createList(d.isCollapsed); | ||
d.children.forEach(function(d) { | ||
createEl(d, list); | ||
}); | ||
link.appendChild(list); | ||
} | ||
} | ||
data.forEach(function(d) { | ||
createEl(d, container) | ||
}); | ||
// Append the Elements that have been created; | ||
return doc.querySelector(selector) | ||
.appendChild(container); | ||
} | ||
function createLink(data) { | ||
var item = document.createElement('li'); | ||
var a = document.createElement('a'); | ||
a.textContent = data.textContent; | ||
if (options.smoothScroll !== undefined) { | ||
a.setAttribute('data-scroll', ''); | ||
} | ||
a.setAttribute('href', '#' + data.id); | ||
a.setAttribute('class', options.linkClass | ||
+ ' ' + 'node-name--' + data.nodeName | ||
+ ' ' + options.extraLinkClasses); | ||
item.appendChild(a); | ||
return item; | ||
} | ||
function createList(isCollapsed) { | ||
var list = document.createElement('ul'); | ||
var classes = options.listClass | ||
+ ' ' + options.extraListClasses; | ||
if (isCollapsed) { | ||
classes += ' ' + options.collapsibleClass; | ||
classes += ' ' + options.isCollapsedClass; | ||
} | ||
list.setAttribute('class', classes); | ||
return list; | ||
} | ||
function updateFixedSidebarClass() { | ||
var top = document.documentElement.scrollTop || body.scrollTop; | ||
var tocEl = doc.querySelector(options.tocSelector); | ||
if (options.fixedSidebarOffset === 'auto') { | ||
options.fixedSidebarOffset = doc.querySelector(options.tocSelector).offsetTop; | ||
} | ||
if (top > options.fixedSidebarOffset) { | ||
tocEl.classList.add(options.positionFixedClass); | ||
} else { | ||
tocEl.classList.remove(options.positionFixedClass); | ||
} | ||
} | ||
// Update Toc | ||
function updateToc(headingsArray) { | ||
var top = document.documentElement.scrollTop || body.scrollTop; | ||
// Add fixed class at offset; | ||
updateFixedSidebarClass(); | ||
// Get the top most heading currently visible on the page so we know what to highlight. | ||
var headings = headingsArray; | ||
var topHeader; | ||
// Using some instead of each so that we can escape early. | ||
if (options._currentlyHighlighting | ||
&& doc.querySelector(options.tocSelector) !== null | ||
&& headings.length > 0) { | ||
some.call(headings, function(heading, i) { | ||
if (heading.offsetTop > top + options.headingsOffset) { | ||
// Don't allow negative index value. | ||
var index = (i === 0) ? i : i - 1; | ||
topHeader = headings[index]; | ||
return true; | ||
} else if (i === headings.length - 1) { | ||
// This allows scrolling for the last heading on the page. | ||
topHeader = headings[headings.length - 1]; | ||
return true; | ||
} | ||
}); | ||
// Remove the active class from the other tocLinks. | ||
var tocLinks = doc.querySelector(options.tocSelector) | ||
.querySelectorAll('.' + options.linkClass); | ||
forEach.call(tocLinks, function(tocLink) { | ||
tocLink.classList.remove(options.activeLinkClass); | ||
}); | ||
// Add the active class to the active tocLink. | ||
var activeTocLink = doc.querySelector(options.tocSelector) | ||
.querySelector('.' + options.linkClass | ||
+ '.node-name--' + topHeader.nodeName | ||
+ '[href="#' + topHeader.id + '"]'); | ||
activeTocLink.classList.add(options.activeLinkClass); | ||
var tocLists = doc.querySelector(options.tocSelector) | ||
.querySelectorAll('.' + options.listClass + '.' + options.collapsibleClass); | ||
// Collapse the other collapsible lists. | ||
forEach.call(tocLists, function(list) { | ||
list.classList.add(options.isCollapsedClass); | ||
}); | ||
// Expand the active link's collapsible list and its sibling if applicable. | ||
if (activeTocLink.nextSibling) { | ||
activeTocLink.nextSibling.classList.remove(options.isCollapsedClass); | ||
} | ||
removeCollapsedFromParents(activeTocLink.parentNode.parentNode); | ||
} | ||
disableTocAnimation() | ||
} | ||
function removeCollapsedFromParents(element) { | ||
// console.log(element, element.classList.contains(options.collapsibleClass)) | ||
if (element.classList.contains(options.collapsibleClass)) { | ||
element.classList.remove(options.isCollapsedClass) | ||
return removeCollapsedFromParents(element.parentNode.parentNode); | ||
} | ||
return element; | ||
} | ||
function disableTocAnimation() { | ||
// Bind to tocLink clicks to temporarily disable highlighting | ||
// while smoothScroll is animating. | ||
var tocLinks = doc.querySelector(options.tocSelector) | ||
.querySelectorAll('.' + options.linkClass); | ||
if (tocLinks) { | ||
forEach.call(tocLinks, function(tocLink) { | ||
tocLink.addEventListener('click', function() { | ||
options._currentlyHighlighting = false; | ||
window.setTimeout(function() { | ||
options._currentlyHighlighting = true; | ||
}, options.smoothScrollOptions.speed); | ||
}); | ||
}); | ||
} | ||
} | ||
function removeTocLinkListeners() { | ||
// var tocLinks = doc.querySelector(options.tocSelector) | ||
// .querySelectorAll('.' + options.linkClass); | ||
// if (tocLinks) { | ||
// forEach.call(tocLinks, function(tocLink) { | ||
// // TODO: This event listener needs to get remove too!! | ||
// tocLink.removeEventListener('click'); | ||
// }); | ||
// } | ||
} | ||
root.tocbot = tocbot; | ||
window.tocbot = tocbot; | ||
return tocbot; | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 5 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
GitHub dependency
Supply chain riskContains a dependency which resolves to a GitHub URL. Dependencies fetched from GitHub specifiers are not immutable can be used to inject untrusted code or reduce the likelihood of a reproducible install.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
542407
1
40
17427
0
0
221
1
29
20
3
- Removedoptimizely-oui@github:optimizely/oui