Repository: fgnass/spin.js
Branch: master
Commit: 653e79c5ef1f
Files: 24
Total size: 60.2 KB
Directory structure:
gitextract_q8vr1fl3/
├── .gitattributes
├── .gitignore
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Gruntfile.cjs
├── LICENSE.md
├── README.md
├── SpinnerOptions.d.ts
├── package.json
├── rollup.config.js
├── site/
│ ├── CNAME
│ ├── assets/
│ │ ├── gh-fork-ribbon.css
│ │ ├── main.css
│ │ ├── prism.css
│ │ └── prism.js
│ ├── example/
│ │ ├── positioning.css
│ │ ├── positioning.html
│ │ └── positioning.js
│ ├── index.html
│ ├── index.js
│ └── serve.json
├── spin.css
├── spin.ts
└── tsconfig.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
# so documentation files won't cause project language to be shown as HTML
site/* linguist-documentation
================================================
FILE: .gitignore
================================================
/.grunt
/node_modules
/site/bundle.js
/site/spin.css
/site/spin.js
/site/spin.umd.js
/spin.js
/spin.d.ts
================================================
FILE: CHANGELOG.md
================================================
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [4.1.2] - 2024-07-19
### Changed
- Removed some dead code left over from version 3.x.
## [4.1.1] - 2021-09-01
### Changed
- Set package type to `module` to better support native ES module imports.
- Improved website design.
## [4.1.0] - 2019-10-22
### Added
- `spinner-line-shrink` animation preset.
## [4.0.0] - 2018-05-06
### Changed
- Switched from `requestAnimationFrame` back to CSS keyframe animations
for better performance.
- In order to preserve compatibility with the
`style-src 'self';` Content Security Policy, animations are now defined
via an external CSS file rather than inserted dynamically.
Add the following to your page to use one of the preset animations:
```html
<link rel="stylesheet" href="node_modules/spin.js/spin.css"/>
```
You can also define custom opacity animations in your own CSS file and
select them via the `animation` option.
### Fixed
- A transparent shadow is now set by default to resolve aliased lines in
certain browsers (issue [#355]).
### Removed
- `opacity` and `trail` options (define a custom opacity animation instead).
- Support for Internet Explorer 9 (it doesn't support keyframe animations).
- `fps` option (only used for IE 9).
## [3.1.0] - 2017-11-26
### Added
- Support for custom box-shadows with corrected positioning (issue [#35]).
- `fadeColor` option to customize the color that lines fade to (issue [#30]).
## [3.0.0] - 2017-11-09
### Added
- Support for Content Security Policy `style-src 'self';` option
(issue [#115] and issue [#229]).
- [CONTRIBUTING.md](CONTRIBUTING.md) file.
### Changed
- Rewritten in TypeScript.
- Replaced dynamic CSS keyframe animations with `requestAnimationFrame`.
- Unified animation logic in all browsers.
- Moved internal functions out of Spinner instance.
- Website now uses native range inputs rather than a polyfill, and doesn't
depend on jQuery.
- Distributed as a standard ES6 module (closes [#341]).
### Fixed
- Janky animation appearance in Microsoft Edge (issue [#342]).
- Missing line with trail set to 100 in Internet Explorer (issue [#327]).
- Spinner is not defined error in Angular (issue [#340]).
### Removed
- Useless `hwaccel` option.
- IE 6-8 support and VML fallback since it isn't needed for IE 9+.
- Minified files from bundle.
- jQuery plugin (closes [#325]).
- Bower/composer/component/spm support. Install from npm instead
(recommended), or save spin.js file in your repo.
Note: version 3.0 does not change the public Spinner API, so if you are
already using a module bundler such as Webpack or Rollup, upgrading should
be as easy as adding the following ES6 module import:
```javascript
import {Spinner} from 'spin.js';
```
## [2.3.2] - 2015-07-24
### Fixed
- Updated UMD header to protect against HTMLElement global pollution
(PR [#300]).
## [2.3.1] - 2015-06-15
### Changed
- There were multiple tagging issues that produced 2.1.3, 2.2.0, and 2.3.0.
In the spirit of SemVer, this release is now 2.3.1.
- The minified spin.min.js is now distributed in the repo, making Bower
usage easier (issue [#250]).
### Fixed
- Incorrect syntax in the example at the top of spin.js (PR [#294]).
### Removed
* Moot `version` property from Bower manifest (PR [#295]).
## [2.1.2] - 2015-05-28
### Changed
- Version 2.1.1 had a packaging error, so this release is now 2.1.2.
- Standard CSS attributes are now preferred over vendor ones if supported.
- Unified internal coding style across all files.
- Website now uses the latest version of jQuery from its 1.x branch.
- Updated documentation to note that the container element must use
relative positioning (issue [#292]).
### Added
- spm support (PR [#232]).
### Fixed
- All broken examples
- Bug on demo page where the direction setting wasn't reflected in the
option object.
## [2.1.0] - 2015-04-16
### Added
- `scale` option for resizing the spinner (PR [#287]).
- Support for importing on server without DOM (PR [#283]).
## [2.0.2] - 2015-01-02
### Fixed
- Use correct `require` call in jQuery plugin
### Removed
- Cleaned up unused code
## [2.0.1] - 2014-04-24
### Fixed
- Position offsets are now applied when instantiating spinner without
a target (issue [#218]).
## [2.0.0] - 2014-03-13
### Changed
- Spinner is now absolutely positioned at `top: 50%, left: 50%` by default.
- `top` and `left` options now require CSS units. For example, `top: 100`
must instead be written as `top: '100px'`.
- Spinner must now always be invoked as constructor.
## [1.3.3] - 2013-12-24
### Changed
- Created master branch and Grunt-based build process (issue [#189]).
## [1.3.2] - 2013-08-26
### Fixed
- SyntaxError in Chrome Canary (issue [#168]).
## [1.3.1] - 2013-08-19
### Added
- Support for multi-colored spinners (PR [#167]).
## [1.3.0] - 2013-04-02
### Added
- `direction` option to control the spinning direction (PR [#126]).
- jQuery plugin
### Changed
- Implemented UMD pattern to support AMD and CommonJS module loaders
- Use strict mode
## [1.2.8] - 2013-02-07
### Fixed
- 'Spinner' is undefined error in Internet Explorer 7 and 8 (issue [#78]).
## [1.2.7] - 2012-10-02
### Added
- `position` option to control the corresponding CSS property (issue [#98]).
- Trailing semicolon to support concatenation tools that don't know about
ASI (issue [#96] and issue [#99]).
## [1.2.6] - 2012-08-30
### Added
- `corners` option to control the border-radius (issue [#93]).
### Fixed
- Scroll bar appearing in wide target elements (issue [#74]).
- Invalid Argument error in Internet Explorer (issue [#77]).
- Broken spinner in Opera 12 (issue [#87]).
- Unexpected positioning when specifying `top` and `left` options as a
string (issue [#81] and issue [#90]).
## [1.2.5] - 2012-03-22
### Added
- `rotate` option (issue [#60]).
### Fixed
- Bug that prevented the VML from being displayed when Modernizr's
html5shiv was used (issue [#58]).
- The `constructor` property is now preserved (issue [#61]).
## [1.2.4] - 2012-02-28
### Added
- New config options: `top`, `left`, `zIndex`, and `className`.
## [1.2.3] - 2012-01-30
### Changed
- Disabled hardware acceleration by default to prevent disappearing
objects and flashing colors in Chrome and Safari (issue [#41] and
issue [#47]).
## [1.2.2] - 2011-11-08
### Fixed
- Cross-domain issue with the dynamically created stylesheet (issue [#36]).
## [1.2.1] - 2011-10-05
### Fixed
- Error when loading spinner in Internet Explorer 9 (issue [#31]).
## [1.2.0] - 2011-09-16
### Changed
- Calling `spin()` now invokes `stop()` first (issue [#28]).
- The `new` operator is now optional (issue [#14]).
- Improved accessibility by adding `role="progressbar"`.
### Fixed
- Implemented workaround for negative margin bug in Internet Explorer
(issue [#27]).
## [1.1.0] - 2011-09-06
### Changed
- Optimized the code for gzip compression. While the minified version
got slightly larger, the zipped version now only weighs 1.7K.
### Fixed
- Animation occasionally got out of sync in mobile Safari and Android's
built-in WebKit (issue [#12]).
- Spinner was misplaced when the target element had a non-zero padding
(issue [#23]).
## [1.0.0] - 2011-08-16
- Initial release
[4.1.2]: https://github.com/fgnass/spin.js/compare/4.1.1...4.1.2
[4.1.1]: https://github.com/fgnass/spin.js/compare/4.1.0...4.1.1
[4.1.0]: https://github.com/fgnass/spin.js/compare/4.0.0...4.1.0
[4.0.0]: https://github.com/fgnass/spin.js/compare/3.1.0...4.0.0
[3.1.0]: https://github.com/fgnass/spin.js/compare/3.0.0...3.1.0
[3.0.0]: https://github.com/fgnass/spin.js/compare/2.3.2...3.0.0
[2.3.2]: https://github.com/fgnass/spin.js/compare/2.3.1...2.3.2
[2.3.1]: https://github.com/fgnass/spin.js/compare/2.1.2...2.3.1
[2.1.2]: https://github.com/fgnass/spin.js/compare/2.1.0...2.1.2
[2.1.0]: https://github.com/fgnass/spin.js/compare/2.0.2...2.1.0
[2.0.2]: https://github.com/fgnass/spin.js/compare/2.0.1...2.0.2
[2.0.1]: https://github.com/fgnass/spin.js/compare/2.0.0...2.0.1
[2.0.0]: https://github.com/fgnass/spin.js/compare/1.3.3...2.0.0
[1.3.3]: https://github.com/fgnass/spin.js/compare/1.3.2...1.3.3
[1.3.2]: https://github.com/fgnass/spin.js/compare/1.3.1...1.3.2
[1.3.1]: https://github.com/fgnass/spin.js/compare/1.3.0...1.3.1
[1.3.0]: https://github.com/fgnass/spin.js/compare/1.2.8...1.3.0
[1.2.8]: https://github.com/fgnass/spin.js/compare/1.2.7...1.2.8
[1.2.7]: https://github.com/fgnass/spin.js/compare/1.2.6...1.2.7
[1.2.6]: https://github.com/fgnass/spin.js/compare/1.2.5...1.2.6
[1.2.5]: https://github.com/fgnass/spin.js/compare/1.2.4...1.2.5
[1.2.4]: https://github.com/fgnass/spin.js/compare/1.2.3...1.2.4
[1.2.3]: https://github.com/fgnass/spin.js/compare/1.2.2...1.2.3
[1.2.2]: https://github.com/fgnass/spin.js/compare/1.2.1...1.2.2
[1.2.1]: https://github.com/fgnass/spin.js/compare/1.2.0...1.2.1
[1.2.0]: https://github.com/fgnass/spin.js/compare/1.1.0...1.2.0
[1.1.0]: https://github.com/fgnass/spin.js/compare/1.0.0...1.1.0
[1.0.0]: https://github.com/fgnass/spin.js/tree/1.0.0
[#355]: https://github.com/fgnass/spin.js/issues/355
[#342]: https://github.com/fgnass/spin.js/issues/342
[#341]: https://github.com/fgnass/spin.js/issues/341
[#340]: https://github.com/fgnass/spin.js/issues/340
[#327]: https://github.com/fgnass/spin.js/issues/327
[#325]: https://github.com/fgnass/spin.js/issues/325
[#300]: https://github.com/fgnass/spin.js/pull/300
[#295]: https://github.com/fgnass/spin.js/pull/295
[#294]: https://github.com/fgnass/spin.js/pull/294
[#292]: https://github.com/fgnass/spin.js/issues/292
[#287]: https://github.com/fgnass/spin.js/pull/287
[#283]: https://github.com/fgnass/spin.js/pull/283
[#250]: https://github.com/fgnass/spin.js/issues/250
[#232]: https://github.com/fgnass/spin.js/pull/232
[#229]: https://github.com/fgnass/spin.js/issues/229
[#218]: https://github.com/fgnass/spin.js/issues/218
[#189]: https://github.com/fgnass/spin.js/issues/189
[#168]: https://github.com/fgnass/spin.js/issues/168
[#167]: https://github.com/fgnass/spin.js/pull/167
[#126]: https://github.com/fgnass/spin.js/pull/126
[#115]: https://github.com/fgnass/spin.js/issues/115
[#99]: https://github.com/fgnass/spin.js/issues/99
[#98]: https://github.com/fgnass/spin.js/issues/98
[#96]: https://github.com/fgnass/spin.js/issues/96
[#93]: https://github.com/fgnass/spin.js/issues/93
[#90]: https://github.com/fgnass/spin.js/issues/90
[#87]: https://github.com/fgnass/spin.js/issues/87
[#81]: https://github.com/fgnass/spin.js/issues/81
[#78]: https://github.com/fgnass/spin.js/issues/78
[#77]: https://github.com/fgnass/spin.js/issues/77
[#74]: https://github.com/fgnass/spin.js/issues/74
[#61]: https://github.com/fgnass/spin.js/issues/61
[#60]: https://github.com/fgnass/spin.js/issues/60
[#58]: https://github.com/fgnass/spin.js/issues/58
[#47]: https://github.com/fgnass/spin.js/issues/47
[#41]: https://github.com/fgnass/spin.js/issues/41
[#36]: https://github.com/fgnass/spin.js/issues/36
[#35]: https://github.com/fgnass/spin.js/issues/35
[#31]: https://github.com/fgnass/spin.js/issues/31
[#30]: https://github.com/fgnass/spin.js/issues/30
[#28]: https://github.com/fgnass/spin.js/issues/28
[#27]: https://github.com/fgnass/spin.js/issues/27
[#23]: https://github.com/fgnass/spin.js/issues/23
[#14]: https://github.com/fgnass/spin.js/issues/14
[#12]: https://github.com/fgnass/spin.js/issues/12
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing
After cloning the repository, run `npm install` to install development dependencies and compile the project.
Then run `npm start` to start a static file server for viewing the site.
After editing any TypeScript files, run `npm run prepare` to compile TypeScript and create a new bundle for the site.
## Workflow to release a new version
Run `npm version [<newversion> | major | minor | patch]` to bump the package version and create a new version commit and tag.
Then run `npm publish` to build and publish the new version.
Finally, run `npm run gh-pages` and `git push --tags` to update the website and repository.
================================================
FILE: Gruntfile.cjs
================================================
module.exports = function(grunt) {
grunt.initConfig({
copy: {
js: {
files: [
{ src: ['spin.js', 'spin.css'], dest: 'site/' }
]
}
},
'gh-pages': {
release: {
options: {
base: 'site',
message: 'automatic commit'
},
src: '**/*'
}
}
});
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-gh-pages');
grunt.registerTask('default', ['copy']);
};
================================================
FILE: LICENSE.md
================================================
The MIT License
===============
Copyright (c) 2011-2018 Felix Gnass [fgnass at gmail dot com]
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
================================================
FILE: README.md
================================================
# spin.js [](http://js.org)
An animated loading spinner
* No images
* No dependencies
* Highly configurable
* Resolution independent
* Uses CSS keyframe animations
* Works in all major browsers
* Includes TypeScript definitions
* Distributed as a native ES6 module
* MIT License
## Installation
`npm install spin.js`
## Usage
### CSS
```html
<link rel="stylesheet" href="node_modules/spin.js/spin.css">
```
### TypeScript or JavaScript
```javascript
import {Spinner} from 'spin.js';
var target = document.getElementById('foo');
new Spinner({color:'#fff', lines: 12}).spin(target);
```
For an interactive demo and a list of all supported options please refer to the [project's homepage](https://spin.js.org).
================================================
FILE: SpinnerOptions.d.ts
================================================
export interface SpinnerOptions {
/**
* The number of lines to draw
*/
lines?: number;
/**
* The length of each line
*/
length?: number;
/**
* The line thickness
*/
width?: number;
/**
* The radius of the inner circle
*/
radius?: number;
/**
* Scales overall size of the spinner
*/
scale?: number;
/**
* Corner roundness (0..1)
*/
corners?: number;
/**
* A CSS color string, or array of strings to set the line color
*/
color?: string | string[];
/**
* A CSS color string, or array of strings to set the color that lines will fade to.
* Defaults to transparent.
*/
fadeColor?: string | string[];
/**
* The animation name used for the spinner lines. Defaults to 'spinner-line-fade-default'.
*/
animation?: string;
/**
* The rotation offset
*/
rotate?: number;
/**
* 1: clockwise, -1: counterclockwise
*/
direction?: number;
/**
* Rounds per second
*/
speed?: number;
/**
* The z-index (defaults to 2000000000)
*/
zIndex?: number;
/**
* The CSS class to assign to the spinner
*/
className?: string;
/**
* Top position relative to parent (defaults to 50%)
*/
top?: string;
/**
* Left position relative to parent (defaults to 50%)
*/
left?: string;
/**
* Whether to render the default shadow (boolean).
* A string can be used to set a custom box-shadow value.
*/
shadow?: boolean | string;
/**
* Element positioning
*/
position?: string;
}
================================================
FILE: package.json
================================================
{
"name": "spin.js",
"version": "4.1.2",
"description": "A spinning activity indicator",
"files": [
"spin.css",
"spin.d.ts",
"spin.js",
"SpinnerOptions.d.ts"
],
"type": "module",
"main": "spin.js",
"types": "spin.d.ts",
"author": "Felix Gnass <fgnass@gmail.com>",
"contributors": [
"Theodore Brown (https://github.com/theodorejb)",
"Timothy Gu <timothygu99@gmail.com>"
],
"license": "MIT",
"repository": {
"type": "git",
"url": "git://github.com/fgnass/spin.js.git"
},
"keywords": [
"css",
"progress indicator",
"spin",
"spinner"
],
"scripts": {
"prepare": "tsc && grunt --gruntfile Gruntfile.cjs && rollup -c",
"gh-pages": "grunt gh-pages --gruntfile Gruntfile.cjs",
"start": "serve site/"
},
"devDependencies": {
"grunt": "^1.6.1",
"grunt-contrib-copy": "^1.0.0",
"grunt-gh-pages": "^4.0.0",
"rollup": "^4.18.1",
"serve": "^14.2.3",
"typescript": "^5.5.3"
}
}
================================================
FILE: rollup.config.js
================================================
export default [
{
input: 'spin.js',
output: {
file: 'site/spin.umd.js',
format: 'umd',
name: 'Spin',
},
},
{
input: 'site/index.js',
output: {
file: 'site/bundle.js',
format: 'iife'
}
}
];
================================================
FILE: site/CNAME
================================================
spin.js.org
================================================
FILE: site/assets/gh-fork-ribbon.css
================================================
/*!
* "Fork me on GitHub" CSS ribbon v0.2.3 | MIT License
* https://github.com/simonwhitaker/github-fork-ribbon-css
*/
.github-fork-ribbon {
width: 12.1em;
height: 12.1em;
position: absolute;
overflow: hidden;
top: 0;
right: 0;
z-index: 9999;
pointer-events: none;
font-size: 13px;
text-decoration: none;
text-indent: -999999px;
}
.github-fork-ribbon.fixed {
position: fixed;
}
.github-fork-ribbon:hover, .github-fork-ribbon:active {
background-color: rgba(0, 0, 0, 0.0);
}
.github-fork-ribbon:before, .github-fork-ribbon:after {
/* The right and left classes determine the side we attach our banner to */
position: absolute;
display: block;
width: 15.38em;
height: 1.54em;
top: 3.23em;
right: -3.23em;
box-sizing: content-box;
transform: rotate(45deg);
}
.github-fork-ribbon:before {
content: "";
/* Add a bit of padding to give some substance outside the "stitching" */
padding: .38em 0;
/* Set the base colour */
background-color: #39922c;
/* Set a gradient: transparent black at the top to almost-transparent black at the bottom */
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15));
/* Add a drop shadow */
box-shadow: 0 .15em .23em 0 rgba(0, 0, 0, 0.3);
pointer-events: auto;
}
.github-fork-ribbon:after {
/* Set the text from the data-ribbon attribute */
content: attr(data-ribbon);
/* Set the text properties */
color: #fff;
font: 700 1em "Helvetica Neue", Helvetica, Arial, sans-serif;
line-height: 1.54em;
text-decoration: none;
text-shadow: 0 -.08em rgba(0, 0, 0, 0.5);
text-align: center;
text-indent: 0;
/* Set the layout properties */
padding: .15em 0;
margin: .15em 0;
/* Add "stitching" effect */
border-width: .08em 0;
border-style: dotted;
border-color: #fff;
border-color: rgba(255, 255, 255, 0.7);
}
.github-fork-ribbon.left-top, .github-fork-ribbon.left-bottom {
right: auto;
left: 0;
}
.github-fork-ribbon.left-bottom, .github-fork-ribbon.right-bottom {
top: auto;
bottom: 0;
}
.github-fork-ribbon.left-top:before, .github-fork-ribbon.left-top:after, .github-fork-ribbon.left-bottom:before, .github-fork-ribbon.left-bottom:after {
right: auto;
left: -3.23em;
}
.github-fork-ribbon.left-bottom:before, .github-fork-ribbon.left-bottom:after, .github-fork-ribbon.right-bottom:before, .github-fork-ribbon.right-bottom:after {
top: auto;
bottom: 3.23em;
}
.github-fork-ribbon.left-top:before, .github-fork-ribbon.left-top:after, .github-fork-ribbon.right-bottom:before, .github-fork-ribbon.right-bottom:after {
transform: rotate(-45deg);
}
================================================
FILE: site/assets/main.css
================================================
html, body {
margin: 0;
}
html {
background: url(bg.png);
}
body {
color: #333;
font-family: Helvetica, Arial, sans-serif;
font-size: 16px;
}
ul {
padding: 0 0 0 20px;
}
#content {
max-width: 800px;
line-height: 1.4em;
padding: 0 40px 40px;
text-shadow: 0px 1px 0px #fff;
}
#content img {
max-width: 100%;
}
#footer {
background: #202020;
overflow: hidden;
color: #888;
font-size: 12px;
padding: 20px 0 100px 50px;
position: relative;
}
#footer:before {
content: '';
display: block;
box-shadow: 0 0 10px #000;
height: 10px;
position: absolute;
left: 0;
top: -10px;
width: 100%;
}
#footer a.github {
background: url(github.svg) no-repeat;
background-size: 100%;
width: 144px;
height: 72px;
text-indent: -999em;
position: absolute;
bottom: 30px;
right: 30px;
}
a {
color: #333;
}
a:hover {
color: #000;
}
label {
font-size: 14px;
vertical-align: top;
}
#opts {
background: #fff;
padding: 10px;
margin-top: 20px;
box-sizing: border-box;
}
#opts label {
display: inline-block;
line-height: 25px;
width: 80px;
}
h1 {
font-size: 100px;
}
h1, h2, h3, #download a {
font-family: 'Amaranth', sans-serif;
}
h2 {
font-size: 28px;
margin: 30px 0 20px;
}
h3 {
margin: 30px 0 10px 0;
}
.mid_col {
width: 20px;
}
#opts, #preview {
width: 325px;
border-radius: 10px;
}
#preview {
position: relative;
background: #333;
height: 325px;
}
@media screen and (min-width: 545px) {
h1 {
font-size: 150px;
}
}
@media screen and (min-width: 745px) {
h1 {
font-size: 175px;
}
#opts, .mid_col, #preview {
display: table-cell;
}
#opts {
width: auto;
}
#preview {
height: 100%;
}
}
@media screen and (min-width: 800px) {
#preview {
width: 375px;
}
}
@media screen and (min-width: 900px) {
h1 {
font-size: 200px;
}
#content {
margin-left: 100px;
}
}
@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
/* styling fixes for IE 10 and IE 11 only */
#opts input[type="range"] {
padding: 7px;
width: 150px;
}
#opts, .mid_col, #preview {
display: inline-block;
}
#preview {
height: 400px;
}
}
a.button {
display: inline-block;
background: #56ba4a;
border: 3px solid #59a24f;
color: #fff;
border-radius: 5px;
font-family: 'Amaranth', sans-serif;
font-size: 24px;
padding: 10px 30px;
text-decoration: none;
text-shadow: 1px 1px 1px #59a24f;
box-shadow: 2px 2px 4px rgba(0,0,0,0.2);
margin: 10px 20px 0 0;
transition: all 0.25s ease;
}
a.button:hover {
background: #2f8325;
box-shadow: none;
}
.authors {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(275px, 1fr));
grid-gap: 50px;
}
.contact {
background-color: #e1e1e1;
padding: 24px;
text-align: center;
box-shadow: 2px 2px 10px #bbb;
}
.contact h3 {
margin: 20px 0;
}
.contact p {
margin-bottom: 0;
}
.contact img {
border-radius: 50%;
}
================================================
FILE: site/assets/prism.css
================================================
/* PrismJS 1.20.0
https://prismjs.com/download.html#themes=prism-okaidia&languages=markup+css+clike+javascript */
/**
* okaidia theme for JavaScript, CSS and HTML
* Loosely based on Monokai textmate theme by http://www.monokai.nl/
* @author ocodia
*/
code[class*="language-"],
pre[class*="language-"] {
color: #f8f8f2;
background: none;
text-shadow: 0 1px rgba(0, 0, 0, 0.3);
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
font-size: 1em;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
border-radius: 0.3em;
}
:not(pre) > code[class*="language-"],
pre[class*="language-"] {
background: #272822;
}
/* Inline code */
:not(pre) > code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: #8292a2;
}
.token.punctuation {
color: #f8f8f2;
}
.token.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.constant,
.token.symbol,
.token.deleted {
color: #f92672;
}
.token.boolean,
.token.number {
color: #ae81ff;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #a6e22e;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string,
.token.variable {
color: #f8f8f2;
}
.token.atrule,
.token.attr-value,
.token.function,
.token.class-name {
color: #e6db74;
}
.token.keyword {
color: #66d9ef;
}
.token.regex,
.token.important {
color: #fd971f;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}
================================================
FILE: site/assets/prism.js
================================================
/* PrismJS 1.20.0
https://prismjs.com/download.html#themes=prism-okaidia&languages=markup+css+clike+javascript */
var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(u){var c=/\blang(?:uage)?-([\w-]+)\b/i,n=0,M={manual:u.Prism&&u.Prism.manual,disableWorkerMessageHandler:u.Prism&&u.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof W?new W(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,"&").replace(/</g,"<").replace(/\u00a0/g," ")},type:function(e){return Object.prototype.toString.call(e).slice(8,-1)},objId:function(e){return e.__id||Object.defineProperty(e,"__id",{value:++n}),e.__id},clone:function t(e,r){var a,n;switch(r=r||{},M.util.type(e)){case"Object":if(n=M.util.objId(e),r[n])return r[n];for(var i in a={},r[n]=a,e)e.hasOwnProperty(i)&&(a[i]=t(e[i],r));return a;case"Array":return n=M.util.objId(e),r[n]?r[n]:(a=[],r[n]=a,e.forEach(function(e,n){a[n]=t(e,r)}),a);default:return e}},getLanguage:function(e){for(;e&&!c.test(e.className);)e=e.parentElement;return e?(e.className.match(c)||[,"none"])[1].toLowerCase():"none"},currentScript:function(){if("undefined"==typeof document)return null;if("currentScript"in document)return document.currentScript;try{throw new Error}catch(e){var n=(/at [^(\r\n]*\((.*):.+:.+\)$/i.exec(e.stack)||[])[1];if(n){var t=document.getElementsByTagName("script");for(var r in t)if(t[r].src==n)return t[r]}return null}},isActive:function(e,n,t){for(var r="no-"+n;e;){var a=e.classList;if(a.contains(n))return!0;if(a.contains(r))return!1;e=e.parentElement}return!!t}},languages:{extend:function(e,n){var t=M.util.clone(M.languages[e]);for(var r in n)t[r]=n[r];return t},insertBefore:function(t,e,n,r){var a=(r=r||M.languages)[t],i={};for(var l in a)if(a.hasOwnProperty(l)){if(l==e)for(var o in n)n.hasOwnProperty(o)&&(i[o]=n[o]);n.hasOwnProperty(l)||(i[l]=a[l])}var s=r[t];return r[t]=i,M.languages.DFS(M.languages,function(e,n){n===s&&e!=t&&(this[e]=i)}),i},DFS:function e(n,t,r,a){a=a||{};var i=M.util.objId;for(var l in n)if(n.hasOwnProperty(l)){t.call(n,l,n[l],r||l);var o=n[l],s=M.util.type(o);"Object"!==s||a[i(o)]?"Array"!==s||a[i(o)]||(a[i(o)]=!0,e(o,t,l,a)):(a[i(o)]=!0,e(o,t,null,a))}}},plugins:{},highlightAll:function(e,n){M.highlightAllUnder(document,e,n)},highlightAllUnder:function(e,n,t){var r={callback:t,container:e,selector:'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'};M.hooks.run("before-highlightall",r),r.elements=Array.prototype.slice.apply(r.container.querySelectorAll(r.selector)),M.hooks.run("before-all-elements-highlight",r);for(var a,i=0;a=r.elements[i++];)M.highlightElement(a,!0===n,r.callback)},highlightElement:function(e,n,t){var r=M.util.getLanguage(e),a=M.languages[r];e.className=e.className.replace(c,"").replace(/\s+/g," ")+" language-"+r;var i=e.parentElement;i&&"pre"===i.nodeName.toLowerCase()&&(i.className=i.className.replace(c,"").replace(/\s+/g," ")+" language-"+r);var l={element:e,language:r,grammar:a,code:e.textContent};function o(e){l.highlightedCode=e,M.hooks.run("before-insert",l),l.element.innerHTML=l.highlightedCode,M.hooks.run("after-highlight",l),M.hooks.run("complete",l),t&&t.call(l.element)}if(M.hooks.run("before-sanity-check",l),!l.code)return M.hooks.run("complete",l),void(t&&t.call(l.element));if(M.hooks.run("before-highlight",l),l.grammar)if(n&&u.Worker){var s=new Worker(M.filename);s.onmessage=function(e){o(e.data)},s.postMessage(JSON.stringify({language:l.language,code:l.code,immediateClose:!0}))}else o(M.highlight(l.code,l.grammar,l.language));else o(M.util.encode(l.code))},highlight:function(e,n,t){var r={code:e,grammar:n,language:t};return M.hooks.run("before-tokenize",r),r.tokens=M.tokenize(r.code,r.grammar),M.hooks.run("after-tokenize",r),W.stringify(M.util.encode(r.tokens),r.language)},tokenize:function(e,n){var t=n.rest;if(t){for(var r in t)n[r]=t[r];delete n.rest}var a=new i;return I(a,a.head,e),function e(n,t,r,a,i,l){for(var o in r)if(r.hasOwnProperty(o)&&r[o]){var s=r[o];s=Array.isArray(s)?s:[s];for(var u=0;u<s.length;++u){if(l&&l.cause==o+","+u)return;var c=s[u],g=c.inside,f=!!c.lookbehind,h=!!c.greedy,d=0,v=c.alias;if(h&&!c.pattern.global){var p=c.pattern.toString().match(/[imsuy]*$/)[0];c.pattern=RegExp(c.pattern.source,p+"g")}for(var m=c.pattern||c,y=a.next,k=i;y!==t.tail&&!(l&&k>=l.reach);k+=y.value.length,y=y.next){var b=y.value;if(t.length>n.length)return;if(!(b instanceof W)){var x=1;if(h&&y!=t.tail.prev){m.lastIndex=k;var w=m.exec(n);if(!w)break;var A=w.index+(f&&w[1]?w[1].length:0),P=w.index+w[0].length,S=k;for(S+=y.value.length;S<=A;)y=y.next,S+=y.value.length;if(S-=y.value.length,k=S,y.value instanceof W)continue;for(var E=y;E!==t.tail&&(S<P||"string"==typeof E.value);E=E.next)x++,S+=E.value.length;x--,b=n.slice(k,S),w.index-=k}else{m.lastIndex=0;var w=m.exec(b)}if(w){f&&(d=w[1]?w[1].length:0);var A=w.index+d,O=w[0].slice(d),P=A+O.length,L=b.slice(0,A),N=b.slice(P),j=k+b.length;l&&j>l.reach&&(l.reach=j);var C=y.prev;L&&(C=I(t,C,L),k+=L.length),z(t,C,x);var _=new W(o,g?M.tokenize(O,g):O,v,O);y=I(t,C,_),N&&I(t,y,N),1<x&&e(n,t,r,y.prev,k,{cause:o+","+u,reach:j})}}}}}}(e,a,n,a.head,0),function(e){var n=[],t=e.head.next;for(;t!==e.tail;)n.push(t.value),t=t.next;return n}(a)},hooks:{all:{},add:function(e,n){var t=M.hooks.all;t[e]=t[e]||[],t[e].push(n)},run:function(e,n){var t=M.hooks.all[e];if(t&&t.length)for(var r,a=0;r=t[a++];)r(n)}},Token:W};function W(e,n,t,r){this.type=e,this.content=n,this.alias=t,this.length=0|(r||"").length}function i(){var e={value:null,prev:null,next:null},n={value:null,prev:e,next:null};e.next=n,this.head=e,this.tail=n,this.length=0}function I(e,n,t){var r=n.next,a={value:t,prev:n,next:r};return n.next=a,r.prev=a,e.length++,a}function z(e,n,t){for(var r=n.next,a=0;a<t&&r!==e.tail;a++)r=r.next;(n.next=r).prev=n,e.length-=a}if(u.Prism=M,W.stringify=function n(e,t){if("string"==typeof e)return e;if(Array.isArray(e)){var r="";return e.forEach(function(e){r+=n(e,t)}),r}var a={type:e.type,content:n(e.content,t),tag:"span",classes:["token",e.type],attributes:{},language:t},i=e.alias;i&&(Array.isArray(i)?Array.prototype.push.apply(a.classes,i):a.classes.push(i)),M.hooks.run("wrap",a);var l="";for(var o in a.attributes)l+=" "+o+'="'+(a.attributes[o]||"").replace(/"/g,""")+'"';return"<"+a.tag+' class="'+a.classes.join(" ")+'"'+l+">"+a.content+"</"+a.tag+">"},!u.document)return u.addEventListener&&(M.disableWorkerMessageHandler||u.addEventListener("message",function(e){var n=JSON.parse(e.data),t=n.language,r=n.code,a=n.immediateClose;u.postMessage(M.highlight(r,M.languages[t],t)),a&&u.close()},!1)),M;var e=M.util.currentScript();function t(){M.manual||M.highlightAll()}if(e&&(M.filename=e.src,e.hasAttribute("data-manual")&&(M.manual=!0)),!M.manual){var r=document.readyState;"loading"===r||"interactive"===r&&e&&e.defer?document.addEventListener("DOMContentLoaded",t):window.requestAnimationFrame?window.requestAnimationFrame(t):window.setTimeout(t,16)}return M}(_self);"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism);
Prism.languages.markup={comment:/<!--[\s\S]*?-->/,prolog:/<\?[\s\S]+?\?>/,doctype:{pattern:/<!DOCTYPE(?:[^>"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|<!--(?:[^-]|-(?!->))*-->)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^<!|>$|[[\]]/,"doctype-tag":/^DOCTYPE/,name:/[^\s<>'"]+/}},cdata:/<!\[CDATA\[[\s\S]*?]]>/i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.languages.markup.doctype.inside["internal-subset"].inside=Prism.languages.markup,Prism.hooks.add("wrap",function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))}),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(a,e){var s={};s["language-"+e]={pattern:/(^<!\[CDATA\[)[\s\S]+?(?=\]\]>$)/i,lookbehind:!0,inside:Prism.languages[e]},s.cdata=/^<!\[CDATA\[|\]\]>$/i;var n={"included-cdata":{pattern:/<!\[CDATA\[[\s\S]*?\]\]>/i,inside:s}};n["language-"+e]={pattern:/[\s\S]+/,inside:Prism.languages[e]};var t={};t[a]={pattern:RegExp("(<__[^]*?>)(?:<!\\[CDATA\\[(?:[^\\]]|\\](?!\\]>))*\\]\\]>|(?!<!\\[CDATA\\[)[^])*?(?=</__>)".replace(/__/g,function(){return a}),"i"),lookbehind:!0,greedy:!0,inside:n},Prism.languages.insertBefore("markup","cdata",t)}}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup,Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.ssml=Prism.languages.xml,Prism.languages.atom=Prism.languages.xml,Prism.languages.rss=Prism.languages.xml;
!function(e){var s=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-]+[\s\S]*?(?:;|(?=\s*\{))/,inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\((?!\s*\))\s*)(?:[^()]|\((?:[^()]|\([^()]*\))*\))+?(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+s.source+"|(?:[^\\\\\r\n()\"']|\\\\[^])*)\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+s.source+"$"),alias:"url"}}},selector:RegExp("[^{}\\s](?:[^{};\"']|"+s.source+")*?(?=\\s*\\{)"),string:{pattern:s,greedy:!0},property:/[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,important:/!important\b/i,function:/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:,]/},e.languages.css.atrule.inside.rest=e.languages.css;var t=e.languages.markup;t&&(t.tag.addInlined("style","css"),e.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:t.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:e.languages.css}},alias:"language-css"}},t.tag))}(Prism);
Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|interface|extends|implements|trait|instanceof|new)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,boolean:/\b(?:true|false)\b/,function:/\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/};
Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])[_$A-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\.(?:prototype|constructor))/,lookbehind:!0}],keyword:[{pattern:/((?:^|})\s*)(?:catch|finally)\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|(?:get|set)(?=\s*[\[$\w\xA0-\uFFFF])|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],number:/\b(?:(?:0[xX](?:[\dA-Fa-f](?:_[\dA-Fa-f])?)+|0[bB](?:[01](?:_[01])?)+|0[oO](?:[0-7](?:_[0-7])?)+)n?|(?:\d(?:_\d)?)+n|NaN|Infinity)\b|(?:\b(?:\d(?:_\d)?)+\.?(?:\d(?:_\d)?)*|\B\.(?:\d(?:_\d)?)+)(?:[Ee][+-]?(?:\d(?:_\d)?)+)?/,function:/#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*]|\\.|[^/\\\[\r\n])+\/[gimyus]{0,6}(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,lookbehind:!0,greedy:!0},"function-variable":{pattern:/#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)?\s*\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*=>)/i,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\[\s\S]|\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}|(?!\${)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\${|}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&Prism.languages.markup.tag.addInlined("script","javascript"),Prism.languages.js=Prism.languages.javascript;
================================================
FILE: site/example/positioning.css
================================================
body {
font-family: Helvetica, Arial, sans-serif;
font-size: 16px;
padding: 0;
margin: 0;
}
div {
position: relative;
border-radius: 10px;
}
#target1 {
background: #aaa url(../assets/crosshair.gif) center center no-repeat;
width: 99px;
height: 99px;
padding: 15px;
}
#target2 {
background: #bbb url(../assets/crosshair.gif) center center no-repeat;
width: 99px;
height: 99px;
padding: 15px;
}
#target3 {
background: #ccc url(../assets/crosshair.gif) center center no-repeat;
width: 99px;
height: 99px;
padding: 15px;
}
#target4 {
background: #ddd;
padding: 15px;
width: 375px;
height: 66px;
padding: 66px 38px;
}
@keyframes spinner-line-fade-custom {
0%, 59%, 100% {
opacity: 0.25; /* minimum opacity */
}
60% {
opacity: 1;
}
}
================================================
FILE: site/example/positioning.html
================================================
<!DOCTYPE html>
<html>
<head>
<title>spin.js</title>
<link rel="stylesheet" type="text/css" href="../spin.css"/>
<link rel="stylesheet" type="text/css" href="positioning.css"/>
</head>
<body>
<div id="target1"></div>
<div id="target2"></div>
<div id="target3"></div>
<div id="target4"><img src="../assets/browsers.png"></div>
<script type="module" src="positioning.js"></script>
</body>
</html>
================================================
FILE: site/example/positioning.js
================================================
import { Spinner } from "../spin.js";
new Spinner({ radius: 10, length: 40, color: ['red', 'green', 'blue'] })
.spin(document.getElementById('target1'));
new Spinner({ radius: 40, length: 10 }).spin(document.getElementById('target2'));
new Spinner({ top: 0, left: 0 }).spin(document.getElementById('target3'));
new Spinner({ radius: 32, length: 0, width: 10, color: '#c13d3d', animation: 'spinner-line-fade-custom' })
.spin(document.getElementById('target4'));
================================================
FILE: site/index.html
================================================
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>spin.js</title>
<meta name="title" content="Animated activity indicator">
<meta name="description" content="A highly configurable JavaScript/CSS spinner that can be used as a resolution-independent loading indicator.">
<meta name="viewport" content="width=device-width">
<meta property="og:image" content="https://spin.js.org/assets/preview.png"/>
<link rel="shortcut icon" href="assets/favicon.ico">
<link href="spin.css" rel="stylesheet">
<link href="assets/gh-fork-ribbon.css" rel="stylesheet">
<link href="assets/main.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Amaranth:400,700" rel="stylesheet">
<link href="assets/prism.css" rel="stylesheet">
</head>
<body>
<a class="github-fork-ribbon right-top" href="https://github.com/fgnass/spin.js" data-ribbon="Fork me on GitHub" title="Fork me on GitHub">Fork me on GitHub</a>
<div id="content">
<h1>spin.js</h1>
<div id="download">
<a href="spin.js" class="button">spin.js (ESM)</a>
<a href="spin.umd.js" class="button">spin.umd.js</a>
<a href="spin.css" class="button">spin.css</a>
</div>
<h2>Example</h2>
<div id="example">
<div id="preview"></div>
<div class="mid_col"></div>
<form id="opts">
<label>Lines:</label><input type="range" name="lines" min="5" max="20" step="1" value="13"><br>
<label>Length:</label><input type="range" name="length" min="0" max="80" value="38"><br>
<label>Width:</label><input type="range" name="width" min="2" max="52" value="17"><br>
<label>Radius:</label><input type="range" name="radius" min="0" max="84" value="45"><br>
<label>Scale:</label><input type="range" name="scale" min="0.05" max="4.0" step="0.05" value="1.0"><br>
<label>Corners:</label><input type="range" name="corners" min="0" max="1" step="0.1" value="1"><br>
<label>Speed:</label><input type="range" name="speed" min="0.5" max="2.2" step="0.1" value="1"><br>
<label>Rotate:</label><input type="range" name="rotate" min="0" max="90" value="0"><br>
<label>Animation:</label>
<select class="string" name="animation">
<option value="spinner-line-fade-default">spinner-line-fade-default</option>
<option value="spinner-line-fade-quick" selected>spinner-line-fade-quick</option>
<option value="spinner-line-fade-more">spinner-line-fade-more</option>
<option value="spinner-line-shrink">spinner-line-shrink</option>
</select>
<br>
<label>Direction:</label>
<select name="direction">
<option value="1">Clockwise</option>
<option value="-1">Counterclockwise</option>
</select>
<br>
<label>Color:</label><input class="string" type="color" name="color" value="#ffffff"><br>
<label>Fade color:</label><input class="string" type="text" name="fadeColor" value="transparent"><br>
<label>↕:</label><input class="percent" type="range" name="top" min="0" max="100" value="50"><br>
<label>↔:</label><input class="percent" type="range" name="left" min="0" max="100" value="50"><br>
<label>Shadow:</label><input class="string" type="text" name="shadow" value="0 0 1px transparent"><br>
</form>
</div>
<p>
<input type="checkbox" id="share">
<label for="share">
<b>Share it!</b> If checked, the option values will be stored in the URL so that you can easily share your settings.
</label>
</p>
<h2>Features</h2>
<ul>
<li>No images</li>
<li>No dependencies</li>
<li>Highly configurable</li>
<li>Resolution independent</li>
<li>Uses CSS keyframe animations</li>
<li>Works in all major browsers</li>
<li>Includes TypeScript definitions</li>
<li>Distributed as a native ECMAScript module</li>
<li>MIT License</li>
</ul>
<p>
Spin.js dynamically creates spinning activity indicators that can be used as
a resolution-independent replacement for loading GIFs.
</p>
<h2>Installation</h2>
<p>
Run <code>npm install spin.js</code>, or save the spin.js and spin.css files in your repository.
</p>
<h3>JS bundling</h3>
<p>
For best performance and compatibility, it is recommended to use a module bundler such as
<a href="https://parceljs.org/">Parcel</a>, <a href="https://rollupjs.org/">Rollup</a>,
or <a href="https://webpack.js.org/">Webpack</a> to create a production-ready code bundle.
However, in modern browsers it is also possible to directly load the module via a script tag:
</p>
<pre>
<code class="language-html"><script type="module" src="node_modules/spin.js/spin.js"></script></code>
</pre>
<p>
If for some reason you can't use ECMAScript modules or a module bundler,
download <a href="spin.umd.js">spin.umd.js</a> and save it in your repository.
The UMD script can be used as follows:
</p>
<pre>
<code class="language-js">var spinner = new Spin.Spinner(opts).spin(target);</code>
</pre>
<p>
Note that the UMD version is only available as a temporary workaround.
Longer term it is recommended to migrate to the standard ECMAScript module.
</p>
<h3>CSS</h3>
<p>
Load the spin.css file to include the default animation presets.
You could alternatively create a custom CSS keyframe animation (in your own CSS file)
and set it using the <code>animation</code> property.
</p>
<p>
Note: do not use <code><script></code> or <code><link></code> tags directly referencing the files on this website.
Doing this is likely to break your app whenever a major new version is released.
</p>
<h2 id="usage">Usage</h2>
<p>
Run the following code when the document has loaded:
</p>
<!-- populated dynamically -->
<pre>
<code id="spinner-options" class="language-js"></code>
</pre>
<p>
The <code>spin()</code> method creates the necessary HTML elements and starts the animation. If a target
element is passed as argument, the spinner is added as first child and horizontally and vertically centered.
</p>
<h3>Manual insertion</h3>
<p>
In order to manually insert the spinner into the DOM you can invoke the <code>spin()</code> method
without any arguments and use the <code>el</code> property to access the HTML element:
</p>
<pre>
<code class="language-js">var spinner = new Spinner().spin();
target.appendChild(spinner.el);</code>
</pre>
<h3>Hiding the spinner</h3>
<p>
To hide the spinner, invoke the
<code>stop()</code> method, which removes the UI elements from the DOM and stops the animation.
Stopped spinners may be reused by calling <code>spin()</code> again.
</p>
<h3>Positioning</h3>
<p>
The spinner is absolutely positioned at 50% of its offset parent.
You may specify a <code>top</code> and <code>left</code> option to position the spinner manually.
</p>
<p>
<b>Note:</b> The spinner element is a 0×0 pixel div that represents the center of the spinner.
Hence, if you passed <code>{top:0, left:0}</code> only the lower right quarter of the spinner would
be inside the target's bounding box.
</p>
<p>
The spinner element must be surrounded by an element using relative positioning, or the spinner will be
outside of the parent element.
</p>
<h2>Supported browsers</h2>
<img src="assets/browsers.svg">
<p>
Spin.js has been successfully tested in the following browsers:
</p>
<ul>
<li>Firefox</li>
<li>Microsoft Edge</li>
<li>Safari</li>
<li>Chrome</li>
<li>Internet Explorer 10+</li>
</ul>
<h2>Changes</h2>
<p>
See <a href="https://github.com/fgnass/spin.js/blob/master/CHANGELOG.md">CHANGELOG.md</a>
</p>
<h2>Support</h2>
<p>
If you encounter any problems, please use the <a href="https://github.com/fgnass/spin.js/issues">GitHub issue tracker</a>.
</p>
<h2>Authors</h2>
<div class="authors">
<div class="contact">
<img src="https://www.gravatar.com/avatar/f1f2e1842f6ff681a6d1b0a2405d0117"/>
<h3>Felix Gnass</h3>
<p>JS 💛 React ⚛️ NodeJS 💚</p>
<p>
Twitter: <a href="https://twitter.com/fgnass">@fgnass</a>
</p>
</div>
<div class="contact">
<img src="https://www.gravatar.com/avatar/5f7e5be7427b4c706eb1ff85ceb98998"/>
<h3>Theodore Brown</h3>
<p>PHP 🐘 TypeScript 📐 SQL 📊</p>
<p>
Website: <a href="https://theodorejb.me">theodorejb.me</a><br/>
Twitter: <a href="https://twitter.com/theodorejb">@theodorejb</a>
</p>
</div>
</div>
</div>
<div id="footer">
<a class="github" href="https://github.com/fgnass/spin.js">Hosted on GitHub</a>
</div>
<script src="assets/prism.js"></script>
<script src="bundle.js"></script>
</body>
</html>
================================================
FILE: site/index.js
================================================
import { Spinner } from "../spin.js";
var inputs = document.querySelectorAll('#opts input[type="range"], #opts input[type="color"], #opts input[type="text"], #opts select');
var cbInputs = document.querySelectorAll('#opts input[type="checkbox"]');
var spinnerEl = document.getElementById('preview');
var shareEl = document.getElementById('share');
var spinner;
var params = {};
var hash = /^#\?(.*)/.exec(location.hash);
if (hash) {
shareEl.checked = true;
hash[1].split(/&/).forEach(function (pair) {
var kv = pair.split(/=/);
params[kv[0]] = decodeURIComponent(kv[kv.length - 1]);
});
}
for (var i = 0; i < inputs.length; i++) {
var input = inputs[i];
var val = params[input.name];
if (val !== undefined) {
input.value = val;
}
if (input.tagName === 'SELECT' || navigator.userAgent.indexOf('Trident') !== -1) {
// "input" event doesn't work on range inputs in Internet Explorer
var event = 'change';
} else {
event = 'input';
}
input.addEventListener(event, update);
}
for (var i = 0; i < cbInputs.length; i++) {
var input = cbInputs[i];
input.checked = !!params[input.name];
input.addEventListener('click', update);
}
shareEl.addEventListener('click', function () {
var value = '#!';
if (shareEl.checked) {
var opts = getOptionsFromInputs();
value = '#?' + getParamStringFromOpts(opts);
}
window.location.replace(value);
});
update();
function update() {
var opts = getOptionsFromInputs();
if (spinner) {
spinner.stop();
}
spinner = new Spinner(opts).spin(spinnerEl);
if (shareEl.checked) {
window.location.replace('#?' + getParamStringFromOpts(opts));
}
let codeEl = document.getElementById('spinner-options');
codeEl.textContent = getOptionsCode(opts);
Prism.highlightElement(codeEl);
}
function getOptionsCode(options) {
var optDescriptions = {
lines: 'The number of lines to draw',
length: 'The length of each line',
width: 'The line thickness',
radius: 'The radius of the inner circle',
scale: 'Scales overall size of the spinner',
corners: 'Corner roundness (0..1)',
color: 'CSS color or array of colors',
fadeColor: 'CSS color or array of colors',
speed: 'Rounds per second',
rotate: 'The rotation offset',
animation: 'The CSS animation name for the lines',
direction: '1: clockwise, -1: counterclockwise',
zIndex: 'The z-index (defaults to 2e9)',
className: 'The CSS class to assign to the spinner',
top: 'Top position relative to parent',
left: 'Left position relative to parent',
shadow: 'Box-shadow for the lines',
position: 'Element positioning',
};
let code = "import {Spinner} from 'spin.js';\n\n";
code += "var opts = {\n";
for (let opt in options) {
let value = options[opt];
if (typeof value === 'string') {
value = "'" + value + "'";
}
code += " " + opt + ": " + value + ", // " + optDescriptions[opt] + "\n";
}
code += "};\n\n";
code += "var target = document.getElementById('foo');\n";
code += "var spinner = new Spinner(opts).spin(target);";
return code;
}
function getOptionsFromInputs() {
var opts = {};
for (var i = 0; i < inputs.length; i++) {
var input = inputs[i];
var val = input.value;
if (input.classList.contains('percent')) {
val += '%';
} else if (!input.classList.contains('string')) {
val = parseFloat(val);
}
opts[input.name] = val;
}
// set all options so they can be shown in code example
opts['zIndex'] = 2e9;
opts['className'] = 'spinner';
opts['position'] = 'absolute';
for (var i = 0; i < cbInputs.length; i++) {
var input = cbInputs[i];
opts[input.name] = input.checked;
document.getElementById('opt-' + input.name).textContent = input.checked;
}
return opts;
}
function getParamStringFromOpts(opts) {
var params = [];
for (var prop in opts) {
var val = opts[prop];
if (val !== false) {
if (typeof val === 'string' && val.slice(-1) === '%') {
val = val.slice(0, -1);
}
params.push(prop + '=' + encodeURIComponent(val));
}
}
return params.join('&');
}
================================================
FILE: site/serve.json
================================================
{
"headers": [
{
"source" : "index.html",
"headers" : [{
"key" : "Content-Security-Policy",
"value" : "default-src 'self'; style-src 'self' fonts.googleapis.com; font-src 'self' fonts.gstatic.com; img-src 'self' www.gravatar.com;"
}]
}
]
}
================================================
FILE: spin.css
================================================
@keyframes spinner-line-fade-more {
0%, 100% {
opacity: 0; /* minimum opacity */
}
1% {
opacity: 1;
}
}
@keyframes spinner-line-fade-quick {
0%, 39%, 100% {
opacity: 0.25; /* minimum opacity */
}
40% {
opacity: 1;
}
}
@keyframes spinner-line-fade-default {
0%, 100% {
opacity: 0.22; /* minimum opacity */
}
1% {
opacity: 1;
}
}
@keyframes spinner-line-shrink {
0%, 25%, 100% {
/* minimum scale and opacity */
transform: scale(0.5);
opacity: 0.25;
}
26% {
transform: scale(1);
opacity: 1;
}
}
================================================
FILE: spin.ts
================================================
import { SpinnerOptions } from './SpinnerOptions.js';
export { SpinnerOptions } from './SpinnerOptions.js';
const defaults: Required<SpinnerOptions> = {
lines: 12,
length: 7,
width: 5,
radius: 10,
scale: 1.0,
corners: 1,
color: '#000',
fadeColor: 'transparent',
animation: 'spinner-line-fade-default',
rotate: 0,
direction: 1,
speed: 1,
zIndex: 2e9,
className: 'spinner',
top: '50%',
left: '50%',
shadow: '0 0 1px transparent', // prevent aliased lines
position: 'absolute',
};
export class Spinner {
private opts: Required<SpinnerOptions>;
/**
* The Spinner's HTML element - can be used to manually insert the spinner into the DOM
*/
public el: HTMLElement | undefined;
constructor(opts: SpinnerOptions = {}) {
this.opts = { ...defaults, ...opts };
}
/**
* Adds the spinner to the given target element. If this instance is already
* spinning, it is automatically removed from its previous target by calling
* stop() internally.
*/
spin(target?: HTMLElement): this {
this.stop();
this.el = document.createElement('div');
this.el.className = this.opts.className;
this.el.setAttribute('role', 'progressbar');
this.el.style.position = this.opts.position;
this.el.style.width = "0";
this.el.style.zIndex = this.opts.zIndex.toString();
this.el.style.left = this.opts.left;
this.el.style.top = this.opts.top;
this.el.style.transform = `scale(${this.opts.scale})`;
if (target) {
target.insertBefore(this.el, target.firstChild || null);
}
drawLines(this.el, this.opts);
return this;
}
/**
* Stops and removes the Spinner.
* Stopped spinners may be reused by calling spin() again.
*/
stop(): this {
if (this.el) {
if (this.el.parentNode) {
this.el.parentNode.removeChild(this.el);
}
this.el = undefined;
}
return this;
}
}
/**
* Returns the line color from the given string or array.
*/
function getColor(color: string | string[], idx: number): string {
return typeof color == 'string' ? color : color[idx % color.length];
}
/**
* Internal method that draws the individual lines.
*/
function drawLines(el: HTMLElement, opts: Required<SpinnerOptions>): void {
let borderRadius = (Math.round(opts.corners * opts.width * 500) / 1000) + 'px';
let shadow = 'none';
if (opts.shadow === true) {
shadow = '0 2px 4px #000'; // default shadow
} else if (typeof opts.shadow === 'string') {
shadow = opts.shadow;
}
let shadows = parseBoxShadow(shadow);
for (let i = 0; i < opts.lines; i++) {
let degrees = ~~(360 / opts.lines * i + opts.rotate);
let backgroundLine = document.createElement('div');
backgroundLine.style.position = 'absolute';
backgroundLine.style.top = `${-opts.width / 2}px`;
backgroundLine.style.width = (opts.length + opts.width) + 'px';
backgroundLine.style.height = opts.width + 'px';
backgroundLine.style.background = getColor(opts.fadeColor, i);
backgroundLine.style.borderRadius = borderRadius;
backgroundLine.style.transformOrigin = 'left';
backgroundLine.style.transform = `rotate(${degrees}deg) translateX(${opts.radius}px)`;
let delay = i * opts.direction / opts.lines / opts.speed;
delay -= 1 / opts.speed; // so initial animation state will include trail
let line = document.createElement('div');
line.style.width = '100%';
line.style.height = '100%';
line.style.background = getColor(opts.color, i);
line.style.borderRadius = borderRadius;
line.style.boxShadow = normalizeShadow(shadows, degrees);
line.style.animation = `${1 / opts.speed}s linear ${delay}s infinite ${opts.animation}`;
backgroundLine.appendChild(line);
el.appendChild(backgroundLine);
}
}
interface ParsedShadow {
prefix: string,
x: number,
y: number,
xUnits: string,
yUnits: string,
end: string,
}
function parseBoxShadow(boxShadow: string): ParsedShadow[] {
let regex = /^\s*([a-zA-Z]+\s+)?(-?\d+(\.\d+)?)([a-zA-Z]*)\s+(-?\d+(\.\d+)?)([a-zA-Z]*)(.*)$/;
let shadows: ParsedShadow[] = [];
for (let shadow of boxShadow.split(',')) {
let matches = shadow.match(regex);
if (matches === null) {
continue; // invalid syntax
}
let x = +matches[2];
let y = +matches[5];
let xUnits = matches[4];
let yUnits = matches[7];
if (x === 0 && !xUnits) {
xUnits = yUnits;
}
if (y === 0 && !yUnits) {
yUnits = xUnits;
}
if (xUnits !== yUnits) {
continue; // units must match to use as coordinates
}
shadows.push({
prefix: matches[1] || '', // could have value of 'inset' or undefined
x: x,
y: y,
xUnits: xUnits,
yUnits: yUnits,
end: matches[8],
});
}
return shadows;
}
/**
* Modify box-shadow x/y offsets to counteract rotation
*/
function normalizeShadow(shadows: ParsedShadow[], degrees: number): string {
let normalized: string[] = [];
for (let shadow of shadows) {
let xy = convertOffset(shadow.x, shadow.y, degrees);
normalized.push(shadow.prefix + xy[0] + shadow.xUnits + ' ' + xy[1] + shadow.yUnits + shadow.end);
}
return normalized.join(', ');
}
function convertOffset(x: number, y: number, degrees: number) {
let radians = degrees * Math.PI / 180;
let sin = Math.sin(radians);
let cos = Math.cos(radians);
return [
Math.round((x * cos + y * sin) * 1000) / 1000,
Math.round((-x * sin + y * cos) * 1000) / 1000,
];
}
================================================
FILE: tsconfig.json
================================================
{
"compilerOptions": {
"module": "NodeNext",
"moduleResolution": "NodeNext",
"target": "ES5",
"forceConsistentCasingInFileNames": true,
"noUnusedLocals": true,
"strict": true,
"declaration": true
},
"files": [
"spin.ts"
]
}
gitextract_q8vr1fl3/ ├── .gitattributes ├── .gitignore ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Gruntfile.cjs ├── LICENSE.md ├── README.md ├── SpinnerOptions.d.ts ├── package.json ├── rollup.config.js ├── site/ │ ├── CNAME │ ├── assets/ │ │ ├── gh-fork-ribbon.css │ │ ├── main.css │ │ ├── prism.css │ │ └── prism.js │ ├── example/ │ │ ├── positioning.css │ │ ├── positioning.html │ │ └── positioning.js │ ├── index.html │ ├── index.js │ └── serve.json ├── spin.css ├── spin.ts └── tsconfig.json
SYMBOL INDEX (21 symbols across 4 files)
FILE: SpinnerOptions.d.ts
type SpinnerOptions (line 1) | interface SpinnerOptions {
FILE: site/assets/prism.js
function o (line 3) | function o(e){l.highlightedCode=e,M.hooks.run("before-insert",l),l.eleme...
function W (line 3) | function W(e,n,t,r){this.type=e,this.content=n,this.alias=t,this.length=...
function i (line 3) | function i(){var e={value:null,prev:null,next:null},n={value:null,prev:e...
function I (line 3) | function I(e,n,t){var r=n.next,a={value:t,prev:n,next:r};return n.next=a...
function z (line 3) | function z(e,n,t){for(var r=n.next,a=0;a<t&&r!==e.tail;a++)r=r.next;(n.n...
function t (line 3) | function t(){M.manual||M.highlightAll()}
FILE: site/index.js
function update (line 57) | function update() {
function getOptionsCode (line 75) | function getOptionsCode(options) {
function getOptionsFromInputs (line 118) | function getOptionsFromInputs() {
function getParamStringFromOpts (line 148) | function getParamStringFromOpts(opts) {
FILE: spin.ts
class Spinner (line 25) | class Spinner {
method constructor (line 33) | constructor(opts: SpinnerOptions = {}) {
method spin (line 42) | spin(target?: HTMLElement): this {
method stop (line 69) | stop(): this {
function getColor (line 85) | function getColor(color: string | string[], idx: number): string {
function drawLines (line 92) | function drawLines(el: HTMLElement, opts: Required<SpinnerOptions>): void {
type ParsedShadow (line 133) | interface ParsedShadow {
function parseBoxShadow (line 142) | function parseBoxShadow(boxShadow: string): ParsedShadow[] {
function normalizeShadow (line 186) | function normalizeShadow(shadows: ParsedShadow[], degrees: number): stri...
function convertOffset (line 197) | function convertOffset(x: number, y: number, degrees: number) {
Condensed preview — 24 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (66K chars).
[
{
"path": ".gitattributes",
"chars": 104,
"preview": "# so documentation files won't cause project language to be shown as HTML\nsite/* linguist-documentation\n"
},
{
"path": ".gitignore",
"chars": 105,
"preview": "/.grunt\n/node_modules\n/site/bundle.js\n/site/spin.css\n/site/spin.js\n/site/spin.umd.js\n/spin.js\n/spin.d.ts\n"
},
{
"path": "CHANGELOG.md",
"chars": 11484,
"preview": "# Changelog\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changel"
},
{
"path": "CONTRIBUTING.md",
"chars": 637,
"preview": "# Contributing\n\nAfter cloning the repository, run `npm install` to install development dependencies and compile the proj"
},
{
"path": "Gruntfile.cjs",
"chars": 484,
"preview": "module.exports = function(grunt) {\n\n grunt.initConfig({\n\n copy: {\n js: {\n files: [\n { src: ['sp"
},
{
"path": "LICENSE.md",
"chars": 1119,
"preview": "The MIT License\n===============\n\nCopyright (c) 2011-2018 Felix Gnass [fgnass at gmail dot com]\n\nPermission is hereby gra"
},
{
"path": "README.md",
"chars": 808,
"preview": "# spin.js [](http://js.org)\n\nAn animated"
},
{
"path": "SpinnerOptions.d.ts",
"chars": 1687,
"preview": "export interface SpinnerOptions {\n /**\n * The number of lines to draw\n */\n lines?: number;\n\n /**\n *"
},
{
"path": "package.json",
"chars": 986,
"preview": "{\n \"name\": \"spin.js\",\n \"version\": \"4.1.2\",\n \"description\": \"A spinning activity indicator\",\n \"files\": [\n \"spin.cs"
},
{
"path": "rollup.config.js",
"chars": 314,
"preview": "export default [\n {\n input: 'spin.js',\n output: {\n file: 'site/spin.umd.js',\n for"
},
{
"path": "site/CNAME",
"chars": 12,
"preview": "spin.js.org\n"
},
{
"path": "site/assets/gh-fork-ribbon.css",
"chars": 2631,
"preview": "/*!\n * \"Fork me on GitHub\" CSS ribbon v0.2.3 | MIT License\n * https://github.com/simonwhitaker/github-fork-ribbon-css\n*/"
},
{
"path": "site/assets/main.css",
"chars": 2990,
"preview": "html, body {\n margin: 0;\n}\n\nhtml {\n background: url(bg.png);\n}\n\nbody {\n color: #333;\n font-family: Helvetica, Arial,"
},
{
"path": "site/assets/prism.css",
"chars": 1927,
"preview": "/* PrismJS 1.20.0\nhttps://prismjs.com/download.html#themes=prism-okaidia&languages=markup+css+clike+javascript */\n/**\n *"
},
{
"path": "site/assets/prism.js",
"chars": 14630,
"preview": "/* PrismJS 1.20.0\nhttps://prismjs.com/download.html#themes=prism-okaidia&languages=markup+css+clike+javascript */\nvar _s"
},
{
"path": "site/example/positioning.css",
"chars": 842,
"preview": "body {\n font-family: Helvetica, Arial, sans-serif;\n font-size: 16px;\n padding: 0;\n margin: 0;\n}\n\ndiv {\n p"
},
{
"path": "site/example/positioning.html",
"chars": 404,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n <title>spin.js</title>\n <link rel=\"stylesheet\" type=\"text/css\" href=\"../spin.css\"/>\n <"
},
{
"path": "site/example/positioning.js",
"chars": 470,
"preview": "import { Spinner } from \"../spin.js\";\n\nnew Spinner({ radius: 10, length: 40, color: ['red', 'green', 'blue'] })\n .spi"
},
{
"path": "site/index.html",
"chars": 8432,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n <meta charset=\"utf-8\"/>\n <title>spin.js</title>\n <meta name=\"title\" content=\"Animated "
},
{
"path": "site/index.js",
"chars": 4483,
"preview": "import { Spinner } from \"../spin.js\";\n\nvar inputs = document.querySelectorAll('#opts input[type=\"range\"], #opts input[ty"
},
{
"path": "site/serve.json",
"chars": 286,
"preview": "{\n \"headers\": [\n {\n \"source\" : \"index.html\",\n \"headers\" : [{\n \"key\" : \"Content-Security-Policy\",\n "
},
{
"path": "spin.css",
"chars": 571,
"preview": "@keyframes spinner-line-fade-more {\n 0%, 100% {\n opacity: 0; /* minimum opacity */\n }\n 1% {\n opacity: 1;\n }\n}\n"
},
{
"path": "spin.ts",
"chars": 5970,
"preview": "import { SpinnerOptions } from './SpinnerOptions.js';\nexport { SpinnerOptions } from './SpinnerOptions.js';\n\nconst defau"
},
{
"path": "tsconfig.json",
"chars": 304,
"preview": "{\n \"compilerOptions\": {\n \"module\": \"NodeNext\",\n \"moduleResolution\": \"NodeNext\",\n \"target\": \"ES5\""
}
]
About this extraction
This page contains the full source code of the fgnass/spin.js GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 24 files (60.2 KB), approximately 19.7k tokens, and a symbol index with 21 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.