Full Code of svgdotjs/svg.js for AI

master a73d82c9bd17 cached
200 files
792.6 KB
232.7k tokens
762 symbols
1 requests
Download .txt
Showing preview only (844K chars total). Download the full file or copy to clipboard to get everything.
Repository: svgdotjs/svg.js
Branch: master
Commit: a73d82c9bd17
Files: 200
Total size: 792.6 KB

Directory structure:
gitextract_lqipgjf4/

├── .config/
│   ├── karma.conf.cjs
│   ├── karma.conf.common.cjs
│   ├── karma.conf.saucelabs.cjs
│   ├── polyfillListIE.js
│   ├── pretest.js
│   ├── rollup.config.js
│   ├── rollup.polyfills.js
│   └── rollup.tests.js
├── .eslintrc.json
├── .github/
│   ├── CONTRIBUTING.md
│   ├── FUNDING.yml
│   └── ISSUE_TEMPLATE/
│       ├── bug-report.md
│       ├── feature-request.md
│       └── other.md
├── .gitignore
├── .prettierignore
├── .prettierrc.json
├── .travis.yml
├── CHANGELOG.md
├── LICENSE.txt
├── README.md
├── bench/
│   ├── runner.html
│   ├── svg.bench.js
│   └── tests/
│       ├── 10000-accesses.js
│       ├── 10000-boxes.js
│       ├── 10000-circles.js
│       ├── 10000-each.js
│       ├── 10000-pathArray-bbox.js
│       ├── 10000-pathArrays.js
│       ├── 10000-paths.js
│       ├── 10000-pointArray-bbox.js
│       ├── 10000-rects.js
│       ├── 10000-textContent.js
│       └── 10000-transform.js
├── package.json
├── playgrounds/
│   ├── colors/
│   │   ├── main.js
│   │   └── style.css
│   ├── matrix/
│   │   ├── drag.js
│   │   ├── matrix.js
│   │   └── style.css
│   ├── transforms/
│   │   ├── style.css
│   │   └── transforms.js
│   └── webpack.config.js
├── spec/
│   ├── RAFPlugin.js
│   ├── SpecRunner.html
│   ├── SpecRunnerEs6.html
│   ├── checkForAllTests.js
│   ├── fixtures/
│   │   └── fixture.css
│   ├── helpers.js
│   ├── runSVGDomTest.js
│   ├── setupBrowser.js
│   ├── setupSVGDom.js
│   └── spec/
│       ├── animation/
│       │   ├── Animator.js
│       │   ├── Controller.js
│       │   ├── Morphable.js
│       │   ├── Queue.js
│       │   ├── Runner.js
│       │   └── Timeline.js
│       ├── elements/
│       │   ├── A.js
│       │   ├── Circle.js
│       │   ├── ClipPath.js
│       │   ├── Container.js
│       │   ├── Defs.js
│       │   ├── Dom.js
│       │   ├── Element.js
│       │   ├── Ellipse.js
│       │   ├── ForeignObject.js
│       │   ├── Fragment.js
│       │   ├── G.js
│       │   ├── Gradient.js
│       │   ├── Image.js
│       │   ├── Line.js
│       │   ├── Marker.js
│       │   ├── Mask.js
│       │   ├── Path.js
│       │   ├── Pattern.js
│       │   ├── Polygon.js
│       │   ├── Polyline.js
│       │   ├── Rect.js
│       │   ├── Shape.js
│       │   ├── Stop.js
│       │   ├── Style.js
│       │   ├── Svg.js
│       │   ├── Symbol.js
│       │   ├── Text.js
│       │   ├── TextPath.js
│       │   ├── Tspan.js
│       │   └── Use.js
│       ├── modules/
│       │   ├── core/
│       │   │   ├── attr.js
│       │   │   ├── circled.js
│       │   │   ├── containerGeometry.js
│       │   │   ├── event.js
│       │   │   ├── gradiented.js
│       │   │   ├── parser.js
│       │   │   ├── pointed.js
│       │   │   ├── poly.js
│       │   │   ├── regex.js
│       │   │   ├── selector.js
│       │   │   └── textable.js
│       │   └── optional/
│       │       ├── arrange.js
│       │       ├── class.js
│       │       ├── css.js
│       │       ├── data.js
│       │       ├── memory.js
│       │       ├── sugar.js
│       │       └── transform.js
│       ├── types/
│       │   ├── Base.js
│       │   ├── Box.js
│       │   ├── Color.js
│       │   ├── EventTarget.js
│       │   ├── List.js
│       │   ├── Matrix.js
│       │   ├── PathArray.js
│       │   ├── Point.js
│       │   ├── PointArray.js
│       │   ├── SVGArray.js
│       │   └── SVGNumber.js
│       └── utils/
│           ├── adopter.js
│           ├── methods.js
│           ├── pathParser.js
│           ├── utils.js
│           └── window.js
├── src/
│   ├── animation/
│   │   ├── Animator.js
│   │   ├── Controller.js
│   │   ├── Morphable.js
│   │   ├── Queue.js
│   │   ├── Runner.js
│   │   └── Timeline.js
│   ├── elements/
│   │   ├── A.js
│   │   ├── Circle.js
│   │   ├── ClipPath.js
│   │   ├── Container.js
│   │   ├── Defs.js
│   │   ├── Dom.js
│   │   ├── Element.js
│   │   ├── Ellipse.js
│   │   ├── ForeignObject.js
│   │   ├── Fragment.js
│   │   ├── G.js
│   │   ├── Gradient.js
│   │   ├── Image.js
│   │   ├── Line.js
│   │   ├── Marker.js
│   │   ├── Mask.js
│   │   ├── Path.js
│   │   ├── Pattern.js
│   │   ├── Polygon.js
│   │   ├── Polyline.js
│   │   ├── Rect.js
│   │   ├── Shape.js
│   │   ├── Stop.js
│   │   ├── Style.js
│   │   ├── Svg.js
│   │   ├── Symbol.js
│   │   ├── Text.js
│   │   ├── TextPath.js
│   │   ├── Tspan.js
│   │   └── Use.js
│   ├── main.js
│   ├── modules/
│   │   ├── core/
│   │   │   ├── attr.js
│   │   │   ├── circled.js
│   │   │   ├── containerGeometry.js
│   │   │   ├── defaults.js
│   │   │   ├── event.js
│   │   │   ├── gradiented.js
│   │   │   ├── namespaces.js
│   │   │   ├── parser.js
│   │   │   ├── pointed.js
│   │   │   ├── poly.js
│   │   │   ├── regex.js
│   │   │   ├── selector.js
│   │   │   └── textable.js
│   │   └── optional/
│   │       ├── arrange.js
│   │       ├── class.js
│   │       ├── css.js
│   │       ├── data.js
│   │       ├── memory.js
│   │       ├── sugar.js
│   │       └── transform.js
│   ├── polyfills/
│   │   ├── children.js
│   │   └── innerHTML.js
│   ├── svg.js
│   ├── types/
│   │   ├── Base.js
│   │   ├── Box.js
│   │   ├── Color.js
│   │   ├── EventTarget.js
│   │   ├── List.js
│   │   ├── Matrix.js
│   │   ├── PathArray.js
│   │   ├── Point.js
│   │   ├── PointArray.js
│   │   ├── SVGArray.js
│   │   └── SVGNumber.js
│   └── utils/
│       ├── adopter.js
│       ├── methods.js
│       ├── pathParser.js
│       ├── utils.js
│       └── window.js
├── svg.js.d.ts
└── tsconfig.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .config/karma.conf.cjs
================================================
// Karma configuration
const karmaCommon = require('./karma.conf.common.cjs')

let chromeBin = 'ChromeHeadless'
if (process.platform === 'linux') {
  // We need to choose either Chrome or Chromium.
  // Canary is not available on linux.
  // If we do not find Chromium then we can deduce that
  // either Chrome is installed or there is no Chrome variant at all,
  // in which case karma-chrome-launcher will output an error.
  // If `which` finds nothing it will throw an error.
  const { execSync } = require('child_process')

  try {
    if (execSync('which chromium-browser')) chromeBin = 'ChromiumHeadless'
  } catch (e) {}
}

module.exports = function (config) {
  config.set(
    Object.assign(karmaCommon(config), {
      files: [
        'spec/RAFPlugin.js',
        {
          pattern: 'spec/fixtures/fixture.css',
          included: false,
          served: true
        },
        {
          pattern: 'spec/fixtures/pixel.png',
          included: false,
          served: true
        },
        {
          pattern: 'src/**/*.js',
          included: false,
          served: true,
          type: 'modules'
        },
        {
          pattern: 'spec/helpers.js',
          included: false,
          served: true,
          type: 'module'
        },
        {
          pattern: 'spec/setupBrowser.js',
          included: true,
          type: 'module'
        },
        {
          pattern: 'spec/spec/*/**/*.js',
          included: true,
          type: 'module'
        }
      ],

      // preprocess matching files before serving them to the browser
      // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
      preprocessors: {
        'src/**/*.js': ['coverage']
      },

      // test results reporter to use
      // possible values: 'dots', 'progress'
      // available reporters: https://npmjs.org/browse/keyword/karma-reporter
      reporters: ['progress', 'coverage'],
      coverageReporter: {
        // Specify a reporter type.
        type: 'lcov',
        dir: 'coverage/',
        subdir: function (browser) {
          // normalization process to keep a consistent browser name accross different OS
          return browser.toLowerCase().split(/[ /-]/)[0] // output the results into: './coverage/firefox/'
        },
        instrumenterOptions: {
          istanbul: {
            esModules: true
          }
        }
      },

      // start these browsers
      // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
      browsers: [chromeBin, 'FirefoxHeadless']
    })
  )
}


================================================
FILE: .config/karma.conf.common.cjs
================================================
// Karma shared configuration

const os = require('os')
const cpuCount = os.cpus().length

module.exports = function (config) {
  return {
    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '../',

    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['jasmine'],

    // list of files / patterns to load in the browser
    files: [
      '.config/pretest.js',
      'spec/RAFPlugin.js',
      {
        pattern: 'spec/fixtures/fixture.css',
        included: false,
        served: true
      },
      {
        pattern: 'spec/fixtures/fixture.svg',
        included: false,
        served: true
      },
      {
        pattern: 'spec/fixtures/pixel.png',
        included: false,
        served: true
      },
      'dist/svg.js',
      'spec/spec/*.js'
    ],

    proxies: {
      '/fixtures/': '/base/spec/fixtures/',
      '/spec/': '/base/spec/'
    },

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: false,

    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: true,

    // Concurrency level
    // how many browser should be started simultaneous
    concurrency: cpuCount || Infinity,

    // list of files to exclude
    exclude: []
  }
}


================================================
FILE: .config/karma.conf.saucelabs.cjs
================================================
// Karma configuration
// https://wiki.saucelabs.com/display/DOCS/Platform+Configurator

// TODO: remove dotenv after local test
// require('dotenv').config()

const karmaCommon = require('./karma.conf.common.cjs')

const SauceLabsLaunchers = {
  /** Real mobile devices are not available
   *  Your account does not have access to Android devices.
   *  Please contact sales@saucelabs.com to add this feature to your account. */
  /* sl_android_chrome: {
    base: 'SauceLabs',
    appiumVersion: '1.5.3',
    deviceName: 'Samsung Galaxy S7 Device',
    deviceOrientation: 'portrait',
    browserName: 'Chrome',
    platformVersion: '6.0',
    platformName: 'Android'
  }, */
  /* sl_android: {
    base: 'SauceLabs',
    browserName: 'Android',
    deviceName: 'Android Emulator',
    deviceOrientation: 'portrait'
  }, */
  SL_firefox_latest: {
    base: 'SauceLabs',
    browserName: 'firefox',
    version: 'latest'
  },
  SL_chrome_latest: {
    base: 'SauceLabs',
    browserName: 'chrome',
    version: 'latest'
  },
  SL_InternetExplorer: {
    base: 'SauceLabs',
    browserName: 'internet explorer',
    version: '11.0'
  } /*
  sl_windows_edge: {
    base: 'SauceLabs',
    browserName: 'MicrosoftEdge',
    version: 'latest',
    platform: 'Windows 10'
  },
  sl_macos_safari: {
    base: 'SauceLabs',
    browserName: 'safari',
    platform: 'macOS 10.13',
    version: '12.0',
    recordVideo: true,
    recordScreenshots: true,
    screenResolution: '1024x768'
  } */ /*,
  sl_macos_iphone: {
    base: 'SauceLabs',
    browserName: 'Safari',
    deviceName: 'iPhone SE Simulator',
    deviceOrientation: 'portrait',
    platformVersion: '10.2',
    platformName: 'iOS'
  }
  'SL_Chrome': {
    base: 'SauceLabs',
    browserName: 'chrome',
    version: '48.0',
    platform: 'Linux'
  },
  'SL_Firefox': {
    base: 'SauceLabs',
    browserName: 'firefox',
    version: '50.0',
    platform: 'Windows 10'
  },
  'SL_Safari': {
    base: 'SauceLabs',
    browserName: 'safari',
    platform: 'OS X 10.11',
    version: '10.0'
  } */
}

module.exports = function (config) {
  if (!process.env.SAUCE_USERNAME || !process.env.SAUCE_ACCESS_KEY) {
    console.error(
      'SAUCE_USERNAME and SAUCE_ACCESS_KEY must be provided as environment variables.'
    )
    console.warn('Aborting Sauce Labs test')
    process.exit(1)
  }
  const settings = Object.assign(karmaCommon(config), {
    // Concurrency level
    // how many browser should be started simultaneous
    // Saucelabs allow up to 5 concurrent sessions on the free open source tier.
    concurrency: 5,

    // this specifies which plugins karma should load
    // by default all karma plugins, starting with `karma-` will load
    // so if you are really puzzled why something isn't working, then comment
    // out plugins: [] - it's here to make karma load faster
    // get possible karma plugins by `ls node_modules | grep 'karma-*'`
    plugins: ['karma-jasmine', 'karma-sauce-launcher'],

    // logLevel: config.LOG_DEBUG,

    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['dots', 'saucelabs'],

    customLaunchers: SauceLabsLaunchers,

    // start these browsers
    browsers: Object.keys(SauceLabsLaunchers),
    sauceLabs: {
      testName: 'SVG.js Unit Tests'
      // connectOptions: {
      //   noSslBumpDomains: "all"
      // },
      // connectOptions: {
      //   port: 5757,
      //   logfile: 'sauce_connect.log'
      // },
    }

    // The number of disconnections tolerated.
    // browserDisconnectTolerance: 0, // well, sometimes it helps to just restart
    // // How long does Karma wait for a browser to reconnect (in ms).
    // browserDisconnectTimeout: 10 * 60 * 1000,
    // // How long will Karma wait for a message from a browser before disconnecting from it (in ms). ~ macOS 10.12 needs more than 7 minutes
    // browserNoActivityTimeout: 20 * 60 * 1000,
    // // Timeout for capturing a browser (in ms).  On newer versions of iOS simulator (10.0+), the start up time could be between 3 - 6 minutes.
    // captureTimeout: 12 * 60 * 1000, // this is useful if saucelabs takes a long time to boot a vm

    // // Required to make Safari on Sauce Labs play nice.
    // // hostname: 'karmalocal.dev'
  })

  console.log(settings)
  config.set(settings)
}


================================================
FILE: .config/polyfillListIE.js
================================================
/* global SVGElement */
/* eslint no-new-object: "off" */

import CustomEventPolyfill from '@target/custom-event-polyfill/src/index.js6'
import children from '../src/polyfills/children.js'

/* IE 11 has no innerHTML on SVGElement */
import '../src/polyfills/innerHTML.js'

/* IE 11 has no correct CustomEvent implementation */
CustomEventPolyfill()

/* IE 11 has no children on SVGElement */
try {
  if (!SVGElement.prototype.children) {
    Object.defineProperty(SVGElement.prototype, 'children', {
      get: function () {
        return children(this)
      }
    })
  }
} catch (e) {}

/* IE 11 cannot handle getPrototypeOf(not_obj) */
try {
  delete Object.getPrototypeOf('test')
} catch (e) {
  var old = Object.getPrototypeOf
  Object.getPrototypeOf = function (o) {
    if (typeof o !== 'object') o = new Object(o)
    return old.call(this, o)
  }
}


================================================
FILE: .config/pretest.js
================================================
/* global XMLHttpRequest */
'use strict'

function get(uri) {
  var xhr = new XMLHttpRequest()
  xhr.open('GET', uri, false)
  xhr.send()
  if (xhr.status !== 200) {
    console.error('SVG.js fixture could not be loaded. Tests will fail.')
  }
  return xhr.responseText
}

function main() {
  var style = document.createElement('style')
  document.head.appendChild(style)
  style.sheet.insertRule(get('/fixtures/fixture.css'), 0)

  document.body.innerHTML = get('/fixtures/fixture.svg')
}

main()


================================================
FILE: .config/rollup.config.js
================================================
import pkg from '../package.json' with { type: 'json' }
import babel from '@rollup/plugin-babel'
import resolve from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'
import filesize from 'rollup-plugin-filesize'
import terser from '@rollup/plugin-terser'

const buildDate = Date()

const headerLong = `/*!
* ${pkg.name} - ${pkg.description}
* @version ${pkg.version}
* ${pkg.homepage}
*
* @copyright ${pkg.author}
* @license ${pkg.license}
*
* BUILT: ${buildDate}
*/;`

const headerShort = `/*! ${pkg.name} v${pkg.version} ${pkg.license}*/;`

const getBabelConfig = (node = false) => {
  let targets = pkg.browserslist
  const plugins = [
    [
      '@babel/transform-runtime',
      {
        version: '^7.24.7',
        regenerator: false,
        useESModules: true
      }
    ],
    [
      'polyfill-corejs3',
      {
        method: 'usage-pure'
      }
    ]
  ]

  if (node) {
    targets = 'maintained node versions'
  }

  return babel({
    include: 'src/**',
    babelHelpers: 'runtime',
    babelrc: false,
    targets: targets,
    presets: [
      [
        '@babel/preset-env',
        {
          modules: false,
          // useBuildins and plugin-transform-runtime are mutually exclusive
          // https://github.com/babel/babel/issues/10271#issuecomment-528379505
          // use babel-polyfills when released
          useBuiltIns: false,
          bugfixes: true,
          loose: true
        }
      ]
    ],
    plugins
  })
}

// When few of these get mangled nothing works anymore
// We loose literally nothing by let these unmangled
const classes = [
  'A',
  'ClipPath',
  'Defs',
  'Element',
  'G',
  'Image',
  'Marker',
  'Path',
  'Polygon',
  'Rect',
  'Stop',
  'Svg',
  'Text',
  'Tspan',
  'Circle',
  'Container',
  'Dom',
  'Ellipse',
  'Gradient',
  'Line',
  'Mask',
  'Pattern',
  'Polyline',
  'Shape',
  'Style',
  'Symbol',
  'TextPath',
  'Use'
]

const config = (node, min, esm = false) => ({
  input: node || esm ? './src/main.js' : './src/svg.js',
  output: {
    file: esm
      ? './dist/svg.esm.js'
      : node
        ? './dist/svg.node.cjs'
        : min
          ? './dist/svg.min.js'
          : './dist/svg.js',
    format: esm ? 'esm' : node ? 'cjs' : 'iife',
    name: 'SVG',
    sourcemap: true,
    banner: headerLong,
    // remove Object.freeze
    freeze: false
  },
  treeshake: {
    // property getter have no sideeffects
    propertyReadSideEffects: false
  },
  plugins: [
    resolve({ browser: !node }),
    commonjs(),
    getBabelConfig(node),
    filesize(),
    !min
      ? {}
      : terser({
          mangle: {
            reserved: classes
          },
          output: {
            preamble: headerShort
          }
        })
  ]
})

// [node, minified, esm]
const modes = [[false], [false, true], [true], [false, false, true]]

export default modes.map((m) => config(...m))


================================================
FILE: .config/rollup.polyfills.js
================================================
import resolve from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'
import filesize from 'rollup-plugin-filesize'

// We dont need babel. All polyfills are compatible
const config = (ie) => ({
  input: './.config/polyfillListIE.js',
  output: {
    file: 'dist/polyfillsIE.js',
    format: 'iife'
  },
  plugins: [
    resolve({ browser: true }),
    commonjs(),
    //terser(),
    filesize()
  ]
})

export default [true].map(config)


================================================
FILE: .config/rollup.tests.js
================================================
import * as pkg from '../package.json'
import babel from '@rollup/plugin-babel'
import multiEntry from '@rollup/plugin-multi-entry'
import resolve from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'

const getBabelConfig = (targets) =>
  babel({
    include: ['src/**', 'spec/**/*'],
    babelHelpers: 'runtime',
    babelrc: false,
    presets: [
      [
        '@babel/preset-env',
        {
          modules: false,
          targets: targets || pkg.browserslist,
          // useBuildins and plugin-transform-runtime are mutually exclusive
          // https://github.com/babel/babel/issues/10271#issuecomment-528379505
          // use babel-polyfills when released
          useBuiltIns: false,
          // corejs: 3,
          bugfixes: true
        }
      ]
    ],
    plugins: [
      [
        '@babel/plugin-transform-runtime',
        {
          corejs: 3,
          helpers: true,
          useESModules: true,
          version: '^7.9.6',
          regenerator: false
        }
      ]
    ]
  })

export default {
  input: ['spec/setupBrowser.js', 'spec/spec/*/*.js'],
  output: {
    file: 'spec/es5TestBundle.js',
    name: 'SVGTests',
    format: 'iife'
  },
  plugins: [
    resolve({ browser: true }),
    commonjs(),
    getBabelConfig(),
    multiEntry()
  ],
  external: ['@babel/runtime', '@babel/runtime-corejs3']
}


================================================
FILE: .eslintrc.json
================================================
{
  "parserOptions": {
    "ecmaVersion": "latest",
    "sourceType": "module"
  },
  "env": {
    "browser": true,
    "es6": true
  },
  "extends": ["eslint:recommended", "prettier"],
  "rules": {
    "padded-blocks": "off",
    "no-unused-vars": [
      "error",
      {
        "vars": "all",
        "args": "after-used",
        "ignoreRestSiblings": true,
        "varsIgnorePattern": "^_"
      }
    ]
  }
}


================================================
FILE: .github/CONTRIBUTING.md
================================================
# Contributing

When contributing to this repository, please first discuss the change you wish to make on gitter, or with an issue to increase your chances of getting your pull request merged into the main code base.

## Pull Request Process

When you want to make contributions to the project, the process is pretty simple:

1. Discuss in an issue or on gitter what you'd like to change
2. Fork the repository to make your own local copy
3. Make a branch in the format of <issue-number>-<friendly-name>. So for example if I made an issue to change the default color, and it was issue 385 (random) on the repo, the branch would be called `385-change-default-color`
4. Make the changes to the src and perhaps make a playground by duplicating the playgrounds we already have.
   - When you're done making changes, run `npm run build` to build the code and run the linter
5. If applicable - please write new tests, we like to keep our code well tesvted 🎉. Run the tests by running `npm test`
6. Push the code and make a pull request on the main svg.js repo
7. Enjoy our endless love and gratitude ❤️

Seriously, we love pull requests! So go wild!

## Code of Conduct

We only have a few simple rules, because we know you wouldn't want to read a whole code of conduct guide now would you? 🤡

- don't say anything you wouldn't want said to you
- If you think you can help, then we'd love it if you did! 😃
- Respect everybody
- NEVER be rude

If the contributors feel like you're doing anything rude, we have the right to delete/report your posts. So please just treat everybody nicely, and we can all be great friends!


================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms

github: [fuzzyma]


================================================
FILE: .github/ISSUE_TEMPLATE/bug-report.md
================================================
---
name: Bug Report
about: 🐞 Report a bug that you found
---

# Bug report

> **For support questions, please use [stackoverflow](https://stackoverflow.com/questions/tagged/svg.js) with the tag svg.js or head to our chat over at [gitter](https://gitter.im/svgdotjs/svg.js)**.

## Fiddle

Modify [this fiddle](https://jsfiddle.net/Fuzzy/s06mfv5u/) to demonstrate the problem clearly, just fork it and paste the resulting fiddle in your issue. Please make sure this is a **minimal example**, containing only the minimum necessary code to help us troubleshoot your problem.

## Explanation

- What is the behaviour you expect?
- What is happening instead?
- What error message are you getting?


================================================
FILE: .github/ISSUE_TEMPLATE/feature-request.md
================================================
---
name: Feature Request
about: 🎂 Ask nicely for something you reaaaaaaaally want
---

# Feature request

> **For support questions, please use [stackoverflow](https://stackoverflow.com/questions/tagged/svg.js) with the tag svg.js or head to our chat over at [gitter](https://gitter.im/svgdotjs/svg.js)**.

If you want to make a feature request, here are some guidelines to make a good one:

- Add example code and usage for feature requests to see how a user would use it
- Tell us the benefits (everything is allowed)
- Make a simple use case like the one below. Obviously your feature request shouldn't be so silly. But make it clear to the maintainers what you want added and how you plan to use it 😃

## **Example** Drawing [Smiley the Meme](http://i0.kym-cdn.com/entries/icons/original/000/000/107/smily.jpg)

It would be cool if SVG.js could be used to easily draw smiley the meme, it would make my life so much easier when I want to have memes in my svg.

### Benefits

- Drawing memes would be quick and easy
- Memes are funny

I think the syntax to achieve this should be:

```js
let meme = draw.meme({ radius: 300, cx: 50, cy: 80, lookAt: [30, 50] })
```

Then the user could easily change where the smiley is looking with:

```js
meme.lookAt(50, 40)
// OR
meme.lookAt([30, 20])
// OR
meme.lookAt(new SVG.Point(30, 20))
```


================================================
FILE: .github/ISSUE_TEMPLATE/other.md
================================================
---
name: Other Issue
about: 🍺 Something else...
---

> **For support questions, please use [stackoverflow](https://stackoverflow.com/questions/tagged/svg.js) with the tag svg.js or head to our chat over at [gitter](https://gitter.im/svgdotjs/svg.js), if you have a bug report or feature request, use those templates**.


================================================
FILE: .gitignore
================================================
.DS_Store
.idea
.importjs.js
test/
node_modules/
.vscode/
coverage/
spec/es5TestBundle.js
.env
dist
index.html
index.js
todo.md

================================================
FILE: .prettierignore
================================================
.DS_Store
.idea
.importjs.js
test/
node_modules/
.vscode/
coverage/
spec/es5TestBundle.js
.env
dist
package-lock.json


================================================
FILE: .prettierrc.json
================================================
{
  "trailingComma": "none",
  "tabWidth": 2,
  "semi": false,
  "singleQuote": true
}


================================================
FILE: .travis.yml
================================================
language: node_js
node_js:
  - 'stable'
services:
  - xvfb
addons:
  firefox: latest
  chrome: stable
install:
  - npm install
  - npm run build
script:
  - npm test
  - cat coverage/firefox/lcov.info | node_modules/.bin/coveralls


================================================
FILE: CHANGELOG.md
================================================
# Change Log

All notable changes to this project will be documented in this file.

The document follows the conventions described in [“Keep a CHANGELOG”](http://keepachangelog.com).

====

## [3.2.5]

### Fixed

- fixed import of svg strings with leading comment (#1339)

## [3.2.4]

### Fixed

- fixed dmove for nested svgs (https://github.com/svgdotjs/svg.draggable.js/issues/127)

## [3.2.3]

### Fixed

- fixed import map for father (#1317)

## [3.2.2]

### Fixed

- fixed import map

## [3.2.1]

### Fixed

- skip descriptive elements on rebuild and `toParent()` (#1304)
- allow 0 as animation duration and delay (#1225)
- allow nodes that are not imported yet (#1252)
- only apply color conversion to attributes that can take a color (#1241)
- support css vars (#1230)
- fix import of leading, dont write data to dom if not neccessary
- discontinue use of svgjs:data in favor of data-svg
- allow + as delemiter in paths (#1165)
- added `amove()` methods to runner (#1131)
- fix `css()`, dont throw when screenCtm fails (#968)
- several type fixes

### Added

- add terminate method to timeline so memory can be freed (#1295)
- add more events to sugar (#1217)

## [3.2.0]

### Fixed

- improve performance of `point()` by not creating intermediate objects (#1251)
- fixed references by using single quotes instead of double quotes which lead to errors (#1277)
- fixed a few spelling errors in comments (#1277)
- fix several typings (#1253, #1280, #1300)

### Added

- added second parameter `assignNewId` to `clone()` to allow cloning with the same id (#1161)

## [3.1.2]

### Fixed

- fixed several type issues (#1249, #1233, #1231, #1223, #1215)
- fixed `css()` returning camelCased properties even though they were specified in kebap-case
- fixed `ObjectBag` loosing information when calling `valueOf()` (Numbers lost its unit)
- fixed `parents()` (#1235)
- fixed `nodeOrNew()` to work in object tags as well (#1219)

## [3.1.1]

### Fixed

- fixed typings for tcs 4.2.4 (#1204, #1206, #1203)

## [3.1.0]

### Fixed

- fixed `zoom()` method of runner which was passed a wrong parameter
- fixed positioning methods of `TSpan` to position them by its bounding box
- fixed `flip()` method which flips correctly by center by default now and accepts correct arguments
- fixed a case in `rbox()` where not always all values of the box were updated
- fixed `getOrigin()` function used by `transform()` so that all origin popssibilities specified in the docs are working (#1085)
- fixed positioning of text by its baseline when using `amove()`
- fixed tons of typings in the svg.d.ts file and relaxed type requirements for `put()` and `parent()`
- fixed adopter when adopting an svg/html string. It had still its wrapper as parentNode attached
- fixed `put()` which correctly creates an svgjs object from the passed element now before returning
- fixed `parent()` which correctly returns a Dom instance when parent is the document or document-fragment
- fixed `add()` which correctly removes namespaces of non-root svg elements now when added to another svg element (#1086)
- fixed `isRoot()` which correctly returns false, if the element is in a document-fragment
- fixed `replace()` which works without a parent now, too
- fixed `defs()` which correctly returns `null` when called on a detached node that is not a root node
- fixed `reference()` which correctly returns `null` instead of throwing when specifying an attribute which holds a number
- fixed `flatten()` which correctly flattens now but doesn't accept parameters anymore (makes no sense)
- fixed `ungroup()` which now inserts the elements at the correct position in the correct order and has position as second argument now
- fixed `position` for `transform()` to also allow a position of 0
- fixed `bbox()` of `PathArray` and `PointArray` which returns an instance of `Box` now
- fixed bug in creation of PointArray which had still references to source arrays in it
- fixed `PID` controller and makeSetterGetter function
- fixed `Queue.push` which didnt let you push queue items
- fixed `Timeline.reverse()` which did exactly the opposite of what you would expect when passing `true/false`
- fixed cancelAnimationFrame-mock for tests
- fixed animate when=after to be really "now" when no runner is on the timeline
- fixed animate attr which is also retargetable now
- fixed internals of ObjectBag which can hold other Morphable values now
- fixed animate transform which didnt change its origin on retarget for declarative animations
- fixed path parsing (#1145)
- fixed `clone()` to return the correct instance (#1154)

### Added

- added second Parameter to `SVG(el, isHTML)` which allows to explicitely create elements in the HTML namespace (#1058)
- added `unlink()` and `linker()` to hyperlinked elements to remove or access the underling `<a>` element
- added `wrap()` method to `Dom` which lets you wrap an element by another one
- added `orient()` method to `Marker`
- added `options` parameter to `dispatch()` and `fire()` to allow for more special needs
- added `newLine()` constructor to `Text` to create a tspan marked as new line (#1088)
- added `Fragment` as a wrapper for document-fragment
- added position argument for `toParent()`
- added position argument for `toRoot()`
- added attr syntax for `data()` method
- added index and array parameter when passing a function to `List.each()` so that it mostly behaves like map
- added possibility to pass a transform object to `PointArray.transform()` similar to Point
- added `with-last` as `when` to `animate` and `schedule` to let an animation start with the start of the last one in the timeline
- added lots of tests in es6 format
- added geometry and positioning methods to `A` (#1110)

### Deleted

- deleted undocumented `Matrix.compose()` method which did the same as `new Matrix()` or `Matrix.transform()`
- deleted undocumented `Path.morph()` and `Path.at()` which was replaced with Morphables in v3

## [3.0.16] - 2019-11-12

### Fixed

- fixed build of polyfills which was broken because of core-js update

## [3.0.15] - 2019-11-08

### Fixed

- allow object input of `when` and `delay` to `animate()`

### Added

- added missing dmove function to runner

## [3.0.14] - 2019-10-31

### Fixed

- hide parser from screen readers (#1023)

### Added

- added transpiled esm bundle for webpack und co and faster import

## [3.0.13] - 2019-06-12

### Fixed

- fixed a bug in Timeline.finish() (#964)
- fixed registration of classes with custom bundler
- fixed transform getter (e.g. `el.transform('scale')`)
- fixed typings (#1004)

## [3.0.12] - 2019-02-19

### Fixed

- fixed package.json which points to correct file for webpack now (browser keyword)
- fixed typescript types

### Added

- added `ForeignObject` to the core

## [3.0.11] - 2019-01-22

### Fixed

- fixed move commands (x, y, move) of text so that it moves text always by the upper left edge.
- fixed center commands (cx, cy, center) of text so that it moves text always by the center.

## [3.0.10] - 2019-01-14

### Fixed

- fixed `textPath()`, `path().text()` and `text().path()`
- fixed `root()` method
- fixed default values returned by `attr`. Can be missleading if present.

### Added

- added `findOne()` for better performance

## [3.0.9] - 2019-01-14

### Fixed

- renamed `unit()` to `convert()` due to name collision

## [3.0.8] - 2019-01-13

### Fixed

- added back `to()` as `unit()` of `SVG.Number` which was removed accidentally

## [3.0.7] - 2019-01-13

### Fixed

- fixed a bug in `isNulledBox()` and `domContains()`
- performance changes:
  - replace `getElementsByTagName` with `querySelector`
  - make Color check in `attr` more restrictive to prevent expensive `toString`

## [3.0.6] - 2019-01-12

### Fixed

- fixed group move and size commands
- default font size is not set anymore because it mostly goes against what the user wants
- fix bug in `font()` which set wrong values

### Added

- `PointArray.transform()` (#945)

## [3.0.5] - 2018-12-12

### Fixed

- fixed `parser` which didnt have all required css rules and not focusable=false
- group `x(), y(), width(), height(), dx(), dy()` now correctly change the bbox of the group by moving/resizing all children
- fixed timeline which fired `finished` too early
- fixed `Animator.frame()`. The passed callback gets the current time now (same as RAF)
- allow `loop(true)` which is the same as `loop()`

## [3.0.4] - 2018-12-07

### Fixed

- fixed `zoom` which was added correctly and is animatable now
- fixed `Runner` which merges transformations on the correct frame and in the correct way now
- fixed condition on which transforms get deleted from an element when animating
- fixed `Timeline` which executes Runner in the correct order now
- fixed `Svg` which correctly deletes the defs reference on `clear()`

## [3.0.3] - 2018-12-05

### Fixed

- fixed `Runner` which correctly retains transformations when it is still on a timeline
- fixed `plot()` method of Runner
- fixed `timeline()` so that one can set the timeline of an element now
- fixed `G` and added missing `width/height`

## [3.0.2] - 2018-12-03

### Fixed

- fixed `List` which still didn't have all method names it should have
- fixed `Runner` which correctly handle retargeted controlled animations now
- fixed `Runner` so that it is able to be persisted correctly
- fixed `Color` which correctly handles empty strings now
- fixed `attr` which correctly handles Objects of other kind now
- fixed `Morphable` which correctly calculates the done flag now

## [3.0.1] - 2018-12-03

### Fixed

- fixed `insertBefore`, `insertAfter` and `flip` correctly returning `this`
- fixed `List` which didn't have all method names it should have

## [3.0.0] - 2018-12-01

### Added

- added `text()` method to `SVG.Path` to create a textPath from this path (#705)
- added `SVG.HTMLNode` which is the object wrapped around html nodes to put something in them
- added `dispatch()` method on `SVG.Element` which returns the dispatched event for event cancelation (#550)
- added `isRoot()` on `SVG.Doc` (#809)
- added a linter during the npm build process
- added `beziere()` and `steps()` to generate easing functions
- added `insertAfter()` and `insertBefore`
- added `SVG.Style` which can be created with `style()` or `fontface()` (#517)
- added `EventTarget` which is a baseclass to get event abilities (#641)
- added `Dom` which is a baseclass to get dom abilities
- added `round()` which lets you round attribues from a node
- added `ax(), ay(), amove()` to change texts x and y values directly (#787)
- added possibility to pass attributes into a constructor like: `new SVG.Rect({width:100})`
- added possibility to pass in additional attribues to element creators e.g. `canvas.rect({x:100})` or `canvas.rect(100, 100, {x:100})` (#796)
- added `SVG.List` (#645)
- added `words()` and `element()` to `Dom` because of (#935)
- added lab, lch, hsl and cmyk color spaces (#790)
- added `random()` method on `SVG.Color` to create random colors of different kinds (#939)

### Removed

- removed `SVG.Array.split()` function
- removed workaround for browser bug with stroke-width
- removed polyfills
- removed `SVG.Set` in favour of `SVG.List`
- removed feature to set style with css string (e.g. "fill:none;display:block;")
- removed `loaded()` and `error()` method on `SVG.Image` (#706)
- removed sub-pixel offset fix
- removed `SVG.Nested` (#809)
- removed `show()` from `SVG.A` to avoid name clash (#802)
- removed `size()` from `SVG.Text` to avoid name clash (#799)
- removed `native()` function
- removed `Bare` in favour of `Dom` (#935)
- removed `bower` support because it is deprecated

### Changed

- gradients now have there corresponding node as type and not only radial/linear
- `SVG.Path.pointAt()` correctly returns an `SVG.Point` now
- replaced static reference to `masker` in `SVG.Mask` with the `masker()` method
- replaced static reference to `clipper` in `SVG.ClipPath` with the `clipper()` method
- replaced static reference to `targets` in `SVG.Mask` and `SVG.ClipPath` with the `targets()` method
- moved all regexes to `SVG.regex`
- new constructor signature for `SVG.Image` and `load()`: `container.image(src, callback) / image.load(src, callback)` (#706)
- changed `style()` to `css()`. Now accepts array as input and returns object when no argument given (#517)
- ids are not generated upon creation anymore. Instead they are generated when requested (#559)
- `SVG.extend()` now expects exactly one module or an array of modules
- `SVG.Text.path()` now returns an instance of SVG.TextPath (#705)
- `SVG.Text.path()` does not move all contents to the textPath (#705)
- `SVG.TextPath` now inherits from `SVG.Text` and can be manipulated the same way (#705)
- `SVG.Text.textPath()` returns the first textPaths in the text element (#705)
- renamed `SVG.Stop` constructor `at()` on `SVG.Gradient` to `stop()` (#707)
- renamed `fill()` method on `SVG.Gradient` and `SVG.Pattern` to `url()` (#708)
- renamed `previous()` method to `prev()`
- changed `childNodes` to `children` (same for `firstChild`, `lastChild`, ...) (#710) - changed it back because of performance drop
- moved `defs()` method from `SVG.Parent` to `SVG.Element`
- `SVG()` can be called with css selector, node or svg string, now. Without an argument it creates a new `SVG.Doc()` (#646)
- `add()`, `put()`, `addTo()`, `putIn()` now excepts all arguments accepted by `SVG()`
- all `SVG.*` objects now can have a node as parameter when constructing
- `SVG()` does not set a default size anymore
- default constructor now has an optional `node` argument which is used to consruct the object e.g. `new SVG.Rect(rectNode)`
- SVG.Elements constructor now tries to import svgjs:data from the node
- `SVG.on()` calls the listener in the context of the passed object. el.on always uses the svg.js object as context
- `SVG.on()/off()` and `el.on()/off()` now accepts multiple comma or space separated events e.g. "mousedown, foo bar" (#727)
- Matrices now apply transformations like `scale`, `translate`, etc... by left multiplying them to simplify transformations
- The way `transform()` works is now completely different. See the docs for more as soon as they are updated
- merged `SVG.Doc` and `SVG.Nested`, added `isRoot()` on `SVG.Doc()` (#809)
- The fx module was completely reworked to be faster and less error prone. For more information on how to use it refer to the docs
- The whole lib is now splitted into es6 modules (#875)
- `Element.svg()` now can can replace the current node, can export the children of a node and can take an export modifier to change/replace the exported nodes
- `ungroup()` now breaks off one container and not more
- `clone()` does not add the clone to the dom anymore
- `attr()` excepts array now to get multiple values at once
- `SVG.Text.rebuild()` now takes every font-size into account (#512)
- `fill()` and `stroke()` return the fill and stroke attribute when called as getter (#789)
- `parents()` now gives back all parents until the passed one or document
- `Image` callback passes normal `load` event instead of custom object (#931)
- renamed `Doc` to `Svg` and `doc()` to `root` (and `toDoc()/toRoot()`) (#932)

## [2.7.1] - 2018-11-30

### Fixed

- CustomEvent-polyfill was not used (needed in IE) (#938)

## [2.7.0] - 2018-11-13

### Fixed

- fixed calling `parent()` on `documentFragment`s children (#927)
- parser is not focusable anymore (#908)
- `SVG.Element.click(null)` correctly unbinds the event (#878)
- fix memory leak (#905)

### Added

- `SVG.Set` now accepts another Set as input (#893)
- `on()/off()` accepts multiple event names as input (backport from 3.0)

## [2.6.6] - 2018-08-30

### Added

- added global reference to support 'window' in bundlers (#767)

## [2.6.5] - 2018-05-26

### Fixed

- fixed `element.parent()` which sometimes failed when used on detached documents (#759)
- fixed `SVG.Text.y()` which didnt work correctly with `SVG.Number` (#778)
- fixed `SVG.Doc.clone()` which throwed an error (#782)
- fixed `SVG.Mask.clone()` which throwed an error (#782)
- fixed `SVG.PointArray` having a reference to outside array in some cases (#803)
- fixed `reference()` which failed when trying to use a reference which does not exist in the attribuets (#840)
- fixed `animate().attr()` method which doenst work for `d` attribute of paths (#847)
- fixed problems with `CustomEvent` polyfill in IE11 (#852)

### Added

- added possibility to pass an array of point objects to SVG.PointArray (#803)

## [2.6.4] - 2018-02-07

### Fixed

- fixed memory leak when creating images (#805)

## [2.6.3] - 2017-07-21

### Fixed

- fixed error in parent method when hitting document node (#720)

## [2.6.2] - 2017-06-05

### Added

- added `width()` and `height()` methods to `SVG.FX`
- added the intended functionality to call animate functions with multiple parameter (#671)

### Changed

- updated Jasmine from 2.5.2 to 2.6.0
- removed the typeof check in the initialisation of SVG.Matrix

### Fixed

- fixed `SVG.FX.once` so that it add its callback on the last situation instead of the current one
- fixed `SVG.FX.step` so that the animation doesn't stop if an afterAll callback call animate (#677)

## [2.6.1] - 2017-04-25

### Fixed

- fixed a bug in path parser which made it stop parsing when hitting z command (#665)

## [2.6.1] - 2017-04-25

### Fixed

- fixed a bug in path parser which made it stop parsing when hitting z command (#665)

## [2.6.0] - 2017-04-21

### Added

- added `options` object to `SVG.on()` and `el.on()` (#661)

### Changed

- back to sloppy mode because of problems with plugins (#660)

## [2.5.3] - 2017-04-15

### Added

- added gitter badge in readme

### Fixed

- fixed svg.js.d.ts (#644 #648)
- fixed bug in `el.flip()` which causes an error when calling flip without any argument

### Removed

- component.json (#652)

## [2.5.2] - 2017-04-11

### Changed

- SVG.js is now running in strict mode

### Fixed

- `clear()` does not remove the parser in svg documents anymore
- `len` not declared in FX module, making it a global variable (9737e8a)
- `bbox` not declared in SVG.Box.transform in the Box module (131df0f)
- `namespace` not declared in the Event module (e89c97e)

## [2.5.1] - 2017-03-27

### Changed

- make svgjs ready to be used on the server

### Fixed

- fixed `SVG.PathArray.parse` that did not correctly parsed flat arrays
- prevented unnecessary parsing of point or path strings

## [2.5.0] - 2017-03-10

### Added

- added a plot and array method to `SVG.TextPath` (#582)
- added `clone()` method to `SVG.Array/PointArray/PathArray` (#590)
- added `font()` method to `SVG.Tspan`
- added `SVG.Box()`
- added `transform()` method to boxes
- added `event()` to `SVG.Element` to retrieve the event that was fired last on the element (#550)

### Changed

- changed CHANGELOG to follow the conventions described in [“Keep a CHANGELOG”](http://keepachangelog.com) (#578)
- make the method plot a getter when no parameter is passed for `SVG.Polyline`,`SVG.Polygon`, `SVG.Line`, `SVG.Path` (related #547)
- allow `SVG.PointArray` to be passed flat array
- change the regexp `SVG.PointArray` use to parse string to allow more flexibility in the way spaces and commas can be used
- allow `plot` to be called with 4 parameters when animating an `SVG.Line`
- relative value for `SVG.Number` are now calculated in its `morph` method (related #547)
- clean up the implementation of the `initAnimation` method of the FX module (#547, #552, #584)
- deprecated `.tbox()`. `.tbox()` now map to `.rbox()`. If you are using `.tbox()`, you can substitute it with `.rbox()` (#594, #602)
- all boxes now accept 4 values or an object on creation
- `el.rbox()` now always returns the right boxes in screen coordinates and has an additional paramater to transform the box into other coordinate systems
- `font()` method can now be used like `attr()` method (#620)
- events are now cancelable by default (#550)

### Fixed

- fixed a bug in the plain morphing part of `SVG.MorphObj` that is in the FX module
- fixed bug which produces an error when removing an event from a node which was formerly removed with a global `off()` (#518)
- fixed a bug in `size()` for poly elements when their height/width is zero (#505)
- viewbox now also accepts strings and arrays as constructor arguments
- `SVG.Array` now accepts a comma seperated string and returns array of numbers instead of strings
- `SVG.Matrix` now accepts an array as input
- `SVG.Element.matrix()` now accepts also 6 values
- `dx()/dy()` now accepts percentage values, too but only if the value on the element is already percentage
- `flip()` now flips on both axis when no parameter is passed
- fixed bug with `documentElement.contains()` in IE
- fixed offset produced by svg parser (#553)
- fixed a bug with clone which didnt copy over dom data (#621)

## [2.4.0] - 2017-01-14

### Added

- added support for basic path animations (#561)

## [2.3.7] - 2017-01-14

### Added

- added code coverage https://coveralls.io/github/svgdotjs/svg.js (3e614d4)
- added `npm run test:quick` which aim at being fast rather than correct - great for git hooks (981ce24)

### Changed

- moved project to [svgdotjs](https://github.com/svgdotjs)
- made matrixify work with transformation chain separated by commas (#543)
- updated dev dependencies; request and gulp-chmod - `npm run build` now requires nodejs 4.x+

### Fixed

- fixed `SVG.Matrix.skew()` (#545)
- fixed broken animations, if using polyfills for es6/7 proposals (#504)
- fixed and improved `SVG.FX.dequeue()` (#546)
- fixed an error in `SVG.FX.step`, if custom properties is added to `Array.prototype` (#549)

## [2.3.6] - 2016-10-21

### Changed

- make SVG.FX.loop modify the last situation instead of the current one (#532)

### Fixed

- fixed leading and trailing space in SVG.PointArray would return NaN for some points (695f26a) (#529)
- fixed test of `SVG.FX.afterAll` (#534)
- fixed `SVG.FX.speed()` (#536)

## [2.3.5] - 2016-10-13

### Added

- added automated unit tests via [Travis](https://travis-ci.org/svgdotjs/svg.js) (#527)
- added `npm run build` to build a new version of SVG.js without requiring gulp to be globally installed

### Changed

- calling `fill()`, `stroke()` without an argument is now a nop
- Polygon now accepts comma less points to achieve parity with Adobe Illustrator (#529)
- updated dependencies

## [2.3.4] - 2016-08-04

### Changed

- reworked parent module for speed improvemenents
- reworked `filterSVGElements` utility to use a for loop instead of the native filter function

## [2.3.3] - 2016-08-02

### Added

- add error callback on image loading (#508)

### Fixed

- fixed bug when getting bbox of text elements which are not in the dom (#514)
- fixed bug when getting bbox of element which is hidden with css (#516)

## [2.3.2] - 2016-06-21

### Added

- added specs for `SVG.ViewBox`
- added `parent` parameter for `clone()`
- added spec for mentioned issue

### Fixed

- fixed string parsing in viewbox (#483)
- fixed bbox when element is not in the dom (#480)
- fixed line constructor which doesn't work with Array as input (#487)
- fixed problem in IE with `document.contains` (#490) related to (#480)
- fixed `undo` when undoing transformations (#494)

## [2.3.1] - 2016-05-05

### Added

- added typings for svg.js (#470)

### Fixed

- fixed `SVG.morph()` (#473)
- fixed parser error (#471)
- fixed bug in `SVG.Color` with new fx
- fixed `radius()` for circles when animating and other related code (#477)
- fixed bug where `stop(true)` throws an error when element is not animated (#475)
- fixed bug in `add()` when altering svgs with whitespaces
- fixed bug in `SVG.Doc().create` where size was set to 100% even if size was already specified
- fixed bug in `parse()` from `SVG.PathArray` which does not correctly handled `S` and `T` (#485)

## [2.3.0] - 2016-03-30

### Added

- added `SVG.Point` which serves as Wrapper to the native `SVGPoint` (#437)
- added `element.point(x,y)` which transforms a point from screen coordinates to the elements space (#403)
- added `element.is()` which helps to check for the object instance faster (instanceof check)
- added more fx specs

### Changed

- textpath now is a parent element, the lines method of text will return the tspans inside the textpath (#450)
- fx module rewritten to support animation chaining and several other stuff (see docs)

### Fixed

- fixed `svgjs:data` attribute which was not set properly in all browsers (#428)
- fixed `isNumber` and `numberAndUnit` regex (#405)
- fixed error where a parent node is not found when loading an image but the canvas was cleared (#447)
- fixed absolute transformation animations (not perfect but better)
- fixed event listeners which didnt work correctly when identic funtions used

## [2.2.5] - 2015-12-29

### Added

- added check for existence of node (#431)

### Changed

- `group.move()` now allows string numbers as input (#433)
- `matrixify()` will not apply the calculated matrix to the node anymore

## [2.2.4] - 2015-12-12

### Fixed

- fixed `transform()` which returns the matrix values (a-f) now, too (#423)
- double newlines (\n\n) are correctly handled as blank line from `text()`
- fixed use of scrollX vs pageXOffset in `rbox()` (#425)
- fixed target array in mask and clip which was removed instead of reinitialized (#429)

## [2.2.3] - 2015-11-30

### Fixed

- fixed null check in image (see 2.2.2)
- fixed bug related to the new path parser (see 2.2.2)
- fixed amd loader (#412)

## [2.2.2] - 2015-11-28

### Added

- added null check in image onload callback (#415)

### Changed

- documentation rework (#407) [thanks @snowyplover]

### Fixed

- fixed leading point bug in path parsing (#416)

## [2.2.1] - 2015-11-18

### Added

- added workaround for `SvgPathSeg` which is removed in Chrome 48 (#409)
- added `gbox()` to group to get bbox with translation included (#405)

### Fixed

- fixed dom data which was not cleaned up properly (#398)

## [2.2.0] - 2015-11-06

### Added

- added `ungroup()/flatten()` (#238), `toParent()` and `toDoc()`
- added UMD-Wrapper with possibility to pass custom window object (#352)
- added `morph()` method for paths via plugin [svg.pathmorphing.js](https://github.com/Fuzzyma/svg.pathmorphing.js)
- added support for css selectors within the `parent()` method
- added `parents()` method to get an array of all parenting elements

### Changed

- svgjs now saves crucial data in the dom before export and restores them when element is adopted

### Fixed

- fixed pattern and gradient animation (#385)
- fixed mask animation in Firefox (#287)
- fixed return value of `text()` after import/clone (#393)

## [2.1.1] - 2015-10-03

### Added

- added custom context binding to event callback (default is the element the event is bound to)

## [2.1.0] - 2015-09-20

### Added

- added transform to pattern and gradients (#383)

### Fixed

- fixed clone of textnodes (#369)
- fixed transformlists in IE (#372)
- fixed typo that leads to broken gradients (#370)
- fixed animate radius for circles (#367)

## [2.0.2] - 2015-06-22

### Fixed

- Fixed zoom consideration in circle and ellipse

## [2.0.1] - 2015-06-21

### Added

- added possibility to remove all events from a certain namespace

### Fixed

- fixed bug with `doc()` which always should return root svg
- fixed bug in `SVG.FX` when animating with `plot()`

### Removed

- removed target reference from use which caused bugs in `dmove()` and `use()` with external file
- removed scale consideration in `move()` duo to incompatibilities with other move-functions e.g. in `SVG.PointArray`

## [2.0.0] - 2015-06-11

### Added

- implemented an SVG adoption system to be able to manipulate existing SVG's not created with svg.js
- added polyfill for IE9 and IE10 custom events [thanks @Fuzzyma]
- added DOM query selector with the `select()` method globally or on parent elements
- added the intentionally neglected `SVG.Circle` element
- added `rx()` and `ry()` to `SVG.Rect`, `SVG.Circle`, `SVG.Ellispe` and `SVG.FX`
- added support to clone manually built text elements
- added `svg.wiml.js` plugin to plugins list
- added `ctm()` method to for matrix-centric transformations
- added `morph()` method to `SVG.Matrix`
- added support for new matrix system to `SVG.FX`
- added `native()` method to elements and matrix to get to the native api
- added `untransform()` method to remove all transformations
- added raw svg import functionality with the `svg()` method
- added coding style description to README
- added reverse functionality for animations
- documented the `situation` object in `SVG.FX`
- added distinction between relative and absolute matrix transformations
- implemented the `element()` method using the `SVG.Bare` class to create elements that are not described by SVG.js
- added `w` and `h` properties as shorthand for `width` and `height` to `SVG.BBox`
- added `SVG.TBox` to get a bounding box that is affected by transformation values
- added event-based or complete detaching of event listeners in `off()` method

### Changed

- changed `parent` reference on elements to `parent()` method
- using `CustomEvent` instead of `Event` to be able to fire events with a `detail` object [thanks @Fuzzyma]
- renamed `SVG.TSpan` class to `SVG.Tspan` to play nice with the adoption system
- completely reworked `clone()` method to use the adoption system
- completely reworked transformations to be chainable and more true to their nature
- changed `lines` reference to `lines()` on `SVG.Text`
- changed `track` reference to `track()` on `SVG.Text`
- changed `textPath` reference to `textPath()` on `SVG.Text`
- changed `array` reference to `array()` method on `SVG.Polyline`, `SVG.Polygon` and `SVG.Path`
- reworked sup-pixel offset implementation to be more compact
- switched from Ruby's `rake` to Node's `gulp` for building [thanks to Alex Ewerlöf]
- changed `to()` method to `at()` method in `SVG.FX`
- renamed `SVG.SetFX` to `SVG.FX.Set`
- reworked `SVG.Number` to return new instances with calculations rather than itself
- reworked animatable matrix rotations
- removed `SVG.Symbol` but kept the `symbol()` method using the new `element()` method

### Fixed

- fixed bug in `radius()` method when `y` value equals `0`
- fixed a bug where events are not detached properly

## [1.0.0-rc.9] - 2014-06-17

### Added

- added `SVG.Marker`
- added `SVG.Symbol`
- added `first()` and `last()` methods to `SVG.Set`
- added `length()` method to `SVG.Text` and `SVG.TSpan` to calculate total text length
- added `reference()` method to get referenced elements from a given attribute value

### Changed

- `SVG.get()` will now also fetch elements with a `xlink:href="#elementId"` or `url(#elementId)` value given

### Fixed

- fixed infinite loop in viewbox when element has a percentage width / height [thanks @shabegger]

## [1.0.0-rc.8] - 2014-06-12

### Fixed

- fixed bug in `SVG.off`
- fixed offset by window scroll position in `rbox()` [thanks @bryhoyt]

## [1.0.0-rc.7] - 2014-06-11

### Added

- added `classes()`, `hasClass()`, `addClass()`, `removeClass()` and `toggleClass()` [thanks @pklingem]

### Changed

- binding events listeners to svg.js instance
- calling `after()` when calling `stop(true)` (fulfill flag) [thanks @vird]
- text element fires `rebuild` event whenever the `rebuild()` method is called

### Fixed

- fixed a bug where `Element#style()` would not save empty values in IE11 [thanks @Shtong]
- fixed `SVG is not defined error` [thanks @anvaka]
- fixed a bug in `move()`on text elements with a string based value
- fix for `text()` method on text element when acting as getter [thanks @Lochemage]
- fix in `style()` method with a css string [thanks @TobiasHeckel]

## [1.0.0-rc.6] - 2014-03-03

### Added

- added `leading()` method to `SVG.FX`
- added `reverse()` method to `SVG.Array` (and thereby also to `SVG.PointArray` and `SVG.PathArray`)
- added `fulfill` option to `stop()` method in `SVG.FX` to finalise animations
- added more output values to `bbox()` and `rbox()` methods

### Changed

- fine-tuned text element positioning
- calling `at()` method directly on morphable svg.js instances in `SVG.FX` module
- moved most `_private` methods to local named functions
- moved helpers to a separate file

### Fixed

- fixed a bug in text `dy()` method

### Removed

- removed internal representation for `style`

## [1.0.0-rc.5] - 2014-02-14

### Added

- added `plain()` method to `SVG.Text` element to add plain text content, without tspans
- added `plain()` method to parent elements to create a text element without tspans
- added `build()` to enable/disable build mode

### Changed

- updated `SVG.TSpan` to accept nested tspan elements, not unlike the `text()` method in `SVG.Text`
- removed the `relative()` method in favour of `dx()`, `dy()` and `dmove()`
- switched form objects to arrays in `SVG.PathArray` for compatibility with other libraries and better performance on parsing and rendering (up-to 48% faster than 1.0.0-rc.4)
- refined docs on element-specific methods and `SVG.PathArray` structure
- reworked `leading()` implementation to be more font-size "aware"
- refactored the `attr` method on `SVG.Element`
- applied Helvetica as default font
- building `SVG.FX` class with `SVG.invent()` function

### Removed

- removed verbose style application to tspans

## [1.0.0-rc.4] - 2014-02-04

### Added

- automatic pattern creation by passing an image url or instance as `fill` attribute on elements
- added `loaded()` method to image tag
- added `pointAt()` method to `SVG.Path`, wrapping the native `getPointAtLength()`

### Changed

- switched to `MAJOR`.`MINOR`.`PATCH` versioning format to play nice with package managers
- made svg.pattern.js part of the core library
- moved `length()` method to sugar module

### Fixed

- fix in `animate('=').to()`
- fix for arcs in patharray `toString()` method [thanks @dotnetCarpenter]

## [v1.0rc3] - 2014-02-03

### Added

- added the `SVG.invent` function to ease invention of new elements
- added second values for `animate('2s')`
- added `length()` mehtod to path, wrapping the native `getTotalLength()`

### Changed

- using `SVG.invent` to generate core shapes as well for leaner code

### Fixed

- fix for html-less documents
- fix for arcs in patharray `toString()` method

## [v1.0rc2] - 2014-02-01

### Added

- added `index()` method to `SVG.Parent` and `SVG.Set`
- added `morph()` and `at()` methods to `SVG.Number` for unit morphing

### Changed

- modified `cx()` and `cy()` methods on elements with native `x`, `y`, `width` and `height` attributes for better performance

## [v1.0rc1] - 2014-01-31

### Added

- added `SVG.PathArray` for real path transformations
- added `bbox()` method to `SVG.Set`
- added `relative()` method for moves relative to the current position
- added `morph()` and `at()` methods to `SVG.Color` for color morphing

### Changed

- enabled proportional resizing on `size()` method with `null` for either `width` or `height` values
- moved data module to separate file
- `data()` method now accepts object for for multiple key / value assignments

### Removed

- removed `unbiased` system for paths

## [v0.38] - 2014-01-28

### Added

- added `loop()` method to `SVG.FX`

### Changed

- switched from `setInterval` to `requestAnimFrame` for animations

## [v0.37] - 2014-01-26

### Added

- added `get()` to `SVG.Set`

### Changed

- moved `SVG.PointArray` to a separate file

## [v0.36] - 2014-01-25

### Added

- added `linkTo()`, `addTo()` and `putIn()` methods on `SVG.Element`

### Changed

- provided more detailed documentation on parent elements

### Fixed

## [v0.35] - 2014-01-23

### Added

- added `SVG.A` element with the `link()`

## [v0.34] - 2014-01-23

### Added

- added `pause()` and `play()` to `SVG.FX`

### Changed

- storing animation values in `situation` object

## [v0.33] - 2014-01-22

### Added

- added `has()` method to `SVG.Set`
- added `width()` and `height()` as setter and getter methods on all shapes
- added `replace()` method to elements
- added `radius()` method to `SVG.Rect` and `SVG.Ellipse`
- added reference to parent node in defs

### Changed

- moved sub-pixel offset fix to be an optional method (e.g. `SVG('drawing').fixSubPixelOffset()`)
- merged plotable.js and path.js

## [v0.32]

### Added

- added library to [cdnjs](http://cdnjs.com)

<!-- Headings above link to the releases listed here -->

[3.2.5]: https://github.com/svgdotjs/svg.js/releases/tag/3.2.5
[3.2.4]: https://github.com/svgdotjs/svg.js/releases/tag/3.2.4
[3.2.3]: https://github.com/svgdotjs/svg.js/releases/tag/3.2.3
[3.2.2]: https://github.com/svgdotjs/svg.js/releases/tag/3.2.2
[3.2.1]: https://github.com/svgdotjs/svg.js/releases/tag/3.2.1
[3.2.0]: https://github.com/svgdotjs/svg.js/releases/tag/3.2.0
[3.1.2]: https://github.com/svgdotjs/svg.js/releases/tag/3.1.2
[3.1.1]: https://github.com/svgdotjs/svg.js/releases/tag/3.1.1
[3.1.0]: https://github.com/svgdotjs/svg.js/releases/tag/3.1.0
[3.0.16]: https://github.com/svgdotjs/svg.js/releases/tag/3.0.16
[3.0.15]: https://github.com/svgdotjs/svg.js/releases/tag/3.0.15
[3.0.14]: https://github.com/svgdotjs/svg.js/releases/tag/3.0.14
[3.0.13]: https://github.com/svgdotjs/svg.js/releases/tag/3.0.13
[3.0.12]: https://github.com/svgdotjs/svg.js/releases/tag/3.0.12
[3.0.11]: https://github.com/svgdotjs/svg.js/releases/tag/3.0.11
[3.0.10]: https://github.com/svgdotjs/svg.js/releases/tag/3.0.10
[3.0.9]: https://github.com/svgdotjs/svg.js/releases/tag/3.0.9
[3.0.8]: https://github.com/svgdotjs/svg.js/releases/tag/3.0.8
[3.0.7]: https://github.com/svgdotjs/svg.js/releases/tag/3.0.7
[3.0.6]: https://github.com/svgdotjs/svg.js/releases/tag/3.0.6
[3.0.5]: https://github.com/svgdotjs/svg.js/releases/tag/3.0.5
[3.0.4]: https://github.com/svgdotjs/svg.js/releases/tag/3.0.4
[3.0.3]: https://github.com/svgdotjs/svg.js/releases/tag/3.0.3
[3.0.2]: https://github.com/svgdotjs/svg.js/releases/tag/3.0.2
[3.0.1]: https://github.com/svgdotjs/svg.js/releases/tag/3.0.1
[3.0.0]: https://github.com/svgdotjs/svg.js/releases/tag/3.0.0
[2.7.1]: https://github.com/svgdotjs/svg.js/releases/tag/2.7.1
[2.7.0]: https://github.com/svgdotjs/svg.js/releases/tag/2.7.0
[2.6.6]: https://github.com/svgdotjs/svg.js/releases/tag/2.6.6
[2.6.5]: https://github.com/svgdotjs/svg.js/releases/tag/2.6.5
[2.6.4]: https://github.com/svgdotjs/svg.js/releases/tag/2.6.4
[2.6.3]: https://github.com/svgdotjs/svg.js/releases/tag/2.6.3
[2.6.2]: https://github.com/svgdotjs/svg.js/releases/tag/2.6.2
[2.6.1]: https://github.com/svgdotjs/svg.js/releases/tag/2.6.1
[2.6.0]: https://github.com/svgdotjs/svg.js/releases/tag/2.6.0
[2.5.3]: https://github.com/svgdotjs/svg.js/releases/tag/2.5.3
[2.5.2]: https://github.com/svgdotjs/svg.js/releases/tag/2.5.2
[2.5.1]: https://github.com/svgdotjs/svg.js/releases/tag/2.5.1
[2.5.0]: https://github.com/svgdotjs/svg.js/releases/tag/2.5.0
[2.4.0]: https://github.com/svgdotjs/svg.js/releases/tag/2.4.0
[2.3.7]: https://github.com/svgdotjs/svg.js/releases/tag/2.3.7
[2.3.6]: https://github.com/svgdotjs/svg.js/releases/tag/2.3.6
[2.3.5]: https://github.com/svgdotjs/svg.js/releases/tag/2.3.5
[2.3.4]: https://github.com/svgdotjs/svg.js/releases/tag/2.3.4
[2.3.3]: https://github.com/svgdotjs/svg.js/releases/tag/2.3.3
[2.3.2]: https://github.com/svgdotjs/svg.js/releases/tag/2.3.2
[2.3.1]: https://github.com/svgdotjs/svg.js/releases/tag/2.3.1
[2.3.0]: https://github.com/svgdotjs/svg.js/releases/tag/2.3.0
[2.2.5]: https://github.com/svgdotjs/svg.js/releases/tag/2.2.5
[2.2.4]: https://github.com/svgdotjs/svg.js/releases/tag/2.2.4
[2.2.3]: https://github.com/svgdotjs/svg.js/releases/tag/2.2.3
[2.2.2]: https://github.com/svgdotjs/svg.js/releases/tag/2.2.2
[2.2.1]: https://github.com/svgdotjs/svg.js/releases/tag/2.2.1
[2.2.0]: https://github.com/svgdotjs/svg.js/releases/tag/2.2.0
[2.1.1]: https://github.com/svgdotjs/svg.js/releases/tag/2.1.1
[2.1.0]: https://github.com/svgdotjs/svg.js/releases/tag/2.1.0
[2.0.2]: https://github.com/svgdotjs/svg.js/releases/tag/2.0.2
[2.0.1]: https://github.com/svgdotjs/svg.js/releases/tag/2.0.1
[2.0.0]: https://github.com/svgdotjs/svg.js/releases/tag/2.0.0
[1.0.0-rc.9]: https://github.com/svgdotjs/svg.js/releases/tag/1.0.0-rc.9
[1.0.0-rc.8]: https://github.com/svgdotjs/svg.js/releases/tag/1.0.0-rc.8
[1.0.0-rc.7]: https://github.com/svgdotjs/svg.js/releases/tag/1.0.0-rc.7
[1.0.0-rc.6]: https://github.com/svgdotjs/svg.js/releases/tag/1.0.0-rc.6
[1.0.0-rc.5]: https://github.com/svgdotjs/svg.js/releases/tag/1.0.0-rc.5
[1.0.0-rc.4]: https://github.com/svgdotjs/svg.js/releases/tag/1.0.0-rc.4
[v1.0rc3]: https://github.com/svgdotjs/svg.js/releases/tag/1.0rc3
[v1.0rc2]: https://github.com/svgdotjs/svg.js/releases/tag/1.0rc2
[v1.0rc1]: https://github.com/svgdotjs/svg.js/releases/tag/1.0rc1
[v0.38]: https://github.com/svgdotjs/svg.js/releases/tag/0.38
[v0.37]: https://github.com/svgdotjs/svg.js/releases/tag/0.37
[v0.36]: https://github.com/svgdotjs/svg.js/releases/tag/0.36
[v0.35]: https://github.com/svgdotjs/svg.js/releases/tag/0.35
[v0.34]: https://github.com/svgdotjs/svg.js/releases/tag/0.34
[v0.33]: https://github.com/svgdotjs/svg.js/releases/tag/0.33
[v0.32]: https://github.com/svgdotjs/svg.js/releases/tag/0.32


================================================
FILE: LICENSE.txt
================================================
Copyright (c) 2012-2018 Wout Fierens
https://svgdotjs.github.io/

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
================================================
# SVG.js

[![Build Status](https://travis-ci.org/svgdotjs/svg.js.svg?branch=master)](https://travis-ci.org/svgdotjs/svg.js)
[![Coverage Status](https://coveralls.io/repos/github/svgdotjs/svg.js/badge.svg?branch=master)](https://coveralls.io/github/svgdotjs/svg.js?branch=master)
[![Cdnjs](https://img.shields.io/cdnjs/v/svg.js.svg)](https://cdnjs.com/libraries/svg.js)
[![jsdelivr](https://badgen.net/jsdelivr/v/npm/@svgdotjs/svg.js)](https://cdn.jsdelivr.net/npm/@svgdotjs/svg.js)
[![Join the chat at https://gitter.im/svgdotjs/svg.js](https://badges.gitter.im/svgdotjs/svg.js.svg)](https://gitter.im/svgdotjs/svg.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Twitter](https://img.shields.io/badge/Twitter-@svg__js-green.svg)](https://twitter.com/svg_js)

**A lightweight library for manipulating and animating SVG, without any dependencies.**

SVG.js is licensed under the terms of the MIT License.

## Installation

#### Npm:

`npm install @svgdotjs/svg.js`

#### Yarn:

`yarn add @svgdotjs/svg.js`

#### CDNs:

[https://cdnjs.com/libraries/svg.js](https://cdnjs.com/libraries/svg.js)  
[https://cdn.jsdelivr.net/npm/@svgdotjs/svg.js](https://cdn.jsdelivr.net/npm/@svgdotjs/svg.js)  
[https://unpkg.com/@svgdotjs/svg.js](https://unpkg.com/@svgdotjs/svg.js)

## Documentation

Check [svgjs.dev](https://svgjs.dev/docs/3.0/) to learn more.

[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=ulima.ums%40googlemail.com&lc=US&item_name=SVG.JS&currency_code=EUR&bn=PP-DonationsBF%3Abtn_donate_74x21.png%3ANonHostedGuest) or [![Sponsor](https://img.shields.io/badge/Sponsor-svg.js-green.svg)](https://github.com/sponsors/Fuzzyma)


================================================
FILE: bench/runner.html
================================================
<!doctype html>
<html>
  <head>
    <title>SVG.js benchmarker</title>
    <style>
      @import url('https://fonts.googleapis.com/css?family=Inconsolata');
      body {
        font-family: 'Inconsolata', 'Menlo', monospace;
        font-weight: 300;
        color: #999;
        font-size: 14px;
      }
      svg {
        width: 2px;
        height: 2px;
        overflow: hidden;
        position: fixed;
        right: 0;
      }
      span.name {
        color: #b7cd3e;
      }
      span.ms {
        color: #ff0066;
      }
      h1 {
        font-size: 1.2em;
      }
      .test {
        text-indent: 1em;
      }
      .skipped {
        color: #fbcb72;
      }
    </style>
  </head>
  <body>
    <div id="draw"></div>
    <svg
      id="native"
      width="100"
      height="100"
      xmlns="http://www.w3.org/2000/svg"
      version="1.1"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      xmlns:svgjs="http://svgjs.dev/svgjs"
    ></svg>
    <script src="../dist/svg.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.5.1/snap.svg-min.js"></script>
    <script src="svg.bench.js"></script>
    <!--<script src="tests/10000-each.js"></script> -->
    <script src="tests/10000-rects.js"></script>
    <!-- <script src="tests/10000-circles.js"></script>
  <script src="tests/10000-paths.js"></script>
  <script src="tests/10000-boxes.js"></script>
  <script src="tests/10000-pointArray-bbox.js"></script>
  <script src="tests/10000-accesses.js"></script>
  <script src="tests/10000-transform.js"></script> -->
    <script>
      SVG.bench.run()
    </script>
  </body>
</html>


================================================
FILE: bench/svg.bench.js
================================================
/* global Snap */

;(function () {
  SVG.bench = {
    // Initalize test store
    _chain: [],
    _before: function () {},
    _after: function () {},
    draw: SVG().addTo('#draw'),
    snap: Snap(100, 100),
    raw: document.getElementById('native'),

    // Add descriptor
    describe: function (name, closure) {
      this._chain.push({
        name: name,
        run: closure
      })

      return this
    },

    // Add test
    test: function (name, run) {
      // run test
      var start = new Date().getTime()
      run()
      this.write(name, new Date().getTime() - start)

      // clear everything
      this.clear()
    },

    // Skip test
    skip: function (name, run) {
      this.write(name, false)
    },

    // Run tests
    run: function () {
      this.pad()

      for (var h, i = 0, il = this._chain.length; i < il; i++) {
        h = document.createElement('h1')
        h.innerHTML = this._chain[i].name
        this.pad().appendChild(h)
        this._chain[i].run(this)
      }
    },

    // Write result
    write: function (name, ms) {
      var test = document.createElement('div')

      if (typeof ms === 'number') {
        test.className = 'test'
        test.innerHTML =
          '<span class="name">' +
          name +
          '</span> completed in <span class="ms">' +
          ms +
          'ms</span>'
      } else {
        test.className = 'test skipped'
        test.innerHTML = name + ' (skipped)'
      }

      this.pad().appendChild(test)

      return this
    },

    // Reference writable element
    pad: function () {
      var pad = document.getElementById('pad')

      if (!pad) {
        pad = document.createElement('div')
        document.getElementsByTagName('body')[0].appendChild(pad)
      }

      return pad
    },

    // Clear canvasses
    clear: function () {
      while (this.raw.hasChildNodes()) {
        this.raw.removeChild(this.raw.lastChild)
      }
      this.draw.clear()
      this.snap.clear()
    }
  }
})()


================================================
FILE: bench/tests/10000-accesses.js
================================================
SVG.bench.describe(
  'Access a dom attributes vs dom properties vs object properties',
  function (bench) {
    bench.test('using an object', function () {
      var sum = 0
      var obj = { x: '30' }
      for (var i = 0; i < 1000000; i++) {
        sum += obj.x * i
      }
      console.log(sum)
    })

    bench.test('figure out what the overhead is', function () {
      var obj = bench.draw.rect(100, 100).move(0, 0)
    })

    bench.test('using dom attributes', function () {
      var sum = 0
      var obj = bench.draw.rect(100, 100).move(0, 0)
      var node = obj.node
      for (var i = 0; i < 1000000; i++) {
        sum += node.getAttribute('x') * i
      }
      console.log(sum, node.getAttribute('x'))
    })

    bench.test('using dom properties', function () {
      var sum = 0
      var obj = bench.draw.rect(100, 100).move(0, 0)
      var node = obj.node
      for (var i = 0; i < 1000000; i++) {
        sum += node.x.baseVal * i
      }
      console.log(sum, node.x)
    })
  }
)


================================================
FILE: bench/tests/10000-boxes.js
================================================
SVG.bench.describe('Generate 100000 bbox', function (bench) {
  var rect = bench.draw.rect(100, 100)

  bench.test('using SVG.js v3.0.0', function () {
    for (var i = 0; i < 100000; i++) rect.bbox()
  })
  //bench.test('using vanilla js', function() {
  //  var node = rect.node
  //  for (var i = 0; i < 10000; i++) {
  //    node.getBBox()
  //  }
  //})
  //bench.test('using Snap.svg v0.5.1', function() {
  //  for (var i = 0; i < 10000; i++)
  //    bench.snap.rect(50, 50, 100, 100)
  //})
})

SVG.bench.describe('Generate 100000 rbox', function (bench) {
  var rect = bench.draw.rect(100, 100)

  bench.test('using SVG.js v3.0.0', function () {
    for (var i = 0; i < 100000; i++) rect.bbox()
  })
  //bench.test('using vanilla js', function() {
  //  var node = rect.node
  //  for (var i = 0; i < 10000; i++) {
  //    node.getBoundingClientRect()
  //  }
  //})
  //bench.test('using Snap.svg v0.5.1', function() {
  //  for (var i = 0; i < 10000; i++)
  //    bench.snap.rect(50, 50, 100, 100)
  //})
})
SVG.bench.describe('Generate 100000 viewbox', function (bench) {
  var nested = bench.draw.nested().viewbox(10, 10, 100, 100)

  bench.test('using SVG.js v3.0.0', function () {
    for (var i = 0; i < 100000; i++) nested.viewbox()
  })
  //bench.test('using vanilla js', function() {
  //  var node = rect.node
  //  for (var i = 0; i < 10000; i++) {
  //    node.getAttribute('viewBox')
  //  }
  //})
  //bench.test('using Snap.svg v0.5.1', function() {
  //  for (var i = 0; i < 10000; i++)
  //    bench.snap.rect(50, 50, 100, 100)
  //})
})


================================================
FILE: bench/tests/10000-circles.js
================================================
SVG.bench.describe('Generate 10000 circles', function (bench) {
  bench.test('using SVG.js v2.5.3', function () {
    for (var i = 0; i < 10000; i++) bench.draw.circle(100, 100)
  })
  bench.test('using vanilla js', function () {
    for (var i = 0; i < 10000; i++) {
      var circle = document.createElementNS(SVG.ns, 'circle')
      circle.setAttributeNS(null, 'rx', 50)
      circle.setAttributeNS(null, 'ry', 50)
      bench.raw.appendChild(circle)
    }
  })
  bench.test('using Snap.svg v0.5.1', function () {
    for (var i = 0; i < 10000; i++) bench.snap.circle(50, 50, 100, 100)
  })
})

SVG.bench.describe('Generate 10000 circles with fill', function (bench) {
  bench.test('using SVG.js v2.5.3', function () {
    for (var i = 0; i < 10000; i++) bench.draw.circle(100, 100).fill('#f06')
  })
  bench.test('using vanilla js', function () {
    for (var i = 0; i < 10000; i++) {
      var circle = document.createElementNS(SVG.ns, 'circle')
      circle.setAttributeNS(null, 'rx', 50)
      circle.setAttributeNS(null, 'ry', 50)
      circle.setAttributeNS(null, 'fill', '#f06')
      bench.raw.appendChild(circle)
    }
  })
  bench.test('using Snap.svg v0.5.1', function () {
    for (var i = 0; i < 10000; i++)
      bench.snap.circle(50, 50, 100, 100).attr('fill', '#f06')
  })
})


================================================
FILE: bench/tests/10000-each.js
================================================
SVG.bench.describe('each() vs forEach()', function (bench) {
  // preparation
  var list = []

  for (var i = 99; i >= 0; i--) list.push(bench.draw.rect(100, 50))

  var set = new SVG.Set(list)

  bench.test('10000 x each()', function () {
    for (var i = 0; i < 10000; i++) {
      set.each(function () {
        this.fill('#f06')
      })
    }
  })

  bench.test('10000 x forEach()', function () {
    for (var i = 0; i < 10000; i++) {
      list.forEach(function (e) {
        e.fill('#f06')
      })
    }
  })
})


================================================
FILE: bench/tests/10000-pathArray-bbox.js
================================================
SVG.bench.describe('Generate 10000 pathArrays bbox', function (bench) {
  var data =
    'M97.499,75.211l5.652,-4.874c-1.235,-3.156 -2.115,-6.44 -2.623,-9.791l-8.313,-1.582c-0.345,-3.501 -0.345,-7.027 0,-10.527l8.313,-1.582c0.508,-3.351 1.388,-6.635 2.623,-9.791l-6.408,-5.526c1.452,-3.204 3.215,-6.258 5.263,-9.117l7.99,2.787c2.116,-2.648 4.52,-5.052 7.168,-7.168l-2.787,-7.99c2.86,-2.049 5.913,-3.812 9.117,-5.263l5.526,6.408c3.156,-1.236 6.44,-2.115 9.791,-2.624l1.582,-8.312c3.501,-0.345 7.027,-0.345 10.527,0l1.582,8.312c3.351,0.509 6.635,1.388 9.791,2.624l5.526,-6.408c3.204,1.451 6.258,3.214 9.117,5.263l-2.787,7.99c2.648,2.116 5.052,4.52 7.168,7.168l7.99,-2.787c2.049,2.859 3.812,5.913 5.263,9.117l-6.408,5.526c1.236,3.156 2.115,6.44 2.624,9.791l8.312,1.582c0.345,3.5 0.345,7.026 0,10.527l-8.312,1.582c-0.509,3.351 -1.388,6.635 -2.624,9.791l6.408,5.526c-1.451,3.204 -3.214,6.257 -5.263,9.117l-7.99,-2.787c-2.116,2.648 -4.52,5.052 -7.168,7.168l2.787,7.99c-2.859,2.048 -5.913,3.811 -9.117,5.263l-5.526,-6.408c-3.156,1.235 -6.44,2.115 -9.791,2.624l-1.444,7.589l0.16,0.015l1.582,8.313c3.351,0.508 6.635,1.388 9.791,2.624l5.526,-6.409c3.204,1.452 6.258,3.215 9.117,5.264l-2.787,7.99c2.648,2.116 5.052,4.52 7.168,7.167l7.99,-2.786c2.049,2.859 3.812,5.913 5.263,9.117l-6.408,5.526c1.235,3.156 2.115,6.44 2.624,9.791l8.312,1.582c0.345,3.5 0.345,7.026 0,10.527l-8.312,1.581c-0.509,3.351 -1.389,6.635 -2.624,9.792l6.408,5.526c-1.451,3.204 -3.214,6.257 -5.263,9.116l-7.99,-2.786c-2.116,2.648 -4.52,5.052 -7.168,7.168l2.787,7.989c-2.859,2.049 -5.913,3.812 -9.117,5.264l-5.526,-6.408c-3.156,1.235 -6.44,2.115 -9.791,2.623l-1.582,8.313c-3.5,0.345 -7.026,0.345 -10.527,0l-1.582,-8.313c-3.351,-0.508 -6.635,-1.388 -9.791,-2.623l-5.526,6.408c-3.204,-1.452 -6.258,-3.215 -9.117,-5.264l2.787,-7.989c-2.648,-2.116 -5.052,-4.52 -7.168,-7.168l-7.99,2.786c-2.048,-2.859 -3.811,-5.912 -5.263,-9.116l6.408,-5.526c-1.235,-3.157 -2.115,-6.441 -2.624,-9.792l-8.312,-1.581c-0.345,-3.501 -0.345,-7.027 0,-10.527l8.312,-1.582c0.509,-3.351 1.389,-6.635 2.624,-9.791l-6.408,-5.526c0.034,-0.076 0.068,-0.151 0.103,-0.226l-7.783,-2.714c-2.116,2.648 -4.52,5.052 -7.168,7.167l2.787,7.99c-2.86,2.049 -5.913,3.812 -9.117,5.264l-5.526,-6.408c-3.156,1.235 -6.44,2.115 -9.791,2.623l-1.582,8.313c-3.501,0.345 -7.027,0.345 -10.527,0l-1.582,-8.313c-3.351,-0.508 -6.635,-1.388 -9.791,-2.623l-5.526,6.408c-3.204,-1.452 -6.258,-3.215 -9.117,-5.264l2.787,-7.99c-2.648,-2.115 -5.052,-4.519 -7.168,-7.167l-7.99,2.786c-2.049,-2.859 -3.812,-5.913 -5.263,-9.116l6.408,-5.527c-1.236,-3.156 -2.115,-6.44 -2.624,-9.791l-8.312,-1.581c-0.345,-3.501 -0.345,-7.027 0,-10.528l8.312,-1.581c0.509,-3.351 1.388,-6.635 2.624,-9.791l-6.408,-5.527c1.451,-3.204 3.214,-6.257 5.263,-9.116l7.99,2.786c2.116,-2.648 4.52,-5.052 7.168,-7.167l-2.787,-7.99c2.859,-2.049 5.913,-3.812 9.117,-5.264l5.526,6.408c3.156,-1.235 6.44,-2.115 9.791,-2.623l1.582,-8.313c3.5,-0.345 7.026,-0.345 10.527,0l1.582,8.313c3.351,0.508 6.635,1.388 9.791,2.623l5.526,-6.408c3.204,1.452 6.257,3.215 9.117,5.264l-2.787,7.99c2.648,2.115 5.052,4.519 7.168,7.167l7.99,-2.786c0.049,0.069 0.099,0.139 0.148,0.209Zm48.456,73.925c5.927,0 10.74,4.813 10.74,10.74c0,5.928 -4.813,10.74 -10.74,10.74c-5.928,0 -10.741,-4.812 -10.741,-10.74c0,-5.927 4.813,-10.74 10.741,-10.74Zm-5.402,-41.978l-0.16,-0.016l-1.582,-8.312c-3.351,-0.509 -6.635,-1.389 -9.791,-2.624l-5.526,6.408c-3.204,-1.452 -6.257,-3.215 -9.117,-5.263l2.787,-7.99c-2.648,-2.116 -5.052,-4.52 -7.168,-7.168l-7.99,2.787c-0.049,-0.07 -0.099,-0.139 -0.148,-0.209l-5.652,4.874c1.235,3.156 2.115,6.44 2.624,9.791l8.312,1.581c0.345,3.501 0.345,7.027 0,10.528l-8.312,1.581c-0.509,3.351 -1.389,6.635 -2.624,9.791l6.408,5.527c-0.034,0.075 -0.068,0.15 -0.103,0.225l7.783,2.714c2.116,-2.647 4.52,-5.051 7.168,-7.167l-2.787,-7.99c2.859,-2.049 5.913,-3.812 9.117,-5.264l5.526,6.409c3.156,-1.236 6.44,-2.116 9.791,-2.624l1.444,-7.589Zm-86.853,-11.617c5.928,0 10.74,4.812 10.74,10.74c0,5.928 -4.812,10.74 -10.74,10.74c-5.927,0 -10.74,-4.812 -10.74,-10.74c0,-5.928 4.813,-10.74 10.74,-10.74Zm91.957,-52.581c5.927,0 10.74,4.813 10.74,10.74c0,5.928 -4.813,10.74 -10.74,10.74c-5.928,0 -10.74,-4.812 -10.74,-10.74c0,-5.927 4.812,-10.74 10.74,-10.74Z'

  var data2 =
    'M0.48858732019046247.35239897640279355L0.5168962223329727.32957811442929225C0.5107105368860513.31480120831760355.5063029229643583.2994249853547438.5037585276550173.2837350574775992L0.46212160205156927.2763278757701558C0.46039361704817827.25993562345804494.46039361704817827.2434263170734397.46212160205156927.22703874692422862L0.5037585276550173.2196315652167852C0.5063029229643582.20394163733964055.5107105368860513.1885654143767808.5168962223329727.17378850826509218L0.4848007791395535.14791487608093778C0.492073342110347.13291322615006.5009035959102843.11861390065414837.5111613155825881.1052275969236928L0.5511804465306873.11827678492536459C0.5617787545514856.10587841756676146.5738195544012016.09462249795570335.5870824653837506.0847150412597803L0.5731233517476615.047304559690581297C0.5874480969931638.037710807908943156.6027395121101284.02945615471664055.6187872337068381.022662336349067613L0.6464650456741969.052665636210823215C0.6622723519660869.046878482866701814.678720765737496.04276286167779995.6955047592052157.040379640761814675L0.7034284469598956.0014615027388882582C0.7209637382551767 -0.0001538434615339766.7386242458550512 -0.0001538434615339766.7561545284981485.0014615027388882582L0.7640782162528285.040379640761814675C0.7808622097205482.04276286167779995.7973106234919571.046878482866701814.8131179297838472.052665636210823215L0.8407957417512061.022662336349067617C0.8568434633479157.02945615471664055.872139887117064.037710807908943156.8864596237103826.04730455969058131L0.8725005100742934.0847150412597803C0.8857634210568424.09462249795570335.8978042209065583.10587841756676146.9084025289273567.11827678492536459L0.948421659875456.1052275969236928C0.9586843881999436.11861390065414837.9675146419998809.13291322615006.9747821963184906.14791487608093778L0.9426867531250714.17378850826509218C0.9488774472241766.1885654143767808.953280052493686.20394163733964055.9558294564552107.2196315652167852L0.9974613734064749.22703874692422862C0.9991893584098659.2434263170734397.9991893584098659.25993562345804494.9974613734064749.2763278757701558L0.9558294564552107.2837350574775992C0.953280052493686.2994249853547438.9488774472241766.31480120831760366.9426867531250714.32957811442929225L0.9747821963184906.3554517466134466C0.9675146419998809.37045339654432435.9586843881999436.38474803987733625.948421659875456.3981390257706916L0.9084025289273567.3850898377690198C0.8978042209065583.3974882051276229.8857634210568424.40874412473868105.8725005100742934.41865158143460407L0.8864596237103826.4560620630038031C0.8721398871170639.46565113262254143.8568434633479156.4739057858148441.8407957417512061.4807042863453168L0.8131179297838472.45070098648356116C0.7973106234919571.4564834576647828.7808622097205482.4606037610165844.7640782162528285.4629869819325697L0.756845722499505.4985199161789591L0.7576471068489037.4985901486224557L0.7655707946035836.5375129688082819C0.7823547880713033.5398915075613674.7988032018427124.5440118109131691.8146105081346023.5497989642572905L0.8422883201019612.519790982232635C0.8583360416986708.5265894827631077.8736324654678193.5348441359554104.8879522020611378.5444378877370485L0.8739930884250485.5818483693062474C0.8872559994075976.5917558260021705.8992967992573135.6030117456132287.9098951072781118.615405430808932L0.9499142382262111.6023609249701599C0.9601769665506987.6157472287006156.969007220350636.6300465541965272.9762747746692458.6450482041274048L0.9441793314758266.6709218363115593C0.9503650169227481.685698742423248.9547726308444411.7010749653861077.9573220348059658.7167648932632523L0.9989539517572301.7241720749706957C1.000681936760621.7405596451199068 1.000681936760621.757068951504512.9989539517572301.7734612038166229L0.9573220348059658.7808637033611664C0.9547726308444411.796553631238311.950365016922748.8119298542011708.9441793314758266.8267114424757592L0.9762747746692458.8525850746599137C0.969007220350636.8675867245907916.9601769665506987.8818813679238033.9499142382262111.8952676716542589L0.9098951072781118.8822231658154869C0.8992967992573135.89462153317409.8872559994075976.9058774527851481.8739930884250485.9157849094810713L0.8879522020611378.9531907088873705C0.8736324654678191.9627844606690087.8583360416986707.9710391138613113.8422883201019612.977837614391784L0.8146105081346023.9478343145300284C0.7988032018427124.9536167857112502.7823547880713033.9577370890630518.7655707946035836.9601156278161371L0.7576471068489037.9990384480019633C0.7401168242058064 1.0006537942023856.7224563166059317 1.0006537942023856.7049210253106508.9990384480019633L0.6969973375559708.9601156278161371C0.6802133440882511.9577370890630517.6637649303168421.95361678571125.647957624024952.9478343145300284L0.6202798120575933.977837614391784C0.6042320904608837.9710391138613113.5889356666917354.9627844606690087.5746159300984167.9531907088873705L0.5885750437345059.9157849094810713C0.5753121327519569.9058774527851481.563271332902241.89462153317409.5526730248814425.8822231658154869L0.5126538939333434.8952676716542589C0.5023961742610396.8818813679238033.49356592046110226.8675867245907916.4862933574903087.8525850746599138L0.518388800683728.8267114424757593C0.5122031152368065.8119298542011709.5077955013151135.7965536312383112.5052460973535888.7808637033611665L0.46361418040232455.773461203816623C0.46188619539893355.757068951504512.46188619539893355.7405596451199069.46361418040232455.7241720749706959L0.5052460973535888.7167648932632524C0.5077955013151135.7010749653861078.5122031152368065.6856987424232481.518388800683728.6709218363115594L0.4862933574903087.645048204127405C0.48646365166455596.6446923597470222.48663394583880315.644341197529539.4868092486652341.6439900353120559L0.4478269087191694.6312826452020677C0.43722860069837116.6436810125606708.4251878008486552.6549369321717289.4119248898661061.6648397067047522L0.42588400350219535.7022501882739512C0.411559258256693.7118439400555895.3962678431397284.720098593247892.3802201215430187.7268970937783648L0.35254230957565996.6968937939166092C0.3367350032837699.702676265097831.32028658951236094.7067965684496326.3035025960446412.7091751072027179L0.2955789082899612.7480979273885441C0.27804361699468016.7497132735889663.2603831093948056.7497132735889663.24285282675170825.7480979273885441L0.23492913899702825.7091751072027179C0.21814514552930853.7067965684496325.2016967317578995.7026762650978308.1858894254660095.6968937939166092L0.15821161349865073.7268970937783648C0.14216389190194106.720098593247892.12686746813279273.7118439400555895.1125477315394741.7022501882739512L0.1265068451755633.6648397067047522C0.11324393419301426.6549369321717289.10120313434329828.6436810125606708.09060482632250003.6312826452020677L0.05058569537440074.6443271510408397C0.04032296704991321.6309408473103841.03149271324997591.6166415218144725.024225158931366137.6016445540464946L0.056320602124785436.5757662396994404C0.050129908025680216.5609893335877518.04572730275617092.545613110624892.0431778987946462.5299231827477474L0.001545981843381972.5225206832032038C-0.00018200316000904808.5061284308910928 -0.00018200316000904808.48961912450648765.001545981843381972.4732268721943768L0.0431778987946462.4658243726498331C0.04572730275617092.4501344447726885.050129908025680216.4347582218098287.056320602124785436.4199813156981401L0.02422515893136614.39410300135108595C0.03149271324997591.3791013514202082.04032296704991321.3648067080871963.05058569537440075.3514204043567407L0.09060482632250003.36446491019551275C0.10120313434329828.35206654283690964.11324393419301426.34081062322585154.1265068451755633.33090784869282824L0.1125477315394741.2934973671236292C0.12686746813279273.2839036153419911.14216389190194106.2756489621496885.15821161349865073.2688504616192157L0.1858894254660095.29885376148097137C0.2016967317578995.2930712902997497.21814514552930853.2889509869479481.23492913899702825.2865724481948626L0.24285282675170825.2476496280090364C0.2603831093948056.24603428180861417.27804361699468016.24603428180861417.2955789082899612.2476496280090364L0.3035025960446412.2865724481948626C0.32028658951236094.28895098694794813.33673500328377.2930712902997497.35254230957565996.29885376148097137L0.3802201215430187.2688504616192157C0.39626784313972835.2756489621496884.411559258256693.2839036153419911.42588400350219535.2934973671236292L0.4119248898661061.33090784869282824C0.42518780084865515.3408106232258515.43722860069837116.35206654283690964.4478269087191694.36446491019551275L0.4878460396672687.3514204043567407C0.4880914636242721.3517434735968252.4883418962334592.35207122499980936.48858732019046247.3523989764027936ZM0.731286570405869.6985278687686304C0.7609728518989083.6985278687686304.7850794948592591.7210631188052454.7850794948592591.7488142983122096C0.7850794948592591.7765701599820733.7609728518989085.7991007278557888.731286570405869.7991007278557888C0.701595280260646.7991007278557888.6774886373002953.7765701599820733.6774886373002953.7488142983122096C0.6774886373002953.7210631188052455.701595280260646.6985278687686304.731286570405869.6985278687686304ZM0.7042298313092943.5019800345618924L0.7034284469598956.501905119955496L0.6955047592052157.46298698193256965C0.678720765737496.46060376101658435.6622723519660869.45648345766478277.6464650456741969.4507009864835611L0.6187872337068382.4807042863453167C0.6027395121101286.473905785814844.5874480969931639.4656511326225414.5731233517476615.45606206300380303L0.5870824653837508.418651581434604C0.5738195544012017.408744124738681.5617787545514857.3974882051276229.5511804465306874.3850898377690197L0.5111613155825881.39813902577069155C0.5109158916255848.39781127436770736.5106654590163977.3974882051276229.5104200350593944.39716045372463865L0.48211113291688407.41998131569813996C0.48829681836380556.4347582218098286.4927044322854986.4501344447726883.4952538362470233.465824372649833L0.5368857531982875.47322687219437665C0.5386137382016786.48961912450648754.5386137382016786.5061284308910927.5368857531982875.5225206832032036L0.4952538362470233.5299231827477473C0.4927044322854986.5456131106248919.48829681836380556.5609893335877517.48211113291688407.5757662396994403L0.5142065761103034.6016445540464944C0.5140362819360561.6019957162639775.5138659877618089.6023468784814607.513690684935378.6026980406989437L0.5526730248814427.615405430808932C0.563271332902241.6030117456132287.5753121327519569.5917558260021705.588575043734506.5818483693062474L0.5746159300984167.5444378877370485C0.5889356666917354.5348441359554102.6042320904608837.5265894827631077.6202798120575934.519790982232635L0.6479576240249522.5497989642572905C0.6637649303168422.544011810913169.6802133440882512.5398915075613674.6969973375559709.5375129688082819L0.7042298313092945.5019800345618926ZM0.2692133631947428.447587348155211C0.2989046533399659.447587348155211.32300628764813283.47011791602892633.32300628764813283.4978737776987901C0.32300628764813283.5256296393686539.2989046533399659.5481602072423692.2692133631947428.5481602072423692C0.23952708170170345.5481602072423692.21542043874135278.5256296393686539.21542043874135278.4978737776987901C0.21542043874135278.47011791602892633.23952708170170345.447587348155211.2692133631947428.447587348155211ZM0.7297939920551139.20139454072216306C0.7594802735481532.20139454072216306.783586916508504.2239297907587782.783586916508504.2516809702657422C0.783586916508504.279436831935606.7594802735481533.30196739980932136.7297939920551139.30196739980932136C0.7001027019098908.30196739980932136.6760010676017238.27943683193560603.6760010676017238.2516809702657422C0.6760010676017238.2239297907587782.7001027019098908.20139454072216306.7297939920551139.20139454072216306Z '

  var data3 = 'M10 10-45-30.5.5 .89L2e-2.5.5.5-.5C.5.5.5.5.5.5L-3-4z'

  var draw = SVG().addTo('body')
  var path = SVG.create('path')
  path.style.visibility = 'hidden'

  bench.test('using SVG.js v3.0.0', function () {
    for (var i = 0; i < 10000; i++) {
      SVG.parser.path.setAttribute('d', data)
      SVG.parser.path.getBBox()
    }
  })

  bench.test('using SVG.js v3.0.0 more data', function () {
    for (var i = 0; i < 10000; i++) {
      SVG.parser.path.setAttribute('d', data2)
      SVG.parser.path.getBBox()
    }
  })

  bench.test('using SVG.js v3.0.0 complicated data', function () {
    for (var i = 0; i < 10000; i++) {
      SVG.parser.path.setAttribute('d', data3)
      SVG.parser.path.getBBox()
    }
  })

  bench.test('using SVG.js v3.0.0 without parser', function () {
    for (var i = 0; i < 10000; i++) {
      path.setAttribute('d', data)
      draw.node.appendChild(path)
      path.getBBox()
    }
    //new SVG.Path().attr('d', data).addTo(draw).bbox()
  })

  bench.test('using SVG.js v3.0.0 more data without parser', function () {
    for (var i = 0; i < 10000; i++) {
      path.setAttribute('d', data2)
      draw.node.appendChild(path)
      path.getBBox()
    }
    //new SVG.Path().attr('d', data2).addTo(draw).bbox()
  })

  bench.test(
    'using SVG.js v3.0.0 complicated data without parser',
    function () {
      for (var i = 0; i < 10000; i++) {
        path.setAttribute('d', data3)
        draw.node.appendChild(path)
        path.getBBox()
      }
      //new SVG.Path().attr('d', data3).addTo(draw).bbox()
    }
  )
})


================================================
FILE: bench/tests/10000-pathArrays.js
================================================
SVG.bench.describe('Generate 10000 pathArrays', function (bench) {
  var data =
    'M97.499,75.211l5.652,-4.874c-1.235,-3.156 -2.115,-6.44 -2.623,-9.791l-8.313,-1.582c-0.345,-3.501 -0.345,-7.027 0,-10.527l8.313,-1.582c0.508,-3.351 1.388,-6.635 2.623,-9.791l-6.408,-5.526c1.452,-3.204 3.215,-6.258 5.263,-9.117l7.99,2.787c2.116,-2.648 4.52,-5.052 7.168,-7.168l-2.787,-7.99c2.86,-2.049 5.913,-3.812 9.117,-5.263l5.526,6.408c3.156,-1.236 6.44,-2.115 9.791,-2.624l1.582,-8.312c3.501,-0.345 7.027,-0.345 10.527,0l1.582,8.312c3.351,0.509 6.635,1.388 9.791,2.624l5.526,-6.408c3.204,1.451 6.258,3.214 9.117,5.263l-2.787,7.99c2.648,2.116 5.052,4.52 7.168,7.168l7.99,-2.787c2.049,2.859 3.812,5.913 5.263,9.117l-6.408,5.526c1.236,3.156 2.115,6.44 2.624,9.791l8.312,1.582c0.345,3.5 0.345,7.026 0,10.527l-8.312,1.582c-0.509,3.351 -1.388,6.635 -2.624,9.791l6.408,5.526c-1.451,3.204 -3.214,6.257 -5.263,9.117l-7.99,-2.787c-2.116,2.648 -4.52,5.052 -7.168,7.168l2.787,7.99c-2.859,2.048 -5.913,3.811 -9.117,5.263l-5.526,-6.408c-3.156,1.235 -6.44,2.115 -9.791,2.624l-1.444,7.589l0.16,0.015l1.582,8.313c3.351,0.508 6.635,1.388 9.791,2.624l5.526,-6.409c3.204,1.452 6.258,3.215 9.117,5.264l-2.787,7.99c2.648,2.116 5.052,4.52 7.168,7.167l7.99,-2.786c2.049,2.859 3.812,5.913 5.263,9.117l-6.408,5.526c1.235,3.156 2.115,6.44 2.624,9.791l8.312,1.582c0.345,3.5 0.345,7.026 0,10.527l-8.312,1.581c-0.509,3.351 -1.389,6.635 -2.624,9.792l6.408,5.526c-1.451,3.204 -3.214,6.257 -5.263,9.116l-7.99,-2.786c-2.116,2.648 -4.52,5.052 -7.168,7.168l2.787,7.989c-2.859,2.049 -5.913,3.812 -9.117,5.264l-5.526,-6.408c-3.156,1.235 -6.44,2.115 -9.791,2.623l-1.582,8.313c-3.5,0.345 -7.026,0.345 -10.527,0l-1.582,-8.313c-3.351,-0.508 -6.635,-1.388 -9.791,-2.623l-5.526,6.408c-3.204,-1.452 -6.258,-3.215 -9.117,-5.264l2.787,-7.989c-2.648,-2.116 -5.052,-4.52 -7.168,-7.168l-7.99,2.786c-2.048,-2.859 -3.811,-5.912 -5.263,-9.116l6.408,-5.526c-1.235,-3.157 -2.115,-6.441 -2.624,-9.792l-8.312,-1.581c-0.345,-3.501 -0.345,-7.027 0,-10.527l8.312,-1.582c0.509,-3.351 1.389,-6.635 2.624,-9.791l-6.408,-5.526c0.034,-0.076 0.068,-0.151 0.103,-0.226l-7.783,-2.714c-2.116,2.648 -4.52,5.052 -7.168,7.167l2.787,7.99c-2.86,2.049 -5.913,3.812 -9.117,5.264l-5.526,-6.408c-3.156,1.235 -6.44,2.115 -9.791,2.623l-1.582,8.313c-3.501,0.345 -7.027,0.345 -10.527,0l-1.582,-8.313c-3.351,-0.508 -6.635,-1.388 -9.791,-2.623l-5.526,6.408c-3.204,-1.452 -6.258,-3.215 -9.117,-5.264l2.787,-7.99c-2.648,-2.115 -5.052,-4.519 -7.168,-7.167l-7.99,2.786c-2.049,-2.859 -3.812,-5.913 -5.263,-9.116l6.408,-5.527c-1.236,-3.156 -2.115,-6.44 -2.624,-9.791l-8.312,-1.581c-0.345,-3.501 -0.345,-7.027 0,-10.528l8.312,-1.581c0.509,-3.351 1.388,-6.635 2.624,-9.791l-6.408,-5.527c1.451,-3.204 3.214,-6.257 5.263,-9.116l7.99,2.786c2.116,-2.648 4.52,-5.052 7.168,-7.167l-2.787,-7.99c2.859,-2.049 5.913,-3.812 9.117,-5.264l5.526,6.408c3.156,-1.235 6.44,-2.115 9.791,-2.623l1.582,-8.313c3.5,-0.345 7.026,-0.345 10.527,0l1.582,8.313c3.351,0.508 6.635,1.388 9.791,2.623l5.526,-6.408c3.204,1.452 6.257,3.215 9.117,5.264l-2.787,7.99c2.648,2.115 5.052,4.519 7.168,7.167l7.99,-2.786c0.049,0.069 0.099,0.139 0.148,0.209Zm48.456,73.925c5.927,0 10.74,4.813 10.74,10.74c0,5.928 -4.813,10.74 -10.74,10.74c-5.928,0 -10.741,-4.812 -10.741,-10.74c0,-5.927 4.813,-10.74 10.741,-10.74Zm-5.402,-41.978l-0.16,-0.016l-1.582,-8.312c-3.351,-0.509 -6.635,-1.389 -9.791,-2.624l-5.526,6.408c-3.204,-1.452 -6.257,-3.215 -9.117,-5.263l2.787,-7.99c-2.648,-2.116 -5.052,-4.52 -7.168,-7.168l-7.99,2.787c-0.049,-0.07 -0.099,-0.139 -0.148,-0.209l-5.652,4.874c1.235,3.156 2.115,6.44 2.624,9.791l8.312,1.581c0.345,3.501 0.345,7.027 0,10.528l-8.312,1.581c-0.509,3.351 -1.389,6.635 -2.624,9.791l6.408,5.527c-0.034,0.075 -0.068,0.15 -0.103,0.225l7.783,2.714c2.116,-2.647 4.52,-5.051 7.168,-7.167l-2.787,-7.99c2.859,-2.049 5.913,-3.812 9.117,-5.264l5.526,6.409c3.156,-1.236 6.44,-2.116 9.791,-2.624l1.444,-7.589Zm-86.853,-11.617c5.928,0 10.74,4.812 10.74,10.74c0,5.928 -4.812,10.74 -10.74,10.74c-5.927,0 -10.74,-4.812 -10.74,-10.74c0,-5.928 4.813,-10.74 10.74,-10.74Zm91.957,-52.581c5.927,0 10.74,4.813 10.74,10.74c0,5.928 -4.813,10.74 -10.74,10.74c-5.928,0 -10.74,-4.812 -10.74,-10.74c0,-5.927 4.812,-10.74 10.74,-10.74Z'

  var data2 =
    'M0.48858732019046247.35239897640279355L0.5168962223329727.32957811442929225C0.5107105368860513.31480120831760355.5063029229643583.2994249853547438.5037585276550173.2837350574775992L0.46212160205156927.2763278757701558C0.46039361704817827.25993562345804494.46039361704817827.2434263170734397.46212160205156927.22703874692422862L0.5037585276550173.2196315652167852C0.5063029229643582.20394163733964055.5107105368860513.1885654143767808.5168962223329727.17378850826509218L0.4848007791395535.14791487608093778C0.492073342110347.13291322615006.5009035959102843.11861390065414837.5111613155825881.1052275969236928L0.5511804465306873.11827678492536459C0.5617787545514856.10587841756676146.5738195544012016.09462249795570335.5870824653837506.0847150412597803L0.5731233517476615.047304559690581297C0.5874480969931638.037710807908943156.6027395121101284.02945615471664055.6187872337068381.022662336349067613L0.6464650456741969.052665636210823215C0.6622723519660869.046878482866701814.678720765737496.04276286167779995.6955047592052157.040379640761814675L0.7034284469598956.0014615027388882582C0.7209637382551767 -0.0001538434615339766.7386242458550512 -0.0001538434615339766.7561545284981485.0014615027388882582L0.7640782162528285.040379640761814675C0.7808622097205482.04276286167779995.7973106234919571.046878482866701814.8131179297838472.052665636210823215L0.8407957417512061.022662336349067617C0.8568434633479157.02945615471664055.872139887117064.037710807908943156.8864596237103826.04730455969058131L0.8725005100742934.0847150412597803C0.8857634210568424.09462249795570335.8978042209065583.10587841756676146.9084025289273567.11827678492536459L0.948421659875456.1052275969236928C0.9586843881999436.11861390065414837.9675146419998809.13291322615006.9747821963184906.14791487608093778L0.9426867531250714.17378850826509218C0.9488774472241766.1885654143767808.953280052493686.20394163733964055.9558294564552107.2196315652167852L0.9974613734064749.22703874692422862C0.9991893584098659.2434263170734397.9991893584098659.25993562345804494.9974613734064749.2763278757701558L0.9558294564552107.2837350574775992C0.953280052493686.2994249853547438.9488774472241766.31480120831760366.9426867531250714.32957811442929225L0.9747821963184906.3554517466134466C0.9675146419998809.37045339654432435.9586843881999436.38474803987733625.948421659875456.3981390257706916L0.9084025289273567.3850898377690198C0.8978042209065583.3974882051276229.8857634210568424.40874412473868105.8725005100742934.41865158143460407L0.8864596237103826.4560620630038031C0.8721398871170639.46565113262254143.8568434633479156.4739057858148441.8407957417512061.4807042863453168L0.8131179297838472.45070098648356116C0.7973106234919571.4564834576647828.7808622097205482.4606037610165844.7640782162528285.4629869819325697L0.756845722499505.4985199161789591L0.7576471068489037.4985901486224557L0.7655707946035836.5375129688082819C0.7823547880713033.5398915075613674.7988032018427124.5440118109131691.8146105081346023.5497989642572905L0.8422883201019612.519790982232635C0.8583360416986708.5265894827631077.8736324654678193.5348441359554104.8879522020611378.5444378877370485L0.8739930884250485.5818483693062474C0.8872559994075976.5917558260021705.8992967992573135.6030117456132287.9098951072781118.615405430808932L0.9499142382262111.6023609249701599C0.9601769665506987.6157472287006156.969007220350636.6300465541965272.9762747746692458.6450482041274048L0.9441793314758266.6709218363115593C0.9503650169227481.685698742423248.9547726308444411.7010749653861077.9573220348059658.7167648932632523L0.9989539517572301.7241720749706957C1.000681936760621.7405596451199068 1.000681936760621.757068951504512.9989539517572301.7734612038166229L0.9573220348059658.7808637033611664C0.9547726308444411.796553631238311.950365016922748.8119298542011708.9441793314758266.8267114424757592L0.9762747746692458.8525850746599137C0.969007220350636.8675867245907916.9601769665506987.8818813679238033.9499142382262111.8952676716542589L0.9098951072781118.8822231658154869C0.8992967992573135.89462153317409.8872559994075976.9058774527851481.8739930884250485.9157849094810713L0.8879522020611378.9531907088873705C0.8736324654678191.9627844606690087.8583360416986707.9710391138613113.8422883201019612.977837614391784L0.8146105081346023.9478343145300284C0.7988032018427124.9536167857112502.7823547880713033.9577370890630518.7655707946035836.9601156278161371L0.7576471068489037.9990384480019633C0.7401168242058064 1.0006537942023856.7224563166059317 1.0006537942023856.7049210253106508.9990384480019633L0.6969973375559708.9601156278161371C0.6802133440882511.9577370890630517.6637649303168421.95361678571125.647957624024952.9478343145300284L0.6202798120575933.977837614391784C0.6042320904608837.9710391138613113.5889356666917354.9627844606690087.5746159300984167.9531907088873705L0.5885750437345059.9157849094810713C0.5753121327519569.9058774527851481.563271332902241.89462153317409.5526730248814425.8822231658154869L0.5126538939333434.8952676716542589C0.5023961742610396.8818813679238033.49356592046110226.8675867245907916.4862933574903087.8525850746599138L0.518388800683728.8267114424757593C0.5122031152368065.8119298542011709.5077955013151135.7965536312383112.5052460973535888.7808637033611665L0.46361418040232455.773461203816623C0.46188619539893355.757068951504512.46188619539893355.7405596451199069.46361418040232455.7241720749706959L0.5052460973535888.7167648932632524C0.5077955013151135.7010749653861078.5122031152368065.6856987424232481.518388800683728.6709218363115594L0.4862933574903087.645048204127405C0.48646365166455596.6446923597470222.48663394583880315.644341197529539.4868092486652341.6439900353120559L0.4478269087191694.6312826452020677C0.43722860069837116.6436810125606708.4251878008486552.6549369321717289.4119248898661061.6648397067047522L0.42588400350219535.7022501882739512C0.411559258256693.7118439400555895.3962678431397284.720098593247892.3802201215430187.7268970937783648L0.35254230957565996.6968937939166092C0.3367350032837699.702676265097831.32028658951236094.7067965684496326.3035025960446412.7091751072027179L0.2955789082899612.7480979273885441C0.27804361699468016.7497132735889663.2603831093948056.7497132735889663.24285282675170825.7480979273885441L0.23492913899702825.7091751072027179C0.21814514552930853.7067965684496325.2016967317578995.7026762650978308.1858894254660095.6968937939166092L0.15821161349865073.7268970937783648C0.14216389190194106.720098593247892.12686746813279273.7118439400555895.1125477315394741.7022501882739512L0.1265068451755633.6648397067047522C0.11324393419301426.6549369321717289.10120313434329828.6436810125606708.09060482632250003.6312826452020677L0.05058569537440074.6443271510408397C0.04032296704991321.6309408473103841.03149271324997591.6166415218144725.024225158931366137.6016445540464946L0.056320602124785436.5757662396994404C0.050129908025680216.5609893335877518.04572730275617092.545613110624892.0431778987946462.5299231827477474L0.001545981843381972.5225206832032038C-0.00018200316000904808.5061284308910928 -0.00018200316000904808.48961912450648765.001545981843381972.4732268721943768L0.0431778987946462.4658243726498331C0.04572730275617092.4501344447726885.050129908025680216.4347582218098287.056320602124785436.4199813156981401L0.02422515893136614.39410300135108595C0.03149271324997591.3791013514202082.04032296704991321.3648067080871963.05058569537440075.3514204043567407L0.09060482632250003.36446491019551275C0.10120313434329828.35206654283690964.11324393419301426.34081062322585154.1265068451755633.33090784869282824L0.1125477315394741.2934973671236292C0.12686746813279273.2839036153419911.14216389190194106.2756489621496885.15821161349865073.2688504616192157L0.1858894254660095.29885376148097137C0.2016967317578995.2930712902997497.21814514552930853.2889509869479481.23492913899702825.2865724481948626L0.24285282675170825.2476496280090364C0.2603831093948056.24603428180861417.27804361699468016.24603428180861417.2955789082899612.2476496280090364L0.3035025960446412.2865724481948626C0.32028658951236094.28895098694794813.33673500328377.2930712902997497.35254230957565996.29885376148097137L0.3802201215430187.2688504616192157C0.39626784313972835.2756489621496884.411559258256693.2839036153419911.42588400350219535.2934973671236292L0.4119248898661061.33090784869282824C0.42518780084865515.3408106232258515.43722860069837116.35206654283690964.4478269087191694.36446491019551275L0.4878460396672687.3514204043567407C0.4880914636242721.3517434735968252.4883418962334592.35207122499980936.48858732019046247.3523989764027936ZM0.731286570405869.6985278687686304C0.7609728518989083.6985278687686304.7850794948592591.7210631188052454.7850794948592591.7488142983122096C0.7850794948592591.7765701599820733.7609728518989085.7991007278557888.731286570405869.7991007278557888C0.701595280260646.7991007278557888.6774886373002953.7765701599820733.6774886373002953.7488142983122096C0.6774886373002953.7210631188052455.701595280260646.6985278687686304.731286570405869.6985278687686304ZM0.7042298313092943.5019800345618924L0.7034284469598956.501905119955496L0.6955047592052157.46298698193256965C0.678720765737496.46060376101658435.6622723519660869.45648345766478277.6464650456741969.4507009864835611L0.6187872337068382.4807042863453167C0.6027395121101286.473905785814844.5874480969931639.4656511326225414.5731233517476615.45606206300380303L0.5870824653837508.418651581434604C0.5738195544012017.408744124738681.5617787545514857.3974882051276229.5511804465306874.3850898377690197L0.5111613155825881.39813902577069155C0.5109158916255848.39781127436770736.5106654590163977.3974882051276229.5104200350593944.39716045372463865L0.48211113291688407.41998131569813996C0.48829681836380556.4347582218098286.4927044322854986.4501344447726883.4952538362470233.465824372649833L0.5368857531982875.47322687219437665C0.5386137382016786.48961912450648754.5386137382016786.5061284308910927.5368857531982875.5225206832032036L0.4952538362470233.5299231827477473C0.4927044322854986.5456131106248919.48829681836380556.5609893335877517.48211113291688407.5757662396994403L0.5142065761103034.6016445540464944C0.5140362819360561.6019957162639775.5138659877618089.6023468784814607.513690684935378.6026980406989437L0.5526730248814427.615405430808932C0.563271332902241.6030117456132287.5753121327519569.5917558260021705.588575043734506.5818483693062474L0.5746159300984167.5444378877370485C0.5889356666917354.5348441359554102.6042320904608837.5265894827631077.6202798120575934.519790982232635L0.6479576240249522.5497989642572905C0.6637649303168422.544011810913169.6802133440882512.5398915075613674.6969973375559709.5375129688082819L0.7042298313092945.5019800345618926ZM0.2692133631947428.447587348155211C0.2989046533399659.447587348155211.32300628764813283.47011791602892633.32300628764813283.4978737776987901C0.32300628764813283.5256296393686539.2989046533399659.5481602072423692.2692133631947428.5481602072423692C0.23952708170170345.5481602072423692.21542043874135278.5256296393686539.21542043874135278.4978737776987901C0.21542043874135278.47011791602892633.23952708170170345.447587348155211.2692133631947428.447587348155211ZM0.7297939920551139.20139454072216306C0.7594802735481532.20139454072216306.783586916508504.2239297907587782.783586916508504.2516809702657422C0.783586916508504.279436831935606.7594802735481533.30196739980932136.7297939920551139.30196739980932136C0.7001027019098908.30196739980932136.6760010676017238.27943683193560603.6760010676017238.2516809702657422C0.6760010676017238.2239297907587782.7001027019098908.20139454072216306.7297939920551139.20139454072216306Z '

  var data3 = 'M10 10-45-30.5.5 .89L2e-2.5.5.5-.5C.5.5.5.5.5.5L-3-4z'

  bench.test('using SVG.js v2.5.3', function () {
    for (var i = 0; i < 10000; i++) new SVG.PathArray(data)
  })

  bench.test('using SVG.js v2.5.3 more data', function () {
    for (var i = 0; i < 10000; i++) new SVG.PathArray(data2)
  })

  bench.test('using SVG.js v2.5.3 complicated data', function () {
    for (var i = 0; i < 10000; i++) new SVG.PathArray(data3)
  })
})


================================================
FILE: bench/tests/10000-paths.js
================================================
SVG.bench.describe('Generate 10000 paths', function (bench) {
  var data =
    'M 100 200 C 200 100 300  0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100'

  bench.test('using SVG.js v2.5.3', function () {
    for (var i = 0; i < 10000; i++) bench.draw.path(data)
  })
  bench.test('using vanilla js', function () {
    for (var i = 0; i < 10000; i++) {
      var path = document.createElementNS(SVG.ns, 'path')
      path.setAttributeNS(null, 'd', data)
      bench.raw.appendChild(path)
    }
  })
  bench.test('using Snap.svg v0.5.1', function () {
    for (var i = 0; i < 10000; i++) bench.snap.path(data)
  })
})


================================================
FILE: bench/tests/10000-pointArray-bbox.js
================================================
SVG.bench.describe('Generate 10000 pathArrays bbox', function (bench) {
  var data =
    '209,153 389,107 547,188 482,289 374,287 91,254 407,243 391,185 166,226 71,177 65,52 234,50 107,136 163,199 158,131 323,45 218,145 305,190 374,143 174,216 296,241'

  var dataArr = [
    [209, 153],
    [389, 107],
    [547, 188],
    [482, 289],
    [374, 287],
    [91, 254],
    [407, 243],
    [391, 185],
    [166, 226],
    [71, 177],
    [65, 52],
    [234, 50],
    [107, 136],
    [163, 199],
    [158, 131],
    [323, 45],
    [218, 145],
    [305, 190],
    [374, 143],
    [174, 216],
    [296, 241]
  ]

  bench.test('using SVG.js v3.0.0', function () {
    for (var i = 0; i < 10000; i++) {
      SVG.parser.poly.setAttribute('points', data)
      SVG.parser.poly.getBBox()
    }
  })

  bench.test('using SVG.js v3.0.0 without parser', function () {
    for (var i = 0; i < 10000; i++) {
      var maxX = -Infinity,
        maxY = -Infinity,
        minX = Infinity,
        minY = Infinity
      dataArr.forEach(function (el) {
        maxX = Math.max(el[0], maxX)
        maxY = Math.max(el[1], maxY)
        minX = Math.min(el[0], minX)
        minY = Math.min(el[1], minY)
      })
      var a = { x: minX, y: minY, width: maxX - minX, height: maxY - minY }
    }
    //new SVG.Path().attr('d', data).addTo(draw).bbox()
  })
})


================================================
FILE: bench/tests/10000-rects.js
================================================
SVG.bench.describe('Generate 10000 rects', function (bench) {
  bench.test('using SVG.js v3.0.6', function () {
    for (var i = 0; i < 10000; i++) bench.draw.rect(100, 100)
  })
  bench.test('using vanilla js', function () {
    for (var i = 0; i < 10000; i++) {
      var rect = document.createElementNS(SVG.ns, 'rect')
      rect.setAttributeNS(null, 'height', 100)
      rect.setAttributeNS(null, 'width', 100)
      bench.raw.appendChild(rect)
    }
  })
  bench.test('using Snap.svg v0.5.1', function () {
    for (var i = 0; i < 10000; i++) bench.snap.rect(50, 50, 100, 100)
  })
})

SVG.bench.describe('Generate 10000 rects with fill', function (bench) {
  bench.test('using SVG.js v3.0.6', function () {
    for (var i = 0; i < 10000; i++) bench.draw.rect(100, 100).fill('#f06')
  })
  bench.test('using vanilla js', function () {
    for (var i = 0; i < 10000; i++) {
      var rect = document.createElementNS(SVG.ns, 'rect')
      rect.setAttributeNS(null, 'height', 100)
      rect.setAttributeNS(null, 'width', 100)
      rect.setAttributeNS(null, 'fill', '#f06')
      bench.raw.appendChild(rect)
    }
  })
  bench.test('using Snap.svg v0.5.1', function () {
    for (var i = 0; i < 10000; i++)
      bench.snap.rect(50, 50, 100, 100).attr('fill', '#f06')
  })
})

SVG.bench.describe(
  'Generate 10000 rects with position and fill',
  function (bench) {
    bench.test('using SVG.js v3.0.6', function () {
      for (var i = 0; i < 10000; i++)
        bench.draw.rect(100, 100).move(50, 50).fill('#f06')
    })
    bench.test('using vanilla js', function () {
      for (var i = 0; i < 10000; i++) {
        var rect = document.createElementNS(SVG.ns, 'rect')
        rect.setAttributeNS(null, 'height', 100)
        rect.setAttributeNS(null, 'width', 100)
        rect.setAttributeNS(null, 'fill', '#f06')
        rect.setAttributeNS(null, 'x', 50)
        rect.setAttributeNS(null, 'y', 50)
        bench.raw.appendChild(rect)
      }
    })
    bench.test('using Snap.svg v0.5.1', function () {
      for (var i = 0; i < 10000; i++)
        bench.snap.rect(50, 50, 100, 100).attr('fill', '#f06')
    })
  }
)

SVG.bench.describe('Generate 10000 rects with gradient fill', function (bench) {
  bench.test('using SVG.js v3.0.6', function () {
    for (var i = 0; i < 10000; i++) {
      var g = bench.draw.gradient('linear', function (add) {
        add.stop(0, '#000')
        add.stop(0.25, '#f00')
        add.stop(1, '#fff')
      })

      bench.draw.rect(100, 100).fill(g)
    }
  })
  bench.test('using vanilla js', function () {
    for (var i = 0; i < 10000; i++) {
      var g = document.createElementNS(SVG.ns, 'linearGradient')
      var stop = document.createElementNS(SVG.ns, 'stop')
      stop.setAttributeNS(null, 'offset', '0%')
      stop.setAttributeNS(null, 'color', '#000')
      g.appendChild(stop)
      stop = document.createElementNS(SVG.ns, 'stop')
      stop.setAttributeNS(null, 'offset', '25%')
      stop.setAttributeNS(null, 'color', '#f00')
      g.appendChild(stop)
      stop = document.createElementNS(SVG.ns, 'stop')
      stop.setAttributeNS(null, 'offset', '100%')
      stop.setAttributeNS(null, 'color', '#fff')
      g.appendChild(stop)
      bench.raw.appendChild(g)

      var rect = document.createElementNS(SVG.ns, 'rect')
      rect.setAttributeNS(null, 'height', 100)
      rect.setAttributeNS(null, 'width', 100)
      rect.setAttributeNS(null, 'fill', '#f06')
      bench.raw.appendChild(rect)
    }
  })
  bench.test('using Snap.svg v0.5.1', function () {
    for (var i = 0; i < 10000; i++) {
      var g = bench.snap.gradient('L(0, 0, 100, 100)#000-#f00:25%-#fff')

      bench.snap.rect(50, 50, 100, 100).attr({
        fill: g
      })
    }
  })
})


================================================
FILE: bench/tests/10000-textContent.js
================================================
SVG.bench.describe('Change textContent 10000 times', function (bench) {
  var data =
    'M 100 200 C 200 100 300  0 400 100 C 500 200 600 300 700 200 C 800 100 900 100 900 100'

  var node = bench.draw.plain('').node

  bench.test('using appendChild', function () {
    for (var i = 0; i < 1000000; i++) {
      while (node.hasChildNodes()) {
        node.removeChild(node.lastChild)
      }

      node.appendChild(document.createTextNode('test' + i))
    }
  })
  bench.test('using textContent', function () {
    for (var i = 0; i < 1000000; i++) {
      node.textContent = 'test' + i
    }
  })
})


================================================
FILE: bench/tests/10000-transform.js
================================================
SVG.bench.describe('Transform 1000000 rects', function (bench) {
  let parameters = {
    translate: [20, 30],
    origin: [100, 100],
    rotate: 25,
    skew: [10, 30],
    scale: 0.5
  }

  let matrixLike = { a: 2, b: 3, c: 1, d: 2, e: 49, f: 100 }
  let matrix = new SVG.Matrix(matrixLike)

  let worker = new SVG.Matrix()
  bench.test('with parameters', function () {
    for (var i = 0; i < 1000000; i++) worker.transform(parameters)
  })

  worker = new SVG.Matrix()
  bench.test('with matrix like', function () {
    for (var i = 0; i < 1000000; i++) {
      worker.transform(matrixLike)
    }
  })

  worker = new SVG.Matrix()
  bench.test('with SVG.Matrix', function () {
    for (var i = 0; i < 1000000; i++) worker.transform(matrix)
  })
})


================================================
FILE: package.json
================================================
{
  "name": "@svgdotjs/svg.js",
  "version": "3.2.5",
  "type": "module",
  "description": "A lightweight library for manipulating and animating SVG.",
  "url": "https://svgjs.dev/",
  "homepage": "https://svgjs.dev/",
  "keywords": [
    "svg",
    "vector",
    "graphics",
    "animation"
  ],
  "author": "Wout Fierens <wout@mick-wout.com>",
  "main": "dist/svg.node.cjs",
  "unpkg": "dist/svg.min.js",
  "jsdelivr": "dist/svg.min.js",
  "browser": "dist/svg.esm.js",
  "module": "src/main.js",
  "exports": {
    ".": {
      "import": {
        "types": "./svg.js.d.ts",
        "default": "./src/main.js"
      },
      "require": {
        "types": "./svg.js.d.ts",
        "default": "./dist/svg.node.cjs"
      }
    }
  },
  "files": [
    "/dist",
    "/src",
    "/svg.js.d.ts",
    "/.config"
  ],
  "maintainers": [
    {
      "name": "Wout Fierens",
      "email": "wout@mick-wout.com"
    },
    {
      "name": "Alex Ewerlöf",
      "email": "alex@userpixel.com",
      "web": "http://www.ewerlof.name"
    },
    {
      "name": "Ulrich-Matthias Schäfer",
      "email": "ulima.ums@googlemail.com",
      "web": "https://svgdotjs.github.io/"
    },
    {
      "name": "Jon Ege Ronnenberg",
      "email": "jon@svgjs.dev",
      "url": "https://keybase.io/dotnetcarpenter"
    }
  ],
  "licenses": [
    {
      "type": "MIT",
      "url": "http://www.opensource.org/licenses/mit-license.php"
    }
  ],
  "repository": {
    "type": "git",
    "url": "https://github.com/svgdotjs/svg.js.git"
  },
  "github": "https://github.com/svgdotjs/svg.js",
  "license": "MIT",
  "funding": {
    "type": "github",
    "url": "https://github.com/sponsors/Fuzzyma"
  },
  "typings": "./svg.js.d.ts",
  "scripts": {
    "build": "npm run format && npm run rollup",
    "build:polyfills": "npx rollup -c .config/rollup.polyfills.js",
    "build:tests": "npx rollup -c .config/rollup.tests.js",
    "fix": "npx eslint ./src --fix",
    "lint": "npx eslint ./src",
    "prettier": "npx prettier --write .",
    "format": "npm run fix && npm run prettier",
    "rollup": "npx rollup -c .config/rollup.config.js",
    "server": "npx http-server ./ -d",
    "test": "npx karma start .config/karma.conf.cjs || true",
    "test:ci": "karma start .config/karma.conf.saucelabs.cjs",
    "test:svgdom": "node ./spec/runSVGDomTest.js || true",
    "zip": "zip -j dist/svg.js.zip -- LICENSE.txt README.md CHANGELOG.md dist/svg.js dist/svg.js.map dist/svg.min.js dist/svg.min.js.map dist/polyfills.js dist/polyfillsIE.js",
    "prepublishOnly": "rm -rf ./dist && npm run build && npm run build:polyfills && npm test",
    "postpublish": "npm run zip",
    "checkTests": "node spec/checkForAllTests.js"
  },
  "devDependencies": {
    "@babel/core": "^7.24.7",
    "@babel/eslint-parser": "^7.24.7",
    "@babel/plugin-transform-runtime": "^7.24.7",
    "@babel/preset-env": "^7.24.7",
    "@rollup/plugin-babel": "^6.0.4",
    "@rollup/plugin-commonjs": "^26.0.1",
    "@rollup/plugin-node-resolve": "^15.2.3",
    "@rollup/plugin-terser": "^0.4.4",
    "@target/custom-event-polyfill": "github:Adobe-Marketing-Cloud/custom-event-polyfill",
    "@types/jasmine": "^5.1.4",
    "babel-plugin-polyfill-corejs3": "^0.10.4",
    "core-js": "^3.37.1",
    "coveralls": "^3.1.1",
    "eslint": "^8.57.0",
    "eslint-config-prettier": "^9.1.0",
    "eslint-config-standard": "^17.1.0",
    "http-server": "^14.1.1",
    "jasmine": "^5.1.0",
    "jasmine-core": "^5.1.2",
    "karma": "^6.4.3",
    "karma-chrome-launcher": "^3.2.0",
    "karma-coverage": "^2.2.1",
    "karma-firefox-launcher": "^2.1.3",
    "karma-jasmine": "^5.1.0",
    "karma-sauce-launcher": "^4.3.6",
    "prettier": "^3.3.2",
    "rollup": "^4.18.0",
    "rollup-plugin-filesize": "^10.0.0",
    "svgdom": "^0.1.19",
    "typescript": "^5.4.5",
    "yargs": "^17.7.2"
  },
  "browserslist": ">0.3%, last 2 version, not dead, not op_mini all"
}


================================================
FILE: playgrounds/colors/main.js
================================================
let canvas = SVG('#canvas').group().translate(-150, 230)

// Make a bunch of rectangles
function rectangles(method = 'Vibrant') {
  // Make a group
  let group = canvas.group()
  group.text(method).attr('font-size', 50).move(-230, 20)

  // Add the squares
  for (let i = 0; i < 20; i++) {
    let color = SVG.Color.random(method.toLowerCase()).toHex()
    let rect = group
      .rect(100, 100)
      .x(20 + 100 * i)
      .fill(color)
  }
  return group
}

rectangles('Vibrant').translate(0, 100)
rectangles('Sine').translate(0, 220)
rectangles('Pastel').translate(0, 340)
rectangles('Dark').translate(0, 460)
rectangles('RGB').translate(0, 580)
rectangles('LAB').translate(0, 700)
rectangles('Grey').translate(0, 820)


================================================
FILE: playgrounds/colors/style.css
================================================
* {
  box-sizing: border-box;
}

html {
  background-color: #fefefe;
}

body {
  margin: 0;
  width: 100vw;
  height: 99vh;
  grid-gap: 30px;
  display: inline-grid;
  align-items: center;
  grid-template-columns: 10vw 40vw auto 10vw;
  grid-template-rows: 0 10vw auto 0;
}

h1 {
  text-align: right;
  border-right: solid 3px #f06;
  padding-right: 12px;
  color: #f06;
  font-size: 52px;
  font-family: Helvetica;
  grid-row: 2;
  grid-column: 2;
  line-height: 1.8em;
}

p {
  padding-right: 50px;
  color: #444;
  font-size: 18px;
  font-family: Helvetica;
  grid-row: 2;
  grid-column: 3;
}

svg {
  height: 100%;
  width: 100%;
  grid-row: 3;
  grid-column: 2/4;
  background-color: #f5f6f7;
  border-radius: 20px;
  border: #f065 1px solid;
}

.pink {
  fill: #ff0066;
}

.green {
  fill: #00ff99;
}

.dark-pink {
  fill: #660029;
}

.light-pink {
  fill: #ff99c2;
}

.off-white {
  fill: #ffcce0;
}


================================================
FILE: playgrounds/matrix/drag.js
================================================
function reactToDrag(element, onDrag, beforeDrag) {
  let xStart, yStart
  let startDrag = (event) => {
    // Avoid the default events
    event.preventDefault()

    // Store the position where the drag started
    xStart = event.pageX
    yStart = event.pageY

    // Fire the start drag event
    if (beforeDrag) {
      var { x, y } = parent.point(event.pageX, event.pageY)
      beforeDrag(event, x, y)
    }

    // Register events to react to dragging and drag ends
    SVG.on(window, ['mousemove.drag', 'touchmove.drag'], reactDrag)
    SVG.on(window, ['mouseup.drag', 'touchend.drag'], stopDrag)
  }

  let reactDrag = (event) => {
    // Convert screen coordinates to svg coordinates and use them
    var { x, y } = parent.point(event.pageX, event.pageY)
    if (onDrag) onDrag(event, x, y)
  }

  let stopDrag = (event) => {
    SVG.off(window, ['mousemove.drag', 'touchmove.drag'])
    SVG.off(window, ['mouseup.drag', 'touchend.drag'])
  }

  // Bind the drag tracker to this element directly
  let parent = element.root()
  let point = new SVG.Point()
  element.mousedown(startDrag).touchstart(startDrag)
}

SVG.extend(SVG.Element, {
  draggable: function (after) {
    let sx, sy

    reactToDrag(
      this,
      (e, x, y) => {
        this.transform({
          origin: [sx, sy],
          position: [x, y]
        })

        if (after) {
          after(this, x, y)
        }
      },
      (e, x, y) => {
        var toAbsolute = new SVG.Matrix(this).inverse()
        var p = new SVG.Point(x, y).transform(toAbsolute)
        sx = p.x
        sy = p.y
      }
    )
    return this
  }
})


================================================
FILE: playgrounds/matrix/matrix.js
================================================
function print(mat) {
  let { a, b, c, d } = mat
  console.log(`
    a: ${a.toFixed(2)}
    b: ${b.toFixed(2)}
    c: ${c.toFixed(2)}
    d: ${d.toFixed(2)}
    `)
}

function moveit() {
  let { cx: x0, cy: y0 } = or.rbox(svg)
  let { cx: x1, cy: y1 } = b1.rbox(svg)
  let { cx: x2, cy: y2 } = b2.rbox(svg)

  let m = new SVG.Matrix(
    (x1 - x0) / 50,
    (y1 - y0) / 50,
    (x2 - x0) / 50,
    (y2 - y0) / 50,
    x0,
    y0
  )
  let com = m.decompose()
  let g = new SVG.Matrix().compose(com)

  // Transform both of the items
  target.transform(m)
  mover.transform(g)

  console.log(com)
  print(m)
  print(g)
}

// Declare the two points
let svg = SVG('svg')
var or = SVG('#or').draggable(moveit)
var b1 = SVG('#b1').draggable(moveit)
var b2 = SVG('#b2').draggable(moveit)

// Declare the squares
let target = SVG('#true')
let mover = SVG('#guess')
let tester = SVG('#tester')


================================================
FILE: playgrounds/matrix/style.css
================================================
* {
  box-sizing: border-box;
}

html {
  background-color: #fefefe;
}

body {
  margin: 0;
  width: 100vw;
  height: 99vh;
  grid-gap: 30px;
  display: inline-grid;
  align-items: center;
  grid-template-columns: 10vw 40vw auto 10vw;
  grid-template-rows: 0 10vw auto 0;
}

h1 {
  text-align: right;
  border-right: solid 3px #f06;
  padding-right: 12px;
  color: #f06;
  font-size: 52px;
  font-family: Helvetica;
  grid-row: 2;
  grid-column: 2;
  line-height: 1.8em;
}

p {
  padding-right: 50px;
  color: #444;
  font-size: 18px;
  font-family: Helvetica;
  grid-row: 2;
  grid-column: 3;
}

svg {
  height: 100%;
  width: 100%;
  grid-row: 3;
  grid-column: 2/4;
  background-color: #f5f6f7;
  border-radius: 20px;
  border: #f065 1px solid;
}

.pink {
  fill: #ff0066;
}

.green {
  fill: #00ff99;
}

.dark-pink {
  fill: #660029;
}

.light-pink {
  fill: #ff99c2;
}

.off-white {
  fill: #ffcce0;
}


================================================
FILE: playgrounds/transforms/style.css
================================================
* {
  box-sizing: border-box;
}

html {
  background-color: #fefefe;
}

body {
  margin: 0;
  width: 100vw;
  height: 99vh;
  grid-gap: 30px;
  display: inline-grid;
  align-items: center;
  grid-template-columns: 10vw 40vw auto 10vw;
  grid-template-rows: 0 10vw auto 0;
}

h1 {
  text-align: right;
  border-right: solid 3px #f06;
  padding-right: 12px;
  color: #f06;
  font-size: 52px;
  font-family: Helvetica;
  grid-row: 2;
  grid-column: 2;
  line-height: 1.8em;
}

p {
  padding-right: 50px;
  color: #444;
  font-size: 18px;
  font-family: Helvetica;
  grid-row: 2;
  grid-column: 3;
}

svg {
  height: 100%;
  width: 100%;
  grid-row: 3;
  grid-column: 2/4;
  background-color: #f5f6f7;
  border-radius: 20px;
  border: #f065 1px solid;
}

.pink {
  fill: #ff0066;
}

.green {
  fill: #00ff99;
}

.dark-pink {
  fill: #660029;
}

.light-pink {
  fill: #ff99c2;
}

.off-white {
  fill: #ffcce0;
}


================================================
FILE: playgrounds/transforms/transforms.js
================================================
let canvas = SVG('#canvas')

// Make the green rectangle
canvas.rect(200, 400).move(200, 400).attr('opacity', 0.3).addClass('green')

// Make the pink rectangle
let a = canvas
  .rect(200, 400)
  .move(200, 400)
  .attr('opacity', 0.3)
  .addClass('pink')
  .transform({ px: 100, py: 500, origin: 'top-left' })

a.animate().rotate({ rotate: 500, origin: 'top-right' })

// Put an ellipse where we expect the object to be
canvas
  .ellipse(30, 30)
  .center(100, 500)
  .attr('opacity', 0.3)
  .addClass('dark-pink')


================================================
FILE: playgrounds/webpack.config.js
================================================
var path = require('path')
module.exports = function (env) {
  let currentTest = path.resolve(__dirname, env)
  return {
    mode: 'development',
    devtool: 'eval-source-map',
    devServer: {
      contentBase: [currentTest, __dirname]
    },

    devServer: {
      contentBase: [currentTest, '..']
    },

    entry: {
      app: path.resolve(currentTest, 'main.js')
    },

    output: {
      path: currentTest,
      filename: 'bundle.js'
    },

    resolve: {
      modules: [path.resolve(__dirname, 'node_modules'), 'node_modules']
    }
  }
}


================================================
FILE: spec/RAFPlugin.js
================================================
/* globals jasmine */
/**
 * Jasmine RequestAnimationFrame: a set of helpers for testing functionality
 * that uses requestAnimationFrame under the Jasmine BDD framework for JavaScript.
 */
function RAFPlugin(jasmine) {
  var index = 0
  var callbacks = []

  function MockRAF() {
    this.nextTime = 0

    var _this = this

    /**
     * Mock for window.requestAnimationFrame
     */
    this.mockRAF = function (fn) {
      if (typeof fn !== 'function') {
        throw new Error('You should pass a function to requestAnimationFrame')
      }

      const i = index++
      callbacks[i] = fn

      return i
    }

    /**
     * Mock for window.cancelAnimationFrame
     */
    this.mockCAF = function (requestID) {
      callbacks.splice(requestID, 1)
    }

    this.mockPerf = {
      now: function () {
        return _this.nextTime
      }
    }

    /**
     * Install request animation frame mocks.
     */
    this.install = function (global) {
      _this.realRAF = global.requestAnimationFrame
      _this.realCAF = global.cancelAnimationFrame
      _this.realPerf = global.performance
      global.requestAnimationFrame = _this.mockRAF
      global.cancelAnimationFrame = _this.mockCAF
      global.performance = _this.mockPerf
    }

    /**
     * Uninstall request animation frame mocks.
     */
    this.uninstall = function (global) {
      global.requestAnimationFrame = _this.realRAF
      global.cancelAnimationFrame = _this.realCAF
      global.performance = _this.realPerf
      _this.nextTime = 0
      callbacks = []
    }

    /**
     * Simulate animation frame readiness.
     */
    this.tick = function (dt) {
      _this.nextTime += dt || 1

      var fns = callbacks
      var fn
      var i

      callbacks = []
      index = 0

      for (i in fns) {
        fn = fns[i]
        fn(_this.nextTime)
      }
    }
  }

  jasmine.RequestAnimationFrame = new MockRAF()
}

RAFPlugin(jasmine)


================================================
FILE: spec/SpecRunner.html
================================================
<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>SVG.js - Jasmine Spec Runner</title>

    <link
      rel="shortcut icon"
      type="image/png"
      href="../node_modules/jasmine-core/images/jasmine_favicon.png"
    />
    <link
      rel="stylesheet"
      href="../node_modules/jasmine-core/lib/jasmine-core/jasmine.css"
    />

    <script src="../node_modules/jasmine-core/lib/jasmine-core/jasmine.js"></script>
    <script src="../node_modules/jasmine-core/lib/jasmine-core/jasmine-html.js"></script>
    <script src="../node_modules/jasmine-core/lib/jasmine-core/boot.js"></script>
    <script src="RAFPlugin.js"></script>

    <link rel="stylesheet" href="fixtures/fixture.css" />
  </head>

  <body>
    <!-- include spec files here... -->

    <script src="../dist/polyfillsIE.js"></script>
    <script src="es5TestBundle.js"></script>
  </body>
</html>


================================================
FILE: spec/SpecRunnerEs6.html
================================================
<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>SVG.js - Jasmine Spec Runner</title>

    <link
      rel="shortcut icon"
      type="image/png"
      href="../node_modules/jasmine-core/images/jasmine_favicon.png"
    />
    <link
      rel="stylesheet"
      href="../node_modules/jasmine-core/lib/jasmine-core/jasmine.css"
    />

    <script src="../node_modules/jasmine-core/lib/jasmine-core/jasmine.js"></script>
    <script src="../node_modules/jasmine-core/lib/jasmine-core/jasmine-html.js"></script>
    <script src="../node_modules/jasmine-core/lib/jasmine-core/boot.js"></script>
    <script src="RAFPlugin.js"></script>

    <link rel="stylesheet" href="fixtures/fixture.css" />
  </head>

  <body>
    <!-- include spec files here... -->
    <script type="module" src="setupBrowser.js"></script>
    <script type="module" src="spec/elements/A.js"></script>
    <script type="module" src="spec/elements/Circle.js"></script>
    <script type="module" src="spec/elements/ClipPath.js"></script>
    <script type="module" src="spec/elements/Container.js"></script>
    <script type="module" src="spec/elements/Dom.js"></script>
    <script type="module" src="spec/elements/Element.js"></script>
    <script type="module" src="spec/elements/ForeignObject.js"></script>
    <script type="module" src="spec/elements/G.js"></script>
    <script type="module" src="spec/elements/Image.js"></script>
    <script type="module" src="spec/elements/Marker.js"></script>
    <script type="module" src="spec/elements/Svg.js"></script>
    <script type="module" src="spec/elements/Text.js"></script>
    <script type="module" src="spec/elements/TextPath.js"></script>
    <script type="module" src="spec/elements/Tspan.js"></script>
    <script type="module" src="spec/modules/core/event.js"></script>
    <script type="module" src="spec/modules/core/textable.js"></script>
    <script type="module" src="spec/types/ArrayPolyfill.js"></script>
    <script type="module" src="spec/types/Base.js"></script>
    <script type="module" src="spec/types/Box.js"></script>
    <script type="module" src="spec/utils/adopter.js"></script>
    <script type="module" src="spec/utils/utils.js"></script>
  </body>
</html>


================================================
FILE: spec/checkForAllTests.js
================================================
const glob = require('glob')
const path = require('path')

glob('./spec/*/**/*.js', (err, tests) => {
  if (err) {
    throw err
  }

  glob('./src/**/*.js', (err, files) => {
    if (err) {
      throw err
    }

    files = files.map((e) => path.basename(e))
    tests = tests.map((e) => path.basename(e))
    const difference = files.filter((x) => !tests.includes(x))

    if (difference.length) {
      console.error(
        'The following files dont have a test file:\n\t' +
          difference.join('\n\t')
      )
    } else {
      console.info('All src files are covered by tests')
    }
  })
})


================================================
FILE: spec/fixtures/fixture.css
================================================
#drawing {
  width: 500px;
  height: 500px;
  position: fixed;
  z-index: -1;
}


================================================
FILE: spec/helpers.js
================================================
import { getWindow } from '../src/utils/window.js'
import { svg } from '../src/modules/core/namespaces.js'

function tag(name, attrs, children) {
  const doc = getWindow().document
  const el = doc.createElementNS(svg, name)
  let i

  for (i in attrs) {
    el.setAttribute(i, attrs[i])
  }

  for (i in children) {
    if (typeof children[i] === 'string') {
      children[i] = doc.createTextNode(children[i])
    }

    el.appendChild(children[i])
  }

  return el
}

export function fixtures() {
  return tag(
    'svg',
    {
      height: 0,
      width: 0,
      id: 'inlineSVG'
    },
    [
      tag('defs', {}, [
        tag('linearGradient', {}, [
          tag('stop', { offset: '5%', 'stop-color': 'green' }),
          tag('stop', { offset: '95%', 'stop-color': 'gold' })
        ]),
        tag('radialGradient', {}, [
          tag('stop', { offset: '5%', 'stop-color': 'green' }),
          tag('stop', { offset: '95%', 'stop-color': 'gold' })
        ])
      ]),
      tag('desc', {}, ['Some description']),
      tag('path', {
        id: 'lineAB',
        d: 'M 100 350 l 150 -300',
        stroke: 'red',
        'stroke-width': '3',
        fill: 'none'
      }),
      tag('path', {
        id: 'lineBC',
        d: 'M 250 50 l 150 300',
        stroke: 'red',
        'stroke-width': '3',
        fill: 'none'
      }),
      tag('path', {
        d: 'M 175 200 l 150 0',
        stroke: 'green',
        'stroke-width': '3',
        fill: 'none'
      }),
      tag('path', {
        d: 'M 100 350 q 150 -300 300 0',
        stroke: 'blue',
        'stroke-width': '5',
        fill: 'none'
      }),
      tag(
        'g',
        {
          stroke: 'black',
          'stroke-width': '2',
          fill: 'black',
          id: 'pointGroup'
        },
        [
          tag('circle', {
            id: 'pointA',
            cx: '100',
            cy: '350',
            r: '3'
          }),
          tag('circle', {
            id: 'pointB',
            cx: '250',
            cy: '50',
            r: '50'
          }),
          tag('circle', {
            id: 'pointC',
            cx: '400',
            cy: '350',
            r: '50'
          })
        ]
      ),
      tag(
        'g',
        {
          'font-size': '30',
          font: 'sans-serif',
          fill: 'black',
          stroke: 'none',
          'text-anchor': 'middle',
          id: 'labelGroup'
        },
        [
          tag(
            'text',
            {
              x: '100',
              y: '350',
              dy: '-30'
            },
            ['A']
          ),
          tag(
            'text',
            {
              x: '250',
              y: '50',
              dy: '-10'
            },
            ['B']
          ),
          tag(
            'text',
            {
              x: '400',
              y: '350',
              dx: '30'
            },
            ['C']
          )
        ]
      ),
      tag('polygon', { points: '200,10 250,190 160,210' }),
      tag('polyline', { points: '20,20 40,25 60,40 80,120 120,140 200,180' })
    ]
  )
}

export function buildFixtures() {
  const doc = getWindow().document
  const body = doc.body || doc.documentElement

  const div = doc.createElement('div')
  div.id = 'fixtures'

  try {
    // FIXME: doesn't work in svgdom
    div.style.position = 'absolute'
    div.style.top = 0
    div.style.left = 0
  } catch (e) {
    //
  }

  div.appendChild(fixtures())
  body.appendChild(div)
}

export function buildCanvas() {
  const doc = getWindow().document
  const body = doc.body || doc.documentElement

  const div = doc.createElement('div')
  div.id = 'canvas'

  try {
    // FIXME: doesn't work in svgdom
    div.style.position = 'absolute'
    div.style.top = 0
    div.style.left = 0
  } catch (e) {
    //
  }
  body.appendChild(div)
}

export function clear() {
  const doc = getWindow().document
  const canvas = doc.getElementById('canvas')
  const fixtures = doc.getElementById('fixtures')

  // remove if present
  fixtures && fixtures.parentNode.removeChild(fixtures)
  canvas.parentNode.removeChild(canvas)
  ;[...doc.querySelectorAll('svg')].forEach((el) =>
    el.parentNode.removeChild(el)
  )
}


================================================
FILE: spec/runSVGDomTest.js
================================================
/*
  This file has to be run with esm because node does not understand imports yet:
  node -r esm ./spec/runSvgdomTest.js || true

  Without "|| true" node reports a super long error when a test fails
 */

import Jasmine from 'jasmine'
const jasmine = new Jasmine()

jasmine.loadConfig({
  spec_dir: '/',
  spec_files: ['spec/spec/*/**/*.js'],
  helpers: ['spec/setupSVGDom.js']
})

jasmine.execute()


================================================
FILE: spec/setupBrowser.js
================================================
/* globals beforeEach, afterEach, jasmine */
import { buildCanvas, clear } from './helpers.js'

jasmine.DEFAULT_TIMEOUT_INTERVAL = 500

beforeEach(() => {
  // buildFixtures()
  buildCanvas()
  window.container = document.getElementById('canvas')
})

afterEach(() => {
  clear()
  window.container = null
})


================================================
FILE: spec/setupSVGDom.js
================================================
import './RAFPlugin.js'
import { createHTMLWindow } from 'svgdom'

/* globals beforeEach, afterEach, jasmine */
import { buildCanvas, clear } from './helpers.js'
import { registerWindow } from '../src/main.js'

jasmine.DEFAULT_TIMEOUT_INTERVAL = 200

function setup() {
  const win = createHTMLWindow()
  registerWindow(win, win.document)
  buildCanvas()
  // buildFixtures()
  global.container = win.document.getElementById('canvas')
}

function teardown() {
  clear()
  global.container = null
  registerWindow()
}

beforeEach(setup)
afterEach(teardown)


================================================
FILE: spec/spec/animation/Animator.js
================================================
/* globals describe, expect, it, beforeEach, afterEach, jasmine */

import { Animator, Queue } from '../../../src/main.js'
import { getWindow } from '../../../src/utils/window.js'

describe('Animator.js', () => {
  beforeEach(() => {
    jasmine.RequestAnimationFrame.install(getWindow())
    Animator.timeouts = new Queue()
    Animator.frames = new Queue()
    Animator.immediates = new Queue()
    Animator.nextDraw = null
  })

  afterEach(() => {
    jasmine.RequestAnimationFrame.uninstall(getWindow())
  })

  describe('timeout()', () => {
    it('calls a function after a specific time', () => {
      var spy = jasmine.createSpy('tester')
      Animator.timeout(spy, 100)

      jasmine.RequestAnimationFrame.tick(99)
      expect(spy).not.toHaveBeenCalled()
      jasmine.RequestAnimationFrame.tick()
      expect(spy).toHaveBeenCalled()
    })
  })

  describe('cancelTimeout()', () => {
    it('cancels a timeout which was created with timeout()', () => {
      var spy = jasmine.createSpy('tester')
      var id = Animator.timeout(spy, 100)
      Animator.clearTimeout(id)

      expect(spy).not.toHaveBeenCalled()
      jasmine.RequestAnimationFrame.tick(100)
      expect(spy).not.toHaveBeenCalled()
    })
  })

  describe('frame()', () => {
    it('calls a function at the next animationFrame', () => {
      var spy = jasmine.createSpy('tester')

      Animator.frame(spy)
      expect(spy).not.toHaveBeenCalled()
      jasmine.RequestAnimationFrame.tick()
      expect(spy).toHaveBeenCalled()
    })
  })

  describe('cancelFrame()', () => {
    it('cancels a single frame which was created with frame()', () => {
      var spy = jasmine.createSpy('tester')

      const id = Animator.frame(spy)
      Animator.cancelFrame(id)

      expect(spy).not.toHaveBeenCalled()
      jasmine.RequestAnimationFrame.tick()
      expect(spy).not.toHaveBeenCalled()
    })
  })

  describe('immediate()', () => {
    it('calls a function at the next animationFrame but after all frames are processed', () => {
      var spy = jasmine.createSpy('tester')

      Animator.immediate(spy)

      expect(spy).not.toHaveBeenCalled()
      jasmine.RequestAnimationFrame.tick()
      expect(spy).toHaveBeenCalled()
    })
  })

  describe('cancelImmediate()', () => {
    it('cancels an immediate cakk which was created with immediate()', () => {
      var spy = jasmine.createSpy('tester')

      const id = Animator.immediate(spy)
      Animator.cancelImmediate(id)

      expect(spy).not.toHaveBeenCalled()
      jasmine.RequestAnimationFrame.tick()
      expect(spy).not.toHaveBeenCalled()
    })
  })
})


================================================
FILE: spec/spec/animation/Controller.js
================================================
/* globals describe, expect, it, jasmine */

import { easing, defaults } from '../../../src/main.js'
import {
  Stepper,
  Ease,
  Controller,
  Spring,
  PID
} from '../../../src/animation/Controller.js'

const { any, createSpy } = jasmine

describe('Controller.js', () => {
  describe('easing', () => {
    var easedValues = {
      '-': 0.5,
      '<>': 0.5,
      '>': 0.7071,
      '<': 0.2929
    }

    ;['-', '<>', '<', '>'].forEach((el) => {
      describe(el, () => {
        it('is 0 at 0', () => {
          expect(easing[el](0)).toBe(0)
        })
        it('is 1 at 1', () => {
          expect(Math.round(easing[el](1) * 1000) / 1000).toBe(1) // we need to round cause for some reason at some point 1==0.999999999
        })
        it('is eased at 0.5', () => {
          expect(easing[el](0.5)).toBeCloseTo(easedValues[el])
        })
      })
    })

    describe('beziere()', () => {
      const b1 = easing.bezier(0.25, 0.25, 0.75, 0.75)
      const b2 = easing.bezier(-0.25, -0.25, 0.75, 0.75)
      const b3 = easing.bezier(0.5, 0.5, 2, 2)
      const b4 = easing.bezier(1, 1, 2, 2)
      const b5 = easing.bezier(-1, -1, -2, -2)

      it('is 0 at 0', () => {
        expect(b1(0)).toBe(0)
      })

      it('is 1 at 1', () => {
        expect(b1(1)).toBe(1)
      })

      it('is eased at 0.5', () => {
        expect(b1(0.5)).toBe(0.5)
        expect(b2(0.5)).toBe(0.3125)
        expect(b3(0.5)).toBe(1.0625)
        expect(b4(0.5)).toBe(1.25)
        expect(b5(0.5)).toBe(-1)
      })

      it('handles values bigger 1', () => {
        expect(b1(1.5)).toBe(1.5)
        expect(b2(1.5)).toBe(1.5)
        expect(b3(1.5)).toBe(1.5)
        expect(b4(1.5)).toBe(1)
        expect(b5(1.5)).toBe(1.5)
      })

      it('handles values lower 0', () => {
        expect(b1(-0.5)).toBe(-0.5)
        expect(b2(-0.5)).toBe(-0.5)
        expect(b3(-0.5)).toBe(-0.5)
        expect(b4(-0.5)).toBe(-0.5)
        expect(b5(-0.5)).toBe(0)
      })
    })

    describe('steps()', () => {
      const s1 = easing.steps(5)
      const s2 = easing.steps(5, 'start')
      const s3 = easing.steps(5, 'end')
      const s4 = easing.steps(5, 'none')
      const s5 = easing.steps(5, 'both')

      it('is 0 at 0', () => {
        expect(s1(0)).toBe(0)
        expect(s1(0, true)).toBe(0)
        expect(s2(0)).toBe(0.2)
        expect(s2(0, true)).toBe(0)
        expect(s3(0)).toBe(0)
        expect(s3(0, true)).toBe(0)
        expect(s4(0)).toBe(0)
        expect(s4(0, true)).toBe(0)
        expect(s5(0)).toBe(1 / 6)
        expect(s5(0, true)).toBe(0)
      })

      it('also works at values < 0', () => {
        expect(s1(-0.1)).toBe(-0.2)
        expect(s1(-0.1, true)).toBe(-0.2)
        expect(s2(-0.1)).toBe(0)
        expect(s2(-0.1, true)).toBe(0)
        expect(s3(-0.1)).toBe(-0.2)
        expect(s3(-0.1, true)).toBe(-0.2)
        expect(s4(-0.1)).toBe(-0.25)
        expect(s4(-0.1, true)).toBe(-0.25)
        expect(s5(-0.1)).toBe(0)
        expect(s5(-0.1, true)).toBe(0)
      })

      it('is 1 at 1', () => {
        expect(s1(1)).toBe(1)
        expect(s1(1, true)).toBe(0.8)
        expect(s2(1)).toBe(1)
        expect(s2(1, true)).toBe(1)
        expect(s3(1)).toBe(1)
        expect(s3(1, true)).toBe(0.8)
        expect(s4(1)).toBe(1)
        expect(s4(1, true)).toBe(1)
        expect(s5(1)).toBe(1)
        expect(s5(1, true)).toBe(5 / 6)
      })

      it('also works at values > 1', () => {
        expect(s1(1.1)).toBe(1)
        expect(s1(1.1, true)).toBe(1)
        expect(s2(1.1)).toBe(1.2)
        expect(s2(1.1, true)).toBe(1.2)
        expect(s3(1.1)).toBe(1)
        expect(s3(1.1, true)).toBe(1)
        expect(s4(1.1)).toBe(1.25)
        expect(s4(1.1, true)).toBe(1.25)
        expect(s5(1.1)).toBe(1)
        expect(s5(1.1, true)).toBe(1)
      })

      it('is eased at 0.1', () => {
        expect(s1(0.1)).toBe(0)
        expect(s1(0.1, true)).toBe(0)
        expect(s2(0.1)).toBe(0.2)
        expect(s2(0.1, true)).toBe(0)
        expect(s3(0.1)).toBe(0)
        expect(s3(0.1, true)).toBe(0)
        expect(s4(0.1)).toBe(0)
        expect(s4(0.1, true)).toBe(0)
        expect(s5(0.1)).toBe(1 / 6)
        expect(s5(0.1, true)).toBe(0)
      })

      it('is eased at 0.15', () => {
        expect(s1(0.15)).toBe(0)
        expect(s1(0.15, true)).toBe(0)
        expect(s2(0.15)).toBe(0.2)
        expect(s2(0.15, true)).toBe(0)
        expect(s3(0.15)).toBe(0)
        expect(s3(0.15, true)).toBe(0)
        expect(s4(0.15)).toBe(0)
        expect(s4(0.15, true)).toBe(0)
        expect(s5(0.15)).toBe(1 / 6)
        expect(s5(0.15, true)).toBe(0)
      })

      it('is eased at 0.2', () => {
        expect(s1(0.2)).toBe(0.2)
        expect(s1(0.2, true)).toBe(0.2)
        expect(s2(0.2)).toBe(0.4)
        expect(s2(0.2, true)).toBe(0.4)
        expect(s3(0.2)).toBe(0.2)
        expect(s3(0.2, true)).toBe(0.2)
        expect(s4(0.2)).toBe(0.25)
        expect(s4(0.2, true)).toBe(0.25)
        expect(s5(0.2)).toBe(1 / 3)
        expect(s5(0.2, true)).toBe(1 / 3)
      })

      it('is eased at 0.25', () => {
        expect(s1(0.25)).toBe(0.2)
        expect(s1(0.25, true)).toBe(0.2)
        expect(s2(0.25)).toBe(0.4)
        expect(s2(0.25, true)).toBe(0.4)
        expect(s3(0.25)).toBe(0.2)
        expect(s3(0.25, true)).toBe(0.2)
        expect(s4(0.25)).toBe(0.25)
        expect(s4(0.25, true)).toBe(0.25)
        expect(s5(0.25)).toBe(1 / 3)
        expect(s5(0.25, true)).toBe(1 / 3)
      })
    })
  })

  describe('Stepper', () => {
    it('has a done() method', () => {
      const stepper = new Stepper()
      expect(stepper).toEqual(any(Stepper))
      expect(stepper.done()).toBe(false)
    })
  })

  describe('Ease', () => {
    describe('()', () => {
      it('wraps the default easing function by default', () => {
        const ease = new Ease()
        expect(ease.ease).toBe(easing[defaults.timeline.ease])
      })

      it('wraps an easing function found in "easing"', () => {
        const ease = new Ease('-')
        expect(ease.ease).toBe(easing['-'])
      })

      it('wraps a a custom easing function', () => {
        const ease = new Ease(easing['-'])
        expect(ease.ease).toBe(easing['-'])
      })
    })

    describe('step()', () => {
      it('provides an eased value to a position', () => {
        let ease = new Ease(easing['-'])
        expect(ease.step(2, 4, 0.5)).toBe(3)

        ease = new Ease(() => 3)
        expect(ease.step(2, 4, 0.5)).toBe(8)

        ease = new Ease()
        expect(ease.step(2, 4, 0.5)).toBeCloseTo(3.414, 3)
      })

      it('jumps to "to" value at pos 1 if from is not a number', () => {
        const ease = new Ease('-')
        expect(ease.step('Hallo', 'Welt', 0.999)).toBe('Hallo')
        expect(ease.step('Hallo', 'Welt', 1)).toBe('Welt')
      })
    })
  })

  describe('Controller', () => {
    describe('()', () => {
      it('constructs a controller with the given stepper function set', () => {
        const spy = createSpy()
        const controller = new Controller(spy)
        expect(controller).toEqual(any(Controller))
        expect(controller.stepper).toBe(spy)
      })
    })

    describe('step()', () => {
      it('runs the stepper with current value, target value, dt and context', () => {
        const spy = createSpy().and.returnValue('foo')
        const controller = new Controller(spy)
        expect(controller.step(10, 20, 30, 'bar')).toBe('foo')
        expect(spy).toHaveBeenCalledWith(10, 20, 30, 'bar')
      })
    })

    describe('done()', () => {
      it('returns given values "done" property', () => {
        const spy = createSpy()
        const controller = new Controller(spy)
        expect(controller.done({ done: 'yes' })).toBe('yes')
      })
    })
  })

  describe('Spring', () => {
    describe('()', () => {
      it('creates a spring with default duration and overshoot', () => {
        const spring = new Spring()
        expect(spring).toEqual(any(Spring))
        expect(spring.duration()).toBe(500)
        expect(spring.overshoot()).toBe(0)
      })

      it('creates a spring with given duration and overshoot', () => {
        const spring = new Spring(100, 10)
        expect(spring).toEqual(any(Spring))
        expect(spring.duration()).toBe(100)
        expect(spring.overshoot()).toBe(10)
      })
    })

    describe('duration()', () => {
      it('gets and sets a new duration for the spring controller', () => {
        const spring = new Spring().duration(100)
        expect(spring.duration()).toBe(100)
      })
    })

    describe('overshoot()', () => {
      it('gets and sets a new overshoot for the spring controller', () => {
        const spring = new Spring().overshoot(10)
        expect(spring.overshoot()).toBe(10)
      })
    })

    describe('step()', () => {
      it('calculates the new spring position', () => {
        const spring = new Spring()
        expect(spring.step(0, 100, 16, {})).toBeCloseTo(0.793, 3)
      })

      it('returns current if current is a string', () => {
        const spring = new Spring()
        expect(spring.step('Hallo', 'Welt', 16, {})).toBe('Hallo')
      })

      it('returns current if dt is 0', () => {
        const spring = new Spring()
        expect(spring.step(0, 100, 0, {})).toBe(0)
      })

      it('is done if dt is infinity and returns target', () => {
        const spring = new Spring()
        const context = {}
        expect(spring.step(0, 100, Infinity, context)).toBe(100)
        expect(spring.done(context)).toBe(true)
      })

      it('uses dt of 16 if it is over 100', () => {
        const spring = new Spring()
        expect(spring.step(0, 100, 101, {})).toBe(spring.step(0, 100, 16, {}))
      })
    })
  })

  describe('PID', () => {
    describe('()', () => {
      it('creates a PID controller with default values', () => {
        const pid = new PID()
        expect(pid).toEqual(any(PID))
        expect(pid.p()).toBe(0.1)
        expect(pid.i()).toBe(0.01)
        expect(pid.d()).toBe(0)
        expect(pid.windup()).toBe(1000)
      })

      it('creates a PID controller with given values', () => {
        const pid = new PID(1, 2, 3, 4)
        expect(pid).toEqual(any(PID))
        expect(pid.p()).toBe(1)
        expect(pid.i()).toBe(2)
        expect(pid.d()).toBe(3)
        expect(pid.windup()).toBe(4)
      })
    })

    describe('p()', () => {
      it('gets and sets the p parameter of the controller', () => {
        const pid = new PID().p(100)
        expect(pid.p()).toBe(100)
      })
    })

    describe('i()', () => {
      it('gets and sets the i parameter of the controller', () => {
        const pid = new PID().i(100)
        expect(pid.i()).toBe(100)
      })
    })

    describe('d()', () => {
      it('gets and sets the d parameter of the controller', () => {
        const pid = new PID().d(100)
        expect(pid.d()).toBe(100)
      })
    })

    describe('windup()', () => {
      it('gets and sets the windup parameter of the controller', () => {
        const pid = new PID().windup(100)
        expect(pid.windup()).toBe(100)
      })
    })

    describe('step()', () => {
      it('returns current if current is a string', () => {
        const pid = new PID()
        expect(pid.step('Hallo', 'Welt', 16, {})).toBe('Hallo')
      })

      it('returns current if dt is 0', () => {
        const pid = new PID()
        expect(pid.step(0, 100, 0, {})).toBe(0)
      })

      it('is done if dt is infinity and returns target', () => {
        const pid = new PID()
        const context = {}
        expect(pid.step(0, 100, Infinity, context)).toBe(100)
        expect(pid.done(context)).toBe(true)
      })

      it('calculates a new value', () => {
        const pid = new PID()
        expect(pid.step(0, 100, 16, {})).toBe(20)
      })

      it('uses antiwindup to restrict i power', () => {
        const pid = new PID(0, 5, 0, 100)
        expect(pid.step(0, 100, 1000, {})).toBe(500)
      })

      it('does not use antiwindup if disabled', () => {
        const pid = new PID(0, 5, 0, false)
        expect(pid.step(0, 100, 1000, {})).toBe(500000)
      })
    })
  })
})


================================================
FILE: spec/spec/animation/Morphable.js
================================================
/* globals describe, expect, it, jasmine */

import {
  Morphable,
  NonMorphable,
  ObjectBag,
  Color,
  Box,
  Matrix,
  PointArray,
  PathArray,
  TransformBag,
  Number as SVGNumber,
  Array as SVGArray
} from '../../../src/main.js'
import { Stepper, easing, Ease } from '../../../src/animation/Controller.js'

const { objectContaining, arrayContaining, any } = jasmine

describe('Morphable.js', () => {
  describe('()', () => {
    it('sets a default stepper', () => {
      const morpher = new Morphable()
      expect(morpher.stepper().ease).toBe(easing['-'])
    })

    it('sets the passed stepper', () => {
      const ease = new Ease()
      const morpher = new Morphable(ease)
      expect(morpher.stepper()).toBe(ease)
    })
  })

  describe('constructors', () => {
    it('Morphable with SVGNumber', () => {
      const morpher = new Morphable().from(10).to(5)

      expect(morpher).toEqual(any(Morphable))
      expect(morpher.type()).toBe(SVGNumber)
      expect(morpher.at(0.5)).toEqual(any(SVGNumber))
      expect(morpher.at(0.5).valueOf()).toBe(7.5)
    })

    it('Morphable with String', () => {
      const morpher = new Morphable().from('foo').to('bar')

      expect(morpher).toEqual(any(Morphable))
      expect(morpher.type()).toBe(NonMorphable)
      expect(morpher.at(0.5)).toEqual(any(NonMorphable))
      expect(morpher.at(0.5).valueOf()).toBe('foo')
      expect(morpher.at(1).valueOf()).toBe('bar')
    })

    it('Morphable with Object', () => {
      const morpher = new Morphable().from({ a: 5, b: 10 }).to({ a: 10, b: 20 })

      expect(morpher).toEqual(any(Morphable))
      expect(morpher.type()).toBe(ObjectBag)
      expect(morpher.at(0.5)).toEqual(any(Object))
      expect(morpher.at(0.5).valueOf()).toEqual(
        objectContaining({ a: new SVGNumber(7.5), b: new SVGNumber(15) })
      )
    })

    it('Morphable from object containing css values', () => {
      const morpher = new Morphable()
        .from({ opacity: '0', 'stroke-width': '10px' })
        .to({ opacity: 1, 'stroke-width': 20 })

      expect(morpher).toEqual(any(Morphable))
      expect(morpher.type()).toBe(ObjectBag)
      expect(morpher.at(0.5)).toEqual(any(Object))
      expect(morpher.at(0.5).valueOf()).toEqual(
        objectContaining({
          opacity: new SVGNumber(0.5),
          'stroke-width': new SVGNumber('15px')
        })
      )
    })

    it('Creates a morphable out of an SVGNumber', () => {
      const morpher = new SVGNumber(5).to(10)

      expect(morpher).toEqual(any(Morphable))
      expect(morpher.type()).toBe(SVGNumber)
      expect(morpher.at(0.5)).toEqual(any(SVGNumber))
      expect(morpher.at(0.5).valueOf()).toBe(7.5)
    })

    it('Creates a morphable out of an Color', () => {
      const morpher = new Color('#fff').to('#000')

      expect(morpher).toEqual(any(Morphable))
      expect(morpher.type()).toBe(Color)
      expect(morpher.at(0.5)).toEqual(any(Color))
      expect(morpher.at(0.5).toHex()).toBe('#808080')
    })

    it('Creates a morphable out of an Box', () => {
      const morpher = new Box(1, 2, 3, 4).to([5, 6, 7, 8])

      expect(morpher).toEqual(any(Morphable))
      expect(morpher.type()).toBe(Box)
      expect(morpher.at(0.5)).toEqual(any(Box))
      expect(morpher.at(0.5)).toEqual(
        objectContaining({ x: 3, y: 4, width: 5, height: 6 })
      )
    })

    it('Creates a morphable out of an Matrix', () => {
      const morpher = new Matrix(1, 2, 3, 4, 5, 6).to([3, 4, 5, 6, 7, 8])

      expect(morpher).toEqual(any(Morphable))
      expect(morpher.type()).toBe(Matrix)
      expect(morpher.at(0.5)).toEqual(any(Matrix))
      expect(morpher.at(0.5)).toEqual(
        objectContaining(new Matrix(2, 3, 4, 5, 6, 7))
      )
    })

    it('Creates a morphable out of an SVGArray', () => {
      const morpher = new SVGArray([1, 2, 3, 4, 5, 6]).to([3, 4, 5, 6, 7, 8])

      expect(morpher).toEqual(any(Morphable))
      expect(morpher.type()).toBe(SVGArray)
      expect(morpher.at(0.5)).toEqual(any(SVGArray))
      expect(morpher.at(0.5).toArray()).toEqual(
        arrayContaining([2, 3, 4, 5, 6, 7])
      )
    })

    it('Creates a morphable out of an PointArray', () => {
      const morpher = new PointArray([1, 2, 3, 4, 5, 6]).to([3, 4, 5, 6, 7, 8])

      expect(morpher).toEqual(any(Morphable))
      expect(morpher.type()).toBe(PointArray)
      expect(morpher.at(0.5)).toEqual(any(PointArray))
      expect(morpher.at(0.5).toArray()).toEqual(
        arrayContaining([2, 3, 4, 5, 6, 7])
      )
    })

    it('Creates a morphable out of an PathArray', () => {
      const morpher = new PathArray(['M', 1, 2, 'L', 3, 4, 'L', 5, 6]).to([
        'M',
        3,
        4,
        'L',
        5,
        6,
        'L',
        7,
        8
      ])

      expect(morpher).toEqual(any(Morphable))
      expect(morpher.type()).toBe(PathArray)
      expect(morpher.at(0.5)).toEqual(any(PathArray))
      expect(morpher.at(0.5).toArray()).toEqual(
        arrayContaining(['M', 2, 3, 'L', 4, 5, 'L', 6, 7])
      )
    })

    it('creates a morphable from unmorphable types', () => {
      const morpher = new Morphable().from('Hallo').to('Welt')

      expect(morpher).toEqual(any(Morphable))
      expect(morpher.type()).toBe(NonMorphable)
      expect(morpher.at(0.5)).toEqual(any(NonMorphable))
      expect(morpher.at(0.5).valueOf()).toBe('Hallo')
      expect(morpher.at(1).valueOf()).toBe('Welt')
    })

    it('Creates a morphable out of an TransformBag', () => {
      const morpher = new TransformBag({ rotate: 0, translateX: 0 }).to({
        rotate: 50,
        translateX: 20
      })

      expect(morpher).toEqual(any(Morphable))
      expect(morpher.type()).toBe(TransformBag)
      expect(morpher.at(0.5)).toEqual(any(TransformBag))

      expect(morpher.at(0.5)).toEqual(
        objectContaining({ rotate: 25, translateX: 10 })
      )
    })

    it('Creates a morphable out of an ObjectBag', () => {
      const morpher = new ObjectBag({ a: 5, b: 10 }).to({ a: 10, b: 20 })

      expect(morpher).toEqual(any(Morphable))
      expect(morpher.type()).toBe(ObjectBag)
      expect(morpher.at(0.5)).toEqual(any(Object))
      expect(morpher.at(0.5).valueOf()).toEqual(
        objectContaining({ a: new SVGNumber(7.5), b: new SVGNumber(15) })
      )
    })

    it('creates a morphable from a color string', () => {
      let morpher = new Morphable().from('#fff').to('#000')

      expect(morpher).toEqual(any(Morphable))
      expect(morpher.type()).toBe(Color)
      expect(morpher.at(0.5)).toEqual(any(Color))
      expect(morpher.at(0.5).toHex()).toBe('#808080')

      morpher = new Morphable().from('rgb(255,255,255)').to('rgb(0,0,0)')

      expect(morpher).toEqual(any(Morphable))
      expect(morpher.type()).toBe(Color)
      expect(morpher.at(0.5)).toEqual(any(Color))
      expect(morpher.at(0.5).toHex()).toBe('#808080')
    })

    it('creates a morphable from path string', () => {
      const morpher = new Morphable().from('M 0 0 L 10 10').to('M 0 0 L 20 20')

      expect(morpher).toEqual(any(Morphable))
      expect(morpher.type()).toBe(PathArray)
      expect(morpher.at(0.5)).toEqual(any(PathArray))
      expect(morpher.at(0.5).toString()).toBe('M0 0L15 15 ')
    })

    it('creates a morphable from number string', () => {
      let morpher = new Morphable().from('10').to('20')

      expect(morpher).toEqual(any(Morphable))
      expect(morpher.type()).toBe(SVGNumber)
      expect(morpher.at(0.5)).toEqual(any(SVGNumber))
      expect(morpher.at(0.5).toString()).toBe('15')

      morpher = new Morphable().from('10px').to('20px')

      expect(morpher).toEqual(any(Morphable))
      expect(morpher.type()).toBe(SVGNumber)
      expect(morpher.at(0.5)).toEqual(any(SVGNumber))
      expect(morpher.at(0.5).toString()).toBe('15px')
    })

    it('creates a morphable from delimited string', () => {
      const morpher = new Morphable().from(' 0 1,  2  , 3  ').to('4,5,6,7')

      expect(morpher).toEqual(any(Morphable))
      expect(morpher.type()).toBe(SVGArray)
      expect(morpher.at(0.5)).toEqual(any(SVGArray))
      expect(morpher.at(0.5)).toEqual([2, 3, 4, 5])
    })

    it('creates a morphable from an array', () => {
      const morpher = new Morphable().from([0, 1, 2, 3]).to([4, 5, 6, 7])

      expect(morpher).toEqual(any(Morphable))
      expect(morpher.type()).toBe(SVGArray)
      expect(morpher.at(0.5)).toEqual(any(SVGArray))
      expect(morpher.at(0.5)).toEqual([2, 3, 4, 5])
    })

    it('converts the to-color to the from-type', () => {
      const morpher = new Color('#fff').to(new Color(1, 2, 3, 'hsl'))
      expect(new Color(morpher.from()).space).toBe('rgb')
      expect(morpher.at(0.5).space).toBe('rgb')
    })

    it('converts the from-color to the to-type', () => {
      const morpher = new Morphable().to(new Color(1, 2, 3, 'hsl')).from('#fff')
      expect(new Color(morpher.from()).space).toBe('hsl')
      expect(morpher.at(0.5).space).toBe('hsl')
    })
  })

  describe('from()', () => {
    it('sets the type of the runner', () => {
      const morpher = new Morphable().from(5)
      expect(morpher.type()).toBe(SVGNumber)
    })

    it('sets the from attribute to an array representation of the morphable type', () => {
      const morpher = new Morphable().from(5)
      expect(morpher.from()).toEqual(arrayContaining([5]))
    })
  })

  describe('type()', () => {
    it('sets the type of the runner', () => {
      const morpher = new Morphable().type(SVGNumber)
      expect(morpher._type).toBe(SVGNumber)
    })

    it('gets the type of the runner', () => {
      const morpher = new Morphable().type(SVGNumber)
      expect(morpher.type()).toBe(SVGNumber)
    })
  })

  describe('to()', () => {
    it('sets the type of the runner', () => {
      const morpher = new Morphable().to(5)
      expect(morpher.type()).toBe(SVGNumber)
    })

    it('sets the from attribute to an array representation of the morphable type', () => {
      const morpher = new Morphable().to(5)
      expect(morpher.to()).toEqual(arrayContaining([5]))
    })
  })

  describe('stepper()', () => {
    it('sets and gets the stepper of the Morphable', () => {
      const stepper = new Stepper()
      const morpher = new Morphable().stepper(stepper)
      expect(morpher.stepper()).toBe(stepper)
    })
  })

  describe('NonMorphable', () => {
    describe('()', () => {
      it('wraps any type into a NonMorphable from an array', () => {
        const non = new NonMorphable([5])
        expect(non.valueOf()).toBe(5)
      })

      it('wraps any type into a NonMorphable from any type', () => {
        expect(new NonMorphable(5).valueOf()).toBe(5)
        expect(new NonMorphable('Hello').valueOf()).toBe('Hello')
      })
    })

    describe('toArray()', () => {
      it('returns array representation of NonMorphable', () => {
        expect(new NonMorphable(5).toArray()).toEqual([5])
        expect(new NonMorphable('Hello').toArray()).toEqual(['Hello'])
      })
    })
  })

  describe('TransformBag', () => {
    describe('()', () => {
      it('creates an object which holds transformations for morphing by passing array', () => {
        const bag = new TransformBag([0, 1, 2, 3, 4, 5, 6, 7])
        expect(bag.toArray()).toEqual([0, 1, 2, 3, 4, 5, 6, 7])
      })

      it('creates an object which holds transformations for morphing by passing object', () => {
        const bag = new TransformBag({
          scaleX: 0,
          scaleY: 1,
          shear: 2,
          rotate: 3,
          translateX: 4,
          translateY: 5,
          originX: 6,
          originY: 7
        })

        expect(bag.toArray()).toEqual([0, 1, 2, 3, 4, 5, 6, 7])
      })
    })

    describe('toArray()', () => {
      it('creates an array out of the transform values', () => {
        const bag = new TransformBag([0, 1, 2, 3, 4, 5, 6, 7])
        expect(bag.toArray()).toEqual([0, 1, 2, 3, 4, 5, 6, 7])
      })
    })
  })

  describe('ObjectBag', () => {
    describe('()', () => {
      it('wraps an object into a morphable object by passing an array', () => {
        const bag = new ObjectBag([
          'foo',
          SVGNumber,
          2,
          1,
          '',
          'bar',
          SVGNumber,
          2,
          2,
          '',
          'baz',
          SVGNumber,
          2,
          3,
          ''
        ])
        expect(bag.values).toEqual([
          'foo',
          SVGNumber,
          2,
          1,
          '',
          'bar',
          SVGNumber,
          2,
          2,
          '',
          'baz',
          SVGNumber,
          2,
          3,
          ''
        ])
      })

      it('wraps an object into a morphable object by passing an object', () => {
        const bag = new ObjectBag({ foo: 1, bar: 2, baz: 3 })
        expect(bag.values).toEqual([
          'bar',
          SVGNumber,
          2,
          2,
          '',
          'baz',
          SVGNumber,
          2,
          3,
          '',
          'foo',
          SVGNumber,
          2,
          1,
          ''
        ])
      })

      it('wraps an object with morphable values in an ObjectBag', () => {
        const bag = new ObjectBag({ fill: new Color(), bar: 2 })
        expect(bag.values).toEqual([
          'bar',
          SVGNumber,
          2,
          2,
          '',
          'fill',
          Color,
          5,
          0,
          0,
          0,
          0,
          'rgb'
        ])
      })

      it('wraps an array with morphable representation in an ObjectBag', () => {
        const bag = new ObjectBag([
          'bar',
          SVGNumber,
          2,
          2,
          '',
          'fill',
          Color,
          5,
          0,
          0,
          0,
          0,
          'rgb'
        ])
        expect(bag.toArray()).toEqual([
          'bar',
          SVGNumber,
          2,
          2,
          '',
          'fill',
          Color,
          5,
          0,
          0,
          0,
          0,
          'rgb'
        ])
      })
    })

    describe('toArray()', () => {
      it('creates an array out of the object', () => {
        const bag = new ObjectBag({ foo: 1, bar: 2, baz: 3 })
        expect(bag.toArray()).toEqual([
          'bar',
          SVGNumber,
          2,
          2,
          '',
          'baz',
          SVGNumber,
          2,
          3,
          '',
          'foo',
          SVGNumber,
          2,
          1,
          ''
        ])
      })

      it('creates a flattened array out of the object with morphable values', () => {
        const bag = new ObjectBag({ fill: new Color(), bar: 2 })
        expect(bag.toArray()).toEqual([
          'bar',
          SVGNumber,
          2,
          2,
          '',
          'fill',
          Color,
          5,
          0,
          0,
          0,
          0,
          'rgb'
        ])
      })
    })

    describe('valueOf()', () => {
      it('creates morphable objects from the stored values', () => {
        const bag = new ObjectBag({ foo: 1, bar: 2, baz: 3 })
        expect(bag.valueOf()).toEqual({
          foo: new SVGNumber(1),
          bar: new SVGNumber(2),
          baz: new SVGNumber(3)
        })
      })

      it('creates also morphable objects from the stored values', () => {
        const bag = new ObjectBag({ fill: new Color(), bar: 2 })
        expect(bag.valueOf()).toEqual({
          fill: objectContaining(new Color()),
          bar: new SVGNumber(2)
        })
      })
    })

    describe('align()', () => {
      it('aligns color spaces between two object bags', () => {
        const bag1 = new ObjectBag({ x: 1, y: '#fff' })
        const bag2 = new ObjectBag({ x: 2, y: new Color().hsl() })
        bag1.align(bag2.toArray())
        expect(bag1.toArray()).toEqual([
          'x',
          SVGNumber,
          2,
          1,
          '',
          'y',
          Color,
          5,
          0,
          0,
          100,
          0,
          'hsl'
        ])
      })
    })
  })
})


================================================
FILE: spec/spec/animation/Queue.js
================================================
/* globals describe, expect, it */

import { Queue } from '../../../src/main.js'

describe('Queue.js', function () {
  describe('first ()', function () {
    it('returns null if no item in the queue', function () {
      var queue = new Queue()
      expect(queue.first()).toEqual(null)
    })

    it('returns the first value in the queue', function () {
      var queue = new Queue()
      queue.push(1)
      expect(queue.first()).toBe(1)
      queue.push(2)
      expect(queue.first()).toBe(1)
    })
  })

  describe('last ()', function () {
    it('returns null if no item in the queue', function () {
      var queue = new Queue()
      expect(queue.last()).toEqual(null)
    })

    it('returns the last value added', function () {
      var queue = new Queue()
      queue.push(1)
      expect(queue.last()).toBe(1)
      queue.push(2)
      expect(queue.last()).toBe(2)
    })
  })

  describe('push ()', function () {
    it('adds an element to the end of the queue', function () {
      var queue = new Queue()
      queue.push(1)
      queue.push(2)
      queue.push(3)

      expect(queue.first()).toBe(1)
      expect(queue.last()).toBe(3)
    })

    it('adds an item to the end of the queue', function () {
      var queue = new Queue()
      queue.push(1)
      const item = queue.push(2)
      queue.push(3)
      queue.remove(item)
      queue.push(item)

      expect(queue.first()).toBe(1)
      expect(queue.last()).toBe(2)
    })
  })

  describe('remove ()', function () {
    it('removes the given item from the queue', function () {
      var queue = new Queue()
      queue.push(1)
      queue.push(2)
      var item = queue.push(3)

      queue.remove(item)

      expect(queue.last()).toBe(2)
      expect(queue.first()).toBe(1)
    })

    it('removes the given item from the queue', function () {
      var queue = new Queue()
      var item = queue.push(1)
      queue.push(2)
      queue.push(3)

      queue.remove(item)

      expect(queue.last()).toBe(3)
      expect(queue.first()).toBe(2)
    })
  })

  describe('shift ()', function () {
    it('returns nothing if queue is empty', function () {
      var queue = new Queue()
      var val = queue.shift()
      expect(val).toBeFalsy()
    })

    it('returns the first item of the queue and removes it', function () {
      var queue = new Queue()
      queue.push(1)
      queue.push(2)
      queue.push(3)

      var val = queue.shift()

      expect(queue.last()).toBe(3)
      expect(queue.first()).toBe(2)

      expect(val).toBe(1)
    })
  })
})


================================================
FILE: spec/spec/animation/Runner.js
================================================
/* globals describe, expect, it, beforeEach, afterEach, spyOn, jasmine */

import {
  Runner,
  defaults,
  Ease,
  Controller,
  SVG,
  Timeline,
  Rect,
  Morphable,
  Animator,
  Queue,
  Matrix,
  Color,
  Box,
  Polygon,
  PointArray
} from '../../../src/main.js'
import { FakeRunner, RunnerArray } from '../../../src/animation/Runner.js'
import { getWindow } from '../../../src/utils/window.js'
import SVGNumber from '../../../src/types/SVGNumber.js'

const { any, createSpy, objectContaining, arrayContaining } = jasmine

describe('Runner.js', () => {
  describe('Runner', () => {
    var initFn = createSpy('initFn')
    var runFn = createSpy('runFn')

    beforeEach(() => {
      jasmine.RequestAnimationFrame.install(getWindow())
      Animator.timeouts = new Queue()
      Animator.frames = new Queue()
      Animator.immediates = new Queue()
      Animator.nextDraw = null
      initFn.calls.reset()
      runFn.calls.reset()
    })

    afterEach(() => {
      jasmine.RequestAnimationFrame.uninstall(getWindow())
    })

    describe('sanitise()', () => {
      it('can handle all form of input', () => {
        var fn = Runner.sanitise

        expect(fn(200, 200, 'now')).toEqual(
          objectContaining({
            duration: 200,
            delay: 200,
            when: 'now',
            times: 1,
            wait: 0,
            swing: false
          })
        )

        expect(fn(200, 200)).toEqual(
          objectContaining({
            duration: 200,
            delay: 200,
            when: 'last',
            times: 1,
            wait: 0,
            swing: false
          })
        )

        expect(fn(200)).toEqual(
          objectContaining({
            duration: 200,
            delay: defaults.timeline.delay,
            when: 'last',
            times: 1,
            wait: 0,
            swing: false
          })
        )

        expect(fn(runFn)).toEqual(
          objectContaining({
            duration: runFn,
            delay: defaults.timeline.delay,
            when: 'last',
            times: 1,
            wait: 0,
            swing: false
          })
        )

        expect(fn({ delay: 200 })).toEqual(
          objectContaining({
            duration: defaults.timeline.duration,
            delay: 200,
            when: 'last',
            times: 1,
            wait: 0,
            swing: false
          })
        )

        expect(
          fn({ times: 3, delay: 200, when: 'now', swing: true, wait: 200 })
        ).toEqual(
          objectContaining({
            duration: defaults.timeline.duration,
            delay: 200,
            when: 'now',
            times: 3,
            wait: 200,
            swing: true
          })
        )
      })
    })

    describe('())', () => {
      it('creates a runner with defaults', () => {
        var runner = new Runner()
        expect(runner instanceof Runner).toBe(true)
        expect(runner._duration).toBe(defaults.timeline.duration)
        expect(runner._stepper instanceof Ease).toBe(true)
      })

      it('creates a runner with duration set', () => {
        var runner = new Runner(1000)
        expect(runner instanceof Runner).toBe(true)
        expect(runner._duration).toBe(1000)
        expect(runner._stepper instanceof Ease).toBe(true)
      })

      it('creates a runner with controller set', () => {
        var runner = new Runner(runFn)
        expect(runner instanceof Runner).toBe(true)
        expect(runner._duration).toBeFalsy()
        expect(runner._stepper instanceof Controller).toBe(true)
      })
    })

    describe('queue()', () => {
      it('adds another closure to the runner', () => {
        var runner = new Runner()
        runner.queue(initFn, runFn, true)

        expect(runner._queue[0]).toEqual(
          objectContaining({
            initialiser: initFn,
            initialised: false,
            runner: runFn,
            finished: false
          })
        )
      })
    })

    describe('step()', () => {
      it('returns itself', () => {
        var runner = new Runner()
        expect(runner.step()).toBe(runner)
      })

      it('does nothing when not active', () => {
        const runner = new Runner().active(false)
        const frozen = Object.freeze(runner)
        expect(frozen.step()).toEqual(runner)
      })

      it('calls initFn once and runFn at every step', () => {
        var runner = new Runner()
        runner.queue(initFn, runFn, false)

        runner.step()
        expect(initFn).toHaveBeenCalled()
        expect(runFn).toHaveBeenCalled()

        runner.step()
        expect(initFn.calls.count()).toBe(1)
        expect(runFn.calls.count()).toBe(2)
      })

      it('calls initFn on every step if its declarative', () => {
        var runner = new Runner(new Controller())
        runner.queue(initFn, runFn, true)

        runner.step()
        expect(initFn).toHaveBeenCalled()
        expect(runFn).toHaveBeenCalled()

        runner.step()
        expect(initFn.calls.count()).toBe(2)
        expect(runFn.calls.count()).toBe(2)
      })

      function getLoop(r) {
        var loopDuration = r._duration + r._wait
        var loopsDone = Math.floor(r._time / loopDuration)
        return loopsDone
      }

      // step in time
      it('steps forward a certain time', () => {
        var spy = createSpy('stepper')
        var r = new Runner(1000).loop(10, false, 100)
        r.queue(null, spy)

        r.step(300) // should be 0.3s
        expect(spy).toHaveBeenCalledWith(0.3)
        expect(getLoop(r)).toBe(0)

        r.step(300) // should be 0.6s
        expect(spy).toHaveBeenCalledWith(0.6)
        expect(getLoop(r)).toBe(0)

        r.step(600) // should be 0.1s
        expect(spy).toHaveBeenCalledWith(0.1)
        expect(getLoop(r)).toBe(1)

        r.step(-300) // should be 0.9s
        expect(spy).toHaveBeenCalledWith(0.9)
        expect(getLoop(r)).toBe(0)

        r.step(2000) // should be 0.7s
        expect(spy).toHaveBeenCalledWith(0.7)
        expect(getLoop(r)).toBe(2)

        r.step(-2000) // should be 0.9s
        expect(spy).toHaveBeenCalledWith(0.9)
        expect(getLoop(r)).toBe(0)
      })

      it('handles dts which are bigger than the animation time', () => {
        var runner = new Runner(1000)
        runner.queue(initFn, runFn, true)

        runner.step(1100)
        expect(initFn).toHaveBeenCalled()
        expect(runFn).toHaveBeenCalledWith(1)
      })

      describe('looping', () => {
        describe('without wait', () => {
          describe('unreversed', () => {
            describe('nonswinging', () => {
              it('does behave correctly at the end of an even loop', () => {
                var spy = createSpy('stepper')
                var runner = new Runner(1000).loop(6, false)
                runner.queue(null, spy)

                runner.step(5750)
                expect(spy).toHaveBeenCalledWith(0.75)
                runner.step(250)
                expect(spy).toHaveBeenCalledWith(1)
              })

              it('does behave correctly at the end of an uneven loop', () => {
                var spy = createSpy('stepper')
                var runner = new Runner(1000).loop(5, false)
                runner.queue(null, spy)

                runner.step(4750)
                expect(spy).toHaveBeenCalledWith(0.75)
                runner.step(250)
                expect(spy).toHaveBeenCalledWith(1)
              })
            })

            describe('swinging', () => {
              it('does behave correctly at the end of an even loop', () => {
                var spy = createSpy('stepper')
                var runner = new Runner(1000).loop(6, true)
                runner.queue(null, spy)

                runner.step(5750)
                expect(spy).toHaveBeenCalledWith(0.25)
                runner.step(250)
                expect(spy).toHaveBeenCalledWith(0)
              })

              it('does behave correctly at the end of an uneven loop', () => {
                var spy = createSpy('stepper')
                var runner = new Runner(1000).loop(5, true)
                runner.queue(null, spy)

                runner.step(4750)
                expect(spy).toHaveBeenCalledWith(0.75)
                runner.step(250)
                expect(spy).toHaveBeenCalledWith(1)
              })
            })
          })

          describe('reversed', () => {
            describe('nonswinging', () => {
              it('does behave correctly at the end of an even loop', () => {
                var spy = createSpy('stepper')
                var runner = new Runner(1000).loop(6, false).reverse()
                runner.queue(null, spy)

                runner.step(5750)
                expect(spy).toHaveBeenCalledWith(0.25)
                runner.step(250)
                expect(spy).toHaveBeenCalledWith(0)
              })

              it('does behave correctly at the end of an uneven loop', () => {
                var spy = createSpy('stepper')
                var runner = new Runner(1000).loop(5, false).reverse()
                runner.queue(null, spy)

                runner.step(4750)
                expect(spy).toHaveBeenCalledWith(0.25)
                runner.step(250)
                expect(spy).toHaveBeenCalledWith(0)
              })
            })

            describe('swinging', () => {
              it('does behave correctly at the end of an even loop', () => {
                var spy = createSpy('stepper')
                var runner = new Runner(1000).loop(6, true).reverse()
                runner.queue(null, spy)

                runner.step(5750)
                expect(spy).toHaveBeenCalledWith(0.75)
                runner.step(250)
                expect(spy).toHaveBeenCalledWith(1)
              })

              it('does behave correctly at the end of an uneven loop', () => {
                var spy = createSpy('stepper')
                var runner = new Runner(1000).loop(5, true).reverse()
                runner.queue(null, spy)

                runner.step(4750)
                expect(spy).toHaveBeenCalledWith(0.25)
                runner.step(250)
                expect(spy).toHaveBeenCalledWith(0)
              })
            })
          })
        })

        describe('with wait', () => {
          describe('unreversed', () => {
            describe('nonswinging', () => {
              it('does behave correctly at the end of an even loop', () => {
                var spy = createSpy('stepper')
                var runner = new Runner(1000).loop(6, false, 100)
                runner.queue(null, spy)

                runner.step(5450)
                expect(spy).toHaveBeenCalledWith(1)
                spy.calls.reset()

                runner.step(800)
                expect(spy).toHaveBeenCalledWith(0.75)
                runner.step(250)
                expect(spy).toHaveBeenCalledWith(1)
              })

              it('does behave correctly at the end of an uneven loop', () => {
                var spy = createSpy('stepper')
                var runner = new Runner(1000).loop(5, false, 100)
                runner.queue(null, spy)

                runner.step(4350)
                expect(spy).toHaveBeenCalledWith(1)
                spy.calls.reset()

                runner.step(800)
                expect(spy).toHaveBeenCalledWith(0.75)
                runner.step(250)
                expect(spy).toHaveBeenCalledWith(1)
              })
            })

            describe('swinging', () => {
              it('does behave correctly at the end of an even loop', () => {
                var spy = createSpy('stepper')
                var runner = new Runner(1000).loop(6, true, 100)
                runner.queue(null, spy)

                runner.step(5450)
                expect(spy).toHaveBeenCalledWith(1)
                spy.calls.reset()

                runner.step(800)
                expect(spy).toHaveBeenCalledWith(0.25)
                runner.step(250)
                expect(spy).toHaveBeenCalledWith(0)
              })

              it('does behave correctly at the end of an uneven loop', () => {
                var spy = createSpy('stepper')
                var runner = new Runner(1000).loop(5, true, 100)
                runner.queue(null, spy)

                runner.step(4350)
                expect(spy).toHaveBeenCalledWith(0)
                spy.calls.reset()

                runner.step(800)
                expect(spy).toHaveBeenCalledWith(0.75)

                runner.step(250)
                expect(spy).toHaveBeenCalledWith(1)
              })
            })
          })

          describe('reversed', () => {
            describe('nonswinging', () => {
              it('does behave correctly at the end of an even loop', () => {
                var spy = createSpy('stepper')
                var runner = new Runner(1000).loop(6, false, 100).reverse()
                runner.queue(null, spy)

                runner.step(5450)
                expect(spy).toHaveBeenCalledWith(0)
                spy.calls.reset()

                runner.step(800)
                expect(spy).toHaveBeenCalledWith(0.25)
                runner.step(250)
                expect(spy).toHaveBeenCalledWith(0)
              })

              it('does behave correctly at the end of an uneven loop', () => {
                var spy = createSpy('stepper')
                var runner = new Runner(1000).loop(5, false, 100).reverse()
                runner.queue(null, spy)

                runner.step(4350)
                expect(spy).toHaveBeenCalledWith(0)
                spy.calls.reset()

                runner.step(800)
                expect(spy).toHaveBeenCalledWith(0.25)
                runner.step(250)
                expect(spy).toHaveBeenCalledWith(0)
              })
            })

            describe('swinging', () => {
              it('does behave correctly at the end of an even loop', () => {
                var spy = createSpy('stepper')
                var runner = new Runner(1000).loop(6, true, 100).reverse()
                runner.queue(null, spy)

                runner.step(5450)
                expect(spy).toHaveBeenCalledWith(0)
                spy.calls.reset()

                runner.step(800)
                expect(spy).toHaveBeenCalledWith(0.75)
                runner.step(250)
                expect(spy).toHaveBeenCalledWith(1)
              })

              it('does behave correctly at the end of an uneven loop', () => {
                var spy = createSpy('stepper')
                var runner = new Runner(1000).loop(5, true, 100).reverse()
                runner.queue(null, spy)

                runner.step(4350)
                expect(spy).toHaveBeenCalledWith(1)
                spy.calls.reset()

                runner.step(800)
                expect(spy).toHaveBeenCalledWith(0.25)
                runner.step(250)
                expect(spy).toHaveBeenCalledWith(0)
              })
            })
          })
        })
      })
    })

    describe('active()', () => {
      it('acts as a getter without parameters', () => {
        var runner = new Runner()
        expect(runner.active()).toBe(true)
      })

      it('disables the runner when false is passed', () => {
        var runner = new Runner()
        expect(runner.active(false)).toBe(runner)
        expect(runner.active()).toBe(false)
      })

      it('enables the runner when true is passed', () => {
        var runner = new Runner()
        expect(runner.active(false)).toBe(runner)
        expect(runner.active(true)).toBe(runner)
        expect(runner.active()).toBe(true)
      })
    })

    describe('duration()', () => {
      it('return the full duration of the runner including all loops and waits', () => {
        var runner = new Runner(800).loop(10, true, 200)
        expect(runner.duration()).toBe(9800)
      })
    })

    describe('loop()', () => {
      it('makes this runner looping', () => {
        var runner = new Runner(1000).loop(5)
        expect(runner.duration()).toBe(5000)
      })

      it('makes this runner indefinitey by passing true', () => {
        var runner = new Runner(1000).loop(true)
        expect(runner.duration()).toBe(Infinity)
      })

      it('makes this runner indefinitey by passing nothing', () => {
        var runner = new Runner(1000).loop()
        expect(runner.duration()).toBe(Infinity)
      })
    })

    describe('time()', () => {
      it('returns itself', () => {
        var runner = new Runner()
        expect(runner.time(0)).toBe(runner)
      })

      it('acts as a getter with no parameter passed', () => {
        var runner = new Runner()
        expect(runner.time()).toBe(0)
      })

      it('reschedules the runner to a new time', () => {
        var runner = new Runner()
        runner.time(10)

        expect(runner.time()).toBe(10)
      })

      it('calls step to reschedule', () => {
        var runner = new Runner()
        spyOn(runner, 'step')
        runner.time(10)

        expect(runner.step).toHaveBeenCalledWith(10)
      })
    })

    describe('loops()', () => {
      it('get the loops of a runner', () => {
        var spy = createSpy('stepper')
        var runner = new Runner(1000).queue(null, spy)

        runner.step(300)
        expect(spy).toHaveBeenCalledWith(0.3)

        expect(runner.loops()).toBe(0.3)
      })
      it('sets the loops of the runner', () => {
        var spy = createSpy('stepper')
        var runner = new Runner(1000).queue(null, spy)

        expect(runner.loops(0.5).loops()).toBe(0.5)
        expect(spy).toHaveBeenCalledWith(0.5)

        expect(runner.loops(0.1).loops()).toBe(0.1)
        expect(spy).toHaveBeenCalledWith(0.1)

        expect(runner.loops(1.5).loops()).toBe(1)
        expect(spy).toHaveBeenCalledWith(1)
      })
      it('sets the loops of the runner in a loop', () => {
        var spy = createSpy('stepper')
        var runner = new Runner(1000).loop(5, true, 500).queue(null, spy)

        expect(runner.loops(1.3).loops()).toBe(1.3)
        expect(spy).toHaveBeenCalledWith(0.7)

        expect(runner.loops(0.3).loops()).toBe(0.3)
      })
    })

    describe('progress()', () => {
      it('gets the progress of a runner', () => {
        var spy = createSpy('stepper')
        var runner = new Runner(1000).queue(null, spy)

        runner.step(300)
        expect(spy).toHaveBeenCalledWith(0.3)

        expect(runner.progress()).toBe(0.3)
      })

      it('gets the progress of a runner when looping', () => {
        var spy = createSpy('stepper')
        var runner = new Runner(800).queue(null, spy).loop(10, false, 200) // duration should be 9800

        // middle of animation, in the middle of wait time
        runner.step(4900)
        expect(runner.progress()).toBe(0.5)
        expect(spy).toHaveBeenCalledWith(1)

        // start of next loop
        runner.step(100)
        expect(spy).toHaveBeenCalledWith(0)

        // move 400 into current loop which is 0.5 progress
        // the progress value is 5400 / 9800
        runner.step(400)
        expect(spy).toHaveBeenCalledWith(0.5)
        expect(runner.progress()).toBe(5400 / 9800)
      })

      it('sets the progress of a runner', () => {
        var spy = createSpy('stepper')
        var runner = new Runner(1000).queue(null, spy)

        expect(runner.progress(0.5).progress()).toBe(0.5)
        expect(spy).toHaveBeenCalledWith(0.5)
      })

      it('sets the progress of a runner when looping', () => {
        var spy = createSpy('stepper')
        var runner = new Runner(800).queue(null, spy).loop(10, false, 200)

        // progress 0.5 somewhere in the middle of wait time
        expect(runner.progress(0.5).progress()).toBe(0.5)
        expect(spy).toHaveBeenCalledWith(1)

        // start of next loop
        runner.step(100)
        expect(spy).toHaveBeenCalledWith(0)

        // should move 0.5 into the next loop
        expect(runner.progress(5400 / 9800).progress()).toBe(5400 / 9800)
        expect(spy.calls.mostRecent().args[0]).toBeCloseTo(0.5)
      })
    })

    describe('position()', () => {
      it('gets the position of a runner', () => {
        var spy = createSpy('stepper')
        var runner = new Runner(1000).queue(null, spy)

        runner.step(300)
        expect(spy).toHaveBeenCalledWith(0.3)

        expect(runner.position()).toBe(0.3)
      })

      it('gets the position of a runner when looping', () => {
        var spy = createSpy('stepper')
        var runner = new Runner(1000).loop(5, true, 100).queue(null, spy)

        runner.step(1200)
        expect(spy).toHaveBeenCalledWith(0.9)

        expect(runner.position()).toBe(0.9)
      })

      it('sets the position of a runner', () => {
        var spy = createSpy('stepper')
        var runner = new Runner(1000).queue(null, spy)

        expect(runner.position(0.5).position()).toBe(0.5)
        expect(spy).toHaveBeenCalledWith(0.5)
      })

      it('sets the position of a runner in a loop', () => {
        var spy = createSpy('stepper')
        var runner = new Runner(1000).loop(5, true, 100).queue(null, spy)

        runner.step(1200)
        expect(runner.position(0.4).position()).toBe(0.4)
        expect(spy).toHaveBeenCalledWith(0.4)

        expect(runner.position(0).position()).toBe(0)
        expect(spy).toHaveBeenCalledWith(0)

        expect(runner.position(1).position()).toBe(1)
        expect(spy).toHaveBeenCalledWith(1)
      })
    })

    describe('element()', () => {
      it('returns the element bound to this runner if any', () => {
        var runner1 = new Runner()
        expect(runner1.element()).toBe(null)

        var element = SVG('<rect />')
        var runner2 = element.animate()
        expect(runner2.element()).toBe(element)
      })

      it('sets an element to be bound to the runner', () => {
        var runner = new Runner()
        var element = SVG('<rect />')
        expect(runner.element(element)).toBe(runner)
        expect(runner.element()).toBe(element)
      })
    })

    describe('timeline()', () => {
      it('returns the timeline bound to this runner if any', () => {
        var runner1 = new Runner()
        expect(runner1.element()).toBe(null)

        var element = SVG('<rect />')
        var runner2 = element.animate()
        expect(runner2.timeline()).toBe(element.timeline())
      })

      it('sets a timeline to be bound to the runner', () => {
        var runner = new Runner()
        var timeline = new Timeline()
        expect(runner.timeline(timeline)).toBe(runner)
        expect(runner.timeline()).toBe(timeline)
      })
    })

    describe('schedule()', () => {
      it('schedules the runner on a timeline', () => {
        var runner = new Runner()
        var timeline = new Timeline()
        var spy = spyOn(timeline, 'schedule').and.callThrough()

        expect(runner.schedule(timeline, 200, 'now')).toBe(runner)
        expect(runner.timeline()).toBe(timeline)
        expect(spy).toHaveBeenCalledWith(runner, 200, 'now')
      })

      it('schedules the runner on its own timeline', () => {
        var runner = new Runner()
        var timeline = new Timeline()
        var spy = spyOn(timeline, 'schedule')
        runner.timeline(timeline)

        expect(runner.schedule(200, 'now')).toBe(runner)
        expect(runner.timeline()).toBe(timeline)
        expect(spy).toHaveBeenCalledWith(runner, 200, 'now')
      })

      it('throws if no timeline is given', () => {
        var runner = new Runner()
        expect(() => runner.schedule(200, 'now')).toThrowError(
          'Runner cannot be scheduled without timeline'
        )
      })
    })

    describe('unschedule()', () => {
      it('unschedules this runner from its timeline', () => {
        var runner = new Runner()
        var timeline = new Timeline()
        var spy = spyOn(timeline, 'unschedule').and.callThrough()

        expect(runner.schedule(timeline, 200, 'now')).toBe(runner)
        expect(runner.unschedule()).toBe(runner)
        expect(spy).toHaveBeenCalledWith(runner)
        expect(runner.timeline()).toBe(null)
      })
    })

    describe('animate()', () => {
      it('creates a new runner scheduled after the first', () => {
        var runner = new Runner(1000)
        var timeline = new Timeline()

        runner.schedule(timeline)

        var runner2 = runner.animate(500, 1000)

        var t = timeline.time()

        expect(runner2.timeline()).toBe(timeline)
        expect(runner2.time()).toBe(0)

        expect(timeline.schedule()).toEqual(
          arrayContaining([
            objectContaining({
              start: t,
              duration: 1000,
        
Download .txt
gitextract_lqipgjf4/

├── .config/
│   ├── karma.conf.cjs
│   ├── karma.conf.common.cjs
│   ├── karma.conf.saucelabs.cjs
│   ├── polyfillListIE.js
│   ├── pretest.js
│   ├── rollup.config.js
│   ├── rollup.polyfills.js
│   └── rollup.tests.js
├── .eslintrc.json
├── .github/
│   ├── CONTRIBUTING.md
│   ├── FUNDING.yml
│   └── ISSUE_TEMPLATE/
│       ├── bug-report.md
│       ├── feature-request.md
│       └── other.md
├── .gitignore
├── .prettierignore
├── .prettierrc.json
├── .travis.yml
├── CHANGELOG.md
├── LICENSE.txt
├── README.md
├── bench/
│   ├── runner.html
│   ├── svg.bench.js
│   └── tests/
│       ├── 10000-accesses.js
│       ├── 10000-boxes.js
│       ├── 10000-circles.js
│       ├── 10000-each.js
│       ├── 10000-pathArray-bbox.js
│       ├── 10000-pathArrays.js
│       ├── 10000-paths.js
│       ├── 10000-pointArray-bbox.js
│       ├── 10000-rects.js
│       ├── 10000-textContent.js
│       └── 10000-transform.js
├── package.json
├── playgrounds/
│   ├── colors/
│   │   ├── main.js
│   │   └── style.css
│   ├── matrix/
│   │   ├── drag.js
│   │   ├── matrix.js
│   │   └── style.css
│   ├── transforms/
│   │   ├── style.css
│   │   └── transforms.js
│   └── webpack.config.js
├── spec/
│   ├── RAFPlugin.js
│   ├── SpecRunner.html
│   ├── SpecRunnerEs6.html
│   ├── checkForAllTests.js
│   ├── fixtures/
│   │   └── fixture.css
│   ├── helpers.js
│   ├── runSVGDomTest.js
│   ├── setupBrowser.js
│   ├── setupSVGDom.js
│   └── spec/
│       ├── animation/
│       │   ├── Animator.js
│       │   ├── Controller.js
│       │   ├── Morphable.js
│       │   ├── Queue.js
│       │   ├── Runner.js
│       │   └── Timeline.js
│       ├── elements/
│       │   ├── A.js
│       │   ├── Circle.js
│       │   ├── ClipPath.js
│       │   ├── Container.js
│       │   ├── Defs.js
│       │   ├── Dom.js
│       │   ├── Element.js
│       │   ├── Ellipse.js
│       │   ├── ForeignObject.js
│       │   ├── Fragment.js
│       │   ├── G.js
│       │   ├── Gradient.js
│       │   ├── Image.js
│       │   ├── Line.js
│       │   ├── Marker.js
│       │   ├── Mask.js
│       │   ├── Path.js
│       │   ├── Pattern.js
│       │   ├── Polygon.js
│       │   ├── Polyline.js
│       │   ├── Rect.js
│       │   ├── Shape.js
│       │   ├── Stop.js
│       │   ├── Style.js
│       │   ├── Svg.js
│       │   ├── Symbol.js
│       │   ├── Text.js
│       │   ├── TextPath.js
│       │   ├── Tspan.js
│       │   └── Use.js
│       ├── modules/
│       │   ├── core/
│       │   │   ├── attr.js
│       │   │   ├── circled.js
│       │   │   ├── containerGeometry.js
│       │   │   ├── event.js
│       │   │   ├── gradiented.js
│       │   │   ├── parser.js
│       │   │   ├── pointed.js
│       │   │   ├── poly.js
│       │   │   ├── regex.js
│       │   │   ├── selector.js
│       │   │   └── textable.js
│       │   └── optional/
│       │       ├── arrange.js
│       │       ├── class.js
│       │       ├── css.js
│       │       ├── data.js
│       │       ├── memory.js
│       │       ├── sugar.js
│       │       └── transform.js
│       ├── types/
│       │   ├── Base.js
│       │   ├── Box.js
│       │   ├── Color.js
│       │   ├── EventTarget.js
│       │   ├── List.js
│       │   ├── Matrix.js
│       │   ├── PathArray.js
│       │   ├── Point.js
│       │   ├── PointArray.js
│       │   ├── SVGArray.js
│       │   └── SVGNumber.js
│       └── utils/
│           ├── adopter.js
│           ├── methods.js
│           ├── pathParser.js
│           ├── utils.js
│           └── window.js
├── src/
│   ├── animation/
│   │   ├── Animator.js
│   │   ├── Controller.js
│   │   ├── Morphable.js
│   │   ├── Queue.js
│   │   ├── Runner.js
│   │   └── Timeline.js
│   ├── elements/
│   │   ├── A.js
│   │   ├── Circle.js
│   │   ├── ClipPath.js
│   │   ├── Container.js
│   │   ├── Defs.js
│   │   ├── Dom.js
│   │   ├── Element.js
│   │   ├── Ellipse.js
│   │   ├── ForeignObject.js
│   │   ├── Fragment.js
│   │   ├── G.js
│   │   ├── Gradient.js
│   │   ├── Image.js
│   │   ├── Line.js
│   │   ├── Marker.js
│   │   ├── Mask.js
│   │   ├── Path.js
│   │   ├── Pattern.js
│   │   ├── Polygon.js
│   │   ├── Polyline.js
│   │   ├── Rect.js
│   │   ├── Shape.js
│   │   ├── Stop.js
│   │   ├── Style.js
│   │   ├── Svg.js
│   │   ├── Symbol.js
│   │   ├── Text.js
│   │   ├── TextPath.js
│   │   ├── Tspan.js
│   │   └── Use.js
│   ├── main.js
│   ├── modules/
│   │   ├── core/
│   │   │   ├── attr.js
│   │   │   ├── circled.js
│   │   │   ├── containerGeometry.js
│   │   │   ├── defaults.js
│   │   │   ├── event.js
│   │   │   ├── gradiented.js
│   │   │   ├── namespaces.js
│   │   │   ├── parser.js
│   │   │   ├── pointed.js
│   │   │   ├── poly.js
│   │   │   ├── regex.js
│   │   │   ├── selector.js
│   │   │   └── textable.js
│   │   └── optional/
│   │       ├── arrange.js
│   │       ├── class.js
│   │       ├── css.js
│   │       ├── data.js
│   │       ├── memory.js
│   │       ├── sugar.js
│   │       └── transform.js
│   ├── polyfills/
│   │   ├── children.js
│   │   └── innerHTML.js
│   ├── svg.js
│   ├── types/
│   │   ├── Base.js
│   │   ├── Box.js
│   │   ├── Color.js
│   │   ├── EventTarget.js
│   │   ├── List.js
│   │   ├── Matrix.js
│   │   ├── PathArray.js
│   │   ├── Point.js
│   │   ├── PointArray.js
│   │   ├── SVGArray.js
│   │   └── SVGNumber.js
│   └── utils/
│       ├── adopter.js
│       ├── methods.js
│       ├── pathParser.js
│       ├── utils.js
│       └── window.js
├── svg.js.d.ts
└── tsconfig.json
Download .txt
SYMBOL INDEX (762 symbols across 82 files)

FILE: .config/pretest.js
  function get (line 4) | function get(uri) {
  function main (line 14) | function main() {

FILE: playgrounds/colors/main.js
  function rectangles (line 4) | function rectangles(method = 'Vibrant') {

FILE: playgrounds/matrix/drag.js
  function reactToDrag (line 1) | function reactToDrag(element, onDrag, beforeDrag) {

FILE: playgrounds/matrix/matrix.js
  function print (line 1) | function print(mat) {
  function moveit (line 11) | function moveit() {

FILE: spec/RAFPlugin.js
  function RAFPlugin (line 6) | function RAFPlugin(jasmine) {

FILE: spec/helpers.js
  function tag (line 4) | function tag(name, attrs, children) {
  function fixtures (line 24) | function fixtures() {
  function buildFixtures (line 145) | function buildFixtures() {
  function buildCanvas (line 165) | function buildCanvas() {
  function clear (line 183) | function clear() {

FILE: spec/setupSVGDom.js
  function setup (line 10) | function setup() {
  function teardown (line 18) | function teardown() {

FILE: spec/spec/animation/Runner.js
  function getLoop (line 196) | function getLoop(r) {
  function closeTo (line 1336) | function closeTo(number, precision = 2) {
  function equal (line 1361) | function equal(obj) {

FILE: spec/spec/utils/adopter.js
  method test (line 241) | test() {
  method test (line 257) | test() {

FILE: src/animation/Animator.js
  method frame (line 12) | frame(fn) {
  method timeout (line 25) | timeout(fn, delay) {
  method immediate (line 42) | immediate(fn) {
  method cancelFrame (line 53) | cancelFrame(node) {
  method clearTimeout (line 57) | clearTimeout(node) {
  method cancelImmediate (line 61) | cancelImmediate(node) {
  method _draw (line 65) | _draw(now) {

FILE: src/animation/Controller.js
  function makeSetterGetter (line 10) | function makeSetterGetter(k, f) {
  class Stepper (line 95) | class Stepper {
    method done (line 96) | done() {
  class Ease (line 106) | class Ease extends Stepper {
    method constructor (line 107) | constructor(fn = timeline.ease) {
    method step (line 112) | step(from, to, pos) {
  class Controller (line 125) | class Controller extends Stepper {
    method constructor (line 126) | constructor(fn) {
    method done (line 131) | done(c) {
    method step (line 135) | step(current, target, dt, c) {
  function recalculate (line 140) | function recalculate() {
  class Spring (line 157) | class Spring extends Controller {
    method constructor (line 158) | constructor(duration = 500, overshoot = 0) {
    method step (line 163) | step(current, target, dt, c) {
  class PID (line 194) | class PID extends Controller {
    method constructor (line 195) | constructor(p = 0.1, i = 0.01, d = 0, windup = 1000) {
    method step (line 200) | step(current, target, dt, c) {

FILE: src/animation/Morphable.js
  class Morphable (line 39) | class Morphable {
    method constructor (line 40) | constructor(stepper) {
    method at (line 50) | at(pos) {
    method done (line 60) | done() {
    method from (line 70) | from(val) {
    method stepper (line 79) | stepper(stepper) {
    method to (line 85) | to(val) {
    method type (line 94) | type(type) {
    method _set (line 105) | _set(value) {
  class NonMorphable (line 142) | class NonMorphable {
    method constructor (line 143) | constructor(...args) {
    method init (line 147) | init(val) {
    method toArray (line 153) | toArray() {
    method valueOf (line 157) | valueOf() {
  class TransformBag (line 162) | class TransformBag {
    method constructor (line 163) | constructor(...args) {
    method init (line 167) | init(obj) {
    method toArray (line 185) | toArray() {
  class ObjectBag (line 216) | class ObjectBag {
    method constructor (line 217) | constructor(...args) {
    method align (line 221) | align(other) {
    method init (line 263) | init(objOrArr) {
    method toArray (line 286) | toArray() {
    method valueOf (line 290) | valueOf() {
  function registerMorphableType (line 309) | function registerMorphableType(type = []) {
  function makeMorphable (line 313) | function makeMorphable() {

FILE: src/animation/Queue.js
  class Queue (line 1) | class Queue {
    method constructor (line 2) | constructor() {
    method first (line 8) | first() {
    method last (line 13) | last() {
    method push (line 17) | push(value) {
    method remove (line 39) | remove(item) {
    method shift (line 51) | shift() {

FILE: src/animation/Runner.js
  class Runner (line 17) | class Runner extends EventTarget {
    method constructor (line 18) | constructor(options) {
    method sanitise (line 70) | static sanitise(duration, delay, when) {
    method active (line 99) | active(enabled) {
    method addTransform (line 110) | addTransform(transform) {
    method after (line 115) | after(fn) {
    method animate (line 119) | animate(duration, delay, when) {
    method clearTransform (line 127) | clearTransform() {
    method clearTransformsFromQueue (line 133) | clearTransformsFromQueue() {
    method delay (line 145) | delay(delay) {
    method duration (line 149) | duration() {
    method during (line 153) | during(fn) {
    method ease (line 157) | ease(fn) {
    method element (line 168) | element(element) {
    method finish (line 175) | finish() {
    method loop (line 179) | loop(times, swing, wait) {
    method loops (line 200) | loops(p) {
    method persist (line 214) | persist(dtOrForever) {
    method position (line 220) | position(p) {
    method progress (line 267) | progress(p) {
    method queue (line 279) | queue(initFn, runFn, retargetFn, isTransform) {
    method reset (line 293) | reset() {
    method reverse (line 300) | reverse(reverse) {
    method schedule (line 305) | schedule(timeline, delay, when) {
    method step (line 323) | step(dt) {
    method time (line 380) | time(time) {
    method timeline (line 389) | timeline(timeline) {
    method unschedule (line 396) | unschedule() {
    method _initialise (line 403) | _initialise(running) {
    method _rememberMorpher (line 425) | _rememberMorpher(method, morpher) {
    method _run (line 445) | _run(positionOrDt) {
    method _tryRetarget (line 464) | _tryRetarget(method, target, extra) {
  class FakeRunner (line 493) | class FakeRunner {
    method constructor (line 494) | constructor(transforms = new Matrix(), id = -1, done = true) {
    method clearTransformsFromQueue (line 500) | clearTransformsFromQueue() {}
  method mergeWith (line 504) | mergeWith(runner) {
  function mergeTransforms (line 517) | function mergeTransforms() {
  class RunnerArray (line 533) | class RunnerArray {
    method constructor (line 534) | constructor() {
    method add (line 539) | add(runner) {
    method clearBefore (line 549) | clearBefore(id) {
    method edit (line 558) | edit(id, newRunner) {
    method getByID (line 565) | getByID(id) {
    method length (line 569) | length() {
    method merge (line 573) | merge() {
    method remove (line 603) | remove(id) {
  method animate (line 613) | animate(duration, delay, when) {
  method delay (line 623) | delay(by, when) {
  method _clearTransformRunnersBefore (line 631) | _clearTransformRunnersBefore(currentRunner) {
  method _currentTransform (line 635) | _currentTransform(current) {
  method _addRunner (line 647) | _addRunner(runner) {
  method _prepareRunner (line 657) | _prepareRunner() {
  method attr (line 671) | attr(a, v) {
  method css (line 676) | css(s, v) {
  method styleAttr (line 680) | styleAttr(type, nameOrAttrs, val) {
  method zoom (line 736) | zoom(level, point) {
  method transform (line 776) | transform(transforms, relative, affine) {
  method x (line 893) | x(x) {
  method y (line 898) | y(y) {
  method ax (line 902) | ax(x) {
  method ay (line 906) | ay(y) {
  method dx (line 910) | dx(x = 0) {
  method dy (line 914) | dy(y = 0) {
  method dmove (line 918) | dmove(x, y) {
  method _queueNumberDelta (line 922) | _queueNumberDelta(method, to) {
  method _queueObject (line 951) | _queueObject(method, to) {
  method _queueNumber (line 972) | _queueNumber(method, value) {
  method cx (line 977) | cx(x) {
  method cy (line 982) | cy(y) {
  method move (line 987) | move(x, y) {
  method amove (line 991) | amove(x, y) {
  method center (line 996) | center(x, y) {
  method size (line 1001) | size(width, height) {
  method width (line 1021) | width(width) {
  method height (line 1026) | height(height) {
  method plot (line 1031) | plot(a, b, c, d) {
  method leading (line 1058) | leading(value) {
  method viewbox (line 1063) | viewbox(x, y, width, height) {
  method update (line 1067) | update(o) {

FILE: src/animation/Timeline.js
  class Timeline (line 23) | class Timeline extends EventTarget {
    method constructor (line 25) | constructor(timeSource = defaultSource) {
    method active (line 34) | active() {
    method finish (line 38) | finish() {
    method getEndTime (line 45) | getEndTime() {
    method getEndTimeOfTimeline (line 52) | getEndTimeOfTimeline() {
    method getLastRunnerInfo (line 57) | getLastRunnerInfo() {
    method getRunnerInfoById (line 61) | getRunnerInfoById(id) {
    method pause (line 65) | pause() {
    method persist (line 70) | persist(dtOrForever) {
    method play (line 76) | play() {
    method reverse (line 82) | reverse(yes) {
    method schedule (line 91) | schedule(runner, delay, when) {
    method seek (line 148) | seek(dt) {
    method source (line 152) | source(fn) {
    method speed (line 158) | speed(speed) {
    method stop (line 164) | stop() {
    method time (line 170) | time(time) {
    method unschedule (line 177) | unschedule(runner) {
    method updateTime (line 189) | updateTime() {
    method _continue (line 197) | _continue(immediateStep = false) {
    method _stepFn (line 208) | _stepFn(immediateStep = false) {
    method terminate (line 312) | terminate() {

FILE: src/elements/A.js
  class A (line 12) | class A extends Container {
    method constructor (line 13) | constructor(node, attrs = node) {
    method target (line 18) | target(target) {
    method to (line 23) | to(url) {
  method unlink (line 38) | unlink() {
  method linkTo (line 55) | linkTo(url) {
  method linker (line 72) | linker() {

FILE: src/elements/Circle.js
  class Circle (line 12) | class Circle extends Shape {
    method constructor (line 13) | constructor(node, attrs = node) {
    method radius (line 17) | radius(r) {
    method rx (line 22) | rx(rx) {
    method ry (line 27) | ry(ry) {
    method size (line 31) | size(size) {

FILE: src/elements/ClipPath.js
  class ClipPath (line 6) | class ClipPath extends Container {
    method constructor (line 7) | constructor(node, attrs = node) {
    method remove (line 12) | remove() {
    method targets (line 22) | targets() {
  method clipper (line 36) | clipper() {
  method clipWith (line 40) | clipWith(element) {
  method unclip (line 52) | unclip() {

FILE: src/elements/Container.js
  class Container (line 4) | class Container extends Element {
    method flatten (line 5) | flatten() {
    method ungroup (line 15) | ungroup(parent = this.parent(), index = parent.index(this)) {

FILE: src/elements/Defs.js
  class Defs (line 4) | class Defs extends Container {
    method constructor (line 5) | constructor(node, attrs = node) {
    method flatten (line 9) | flatten() {
    method ungroup (line 13) | ungroup() {

FILE: src/elements/Dom.js
  class Dom (line 18) | class Dom extends EventTarget {
    method constructor (line 19) | constructor(node, attrs) {
    method add (line 30) | add(element, i) {
    method addTo (line 51) | addTo(parent, i) {
    method children (line 56) | children() {
    method clear (line 65) | clear() {
    method clone (line 75) | clone(deep = true, assignNewIds = true) {
    method each (line 89) | each(block, deep) {
    method element (line 104) | element(nodeName, attrs) {
    method first (line 109) | first() {
    method get (line 114) | get(i) {
    method getEventHolder (line 118) | getEventHolder() {
    method getEventTarget (line 122) | getEventTarget() {
    method has (line 127) | has(element) {
    method html (line 131) | html(htmlOrFn, outerHTML) {
    method id (line 136) | id(id) {
    method index (line 147) | index(element) {
    method last (line 152) | last() {
    method matches (line 157) | matches(selector) {
    method parent (line 171) | parent(type) {
    method put (line 194) | put(element, i) {
    method putIn (line 201) | putIn(parent, i) {
    method remove (line 206) | remove() {
    method removeElement (line 215) | removeElement(element) {
    method replace (line 222) | replace(element) {
    method round (line 232) | round(precision = 2, map = null) {
    method svg (line 247) | svg(svgOrFn, outerSVG) {
    method toString (line 252) | toString() {
    method words (line 256) | words(text) {
    method wrap (line 262) | wrap(node) {
    method writeDataToDom (line 274) | writeDataToDom() {
    method xml (line 284) | xml(xmlOrFn, outerXML, ns) {

FILE: src/elements/Element.js
  class Element (line 18) | class Element extends Dom {
    method constructor (line 19) | constructor(node, attrs) {
    method center (line 39) | center(x, y) {
    method cx (line 44) | cx(x) {
    method cy (line 51) | cy(y) {
    method defs (line 58) | defs() {
    method dmove (line 64) | dmove(x, y) {
    method dx (line 69) | dx(x = 0) {
    method dy (line 74) | dy(y = 0) {
    method getEventHolder (line 78) | getEventHolder() {
    method height (line 83) | height(height) {
    method move (line 88) | move(x, y) {
    method parents (line 93) | parents(until = this.root()) {
    method reference (line 124) | reference(attr) {
    method root (line 133) | root() {
    method setData (line 139) | setData(o) {
    method size (line 145) | size(width, height) {
    method width (line 152) | width(width) {
    method writeDataToDom (line 157) | writeDataToDom() {
    method x (line 163) | x(x) {
    method y (line 168) | y(y) {

FILE: src/elements/Ellipse.js
  class Ellipse (line 13) | class Ellipse extends Shape {
    method constructor (line 14) | constructor(node, attrs = node) {
    method size (line 18) | size(width, height) {

FILE: src/elements/ForeignObject.js
  class ForeignObject (line 5) | class ForeignObject extends Element {
    method constructor (line 6) | constructor(node, attrs = node) {

FILE: src/elements/Fragment.js
  class Fragment (line 5) | class Fragment extends Dom {
    method constructor (line 6) | constructor(node = globals.document.createDocumentFragment()) {
    method xml (line 11) | xml(xmlOrFn, outerXML, ns) {

FILE: src/elements/G.js
  class G (line 11) | class G extends Container {
    method constructor (line 12) | constructor(node, attrs = node) {

FILE: src/elements/Gradient.js
  class Gradient (line 13) | class Gradient extends Container {
    method constructor (line 14) | constructor(type, attrs) {
    method attr (line 22) | attr(a, b, c) {
    method bbox (line 27) | bbox() {
    method targets (line 31) | targets() {
    method toString (line 36) | toString() {
    method update (line 41) | update(block) {
    method url (line 54) | url() {
  method gradient (line 64) | gradient(...args) {

FILE: src/elements/Image.js
  class Image (line 11) | class Image extends Shape {
    method constructor (line 12) | constructor(node, attrs = node) {
    method load (line 17) | load(url, callback) {

FILE: src/elements/Line.js
  class Line (line 13) | class Line extends Shape {
    method constructor (line 15) | constructor(node, attrs = node) {
    method array (line 20) | array() {
    method move (line 28) | move(x, y) {
    method plot (line 33) | plot(x1, y1, x2, y2) {
    method size (line 46) | size(width, height) {

FILE: src/elements/Marker.js
  class Marker (line 5) | class Marker extends Container {
    method constructor (line 7) | constructor(node, attrs = node) {
    method height (line 12) | height(height) {
    method orient (line 16) | orient(orient) {
    method ref (line 21) | ref(x, y) {
    method toString (line 26) | toString() {
    method update (line 31) | update(block) {
    method width (line 44) | width(width) {
  method marker (line 51) | marker(...args) {
  method marker (line 70) | marker(marker, width, height, block) {

FILE: src/elements/Mask.js
  class Mask (line 6) | class Mask extends Container {
    method constructor (line 8) | constructor(node, attrs = node) {
    method remove (line 13) | remove() {
    method targets (line 23) | targets() {
  method masker (line 36) | masker() {
  method maskWith (line 40) | maskWith(element) {
  method unmask (line 50) | unmask() {

FILE: src/elements/Path.js
  class Path (line 7) | class Path extends Shape {
    method constructor (line 9) | constructor(node, attrs = node) {
    method array (line 14) | array() {
    method clear (line 19) | clear() {
    method height (line 25) | height(height) {
    method move (line 32) | move(x, y) {
    method plot (line 37) | plot(d) {
    method size (line 47) | size(width, height) {
    method width (line 53) | width(width) {
    method x (line 60) | x(x) {
    method y (line 65) | y(y) {

FILE: src/elements/Pattern.js
  class Pattern (line 7) | class Pattern extends Container {
    method constructor (line 9) | constructor(node, attrs = node) {
    method attr (line 14) | attr(a, b, c) {
    method bbox (line 19) | bbox() {
    method targets (line 23) | targets() {
    method toString (line 28) | toString() {
    method update (line 33) | update(block) {
    method url (line 46) | url() {
  method pattern (line 54) | pattern(...args) {

FILE: src/elements/Polygon.js
  class Polygon (line 13) | class Polygon extends Shape {
    method constructor (line 15) | constructor(node, attrs = node) {

FILE: src/elements/Polyline.js
  class Polyline (line 13) | class Polyline extends Shape {
    method constructor (line 15) | constructor(node, attrs = node) {

FILE: src/elements/Rect.js
  class Rect (line 11) | class Rect extends Shape {
    method constructor (line 13) | constructor(node, attrs = node) {

FILE: src/elements/Shape.js
  class Shape (line 4) | class Shape extends Element {}

FILE: src/elements/Stop.js
  class Stop (line 6) | class Stop extends Element {
    method constructor (line 7) | constructor(node, attrs = node) {
    method update (line 12) | update(o) {

FILE: src/elements/Style.js
  function cssRule (line 6) | function cssRule(selector, rule) {
  class Style (line 21) | class Style extends Element {
    method constructor (line 22) | constructor(node, attrs = node) {
    method addText (line 26) | addText(w = '') {
    method font (line 31) | font(name, src, params = {}) {
    method rule (line 39) | rule(selector, obj) {
  method style (line 45) | style(selector, obj) {
  method fontface (line 48) | fontface(name, src, params) {

FILE: src/elements/Svg.js
  class Svg (line 13) | class Svg extends Container {
    method constructor (line 14) | constructor(node, attrs = node) {
    method defs (line 20) | defs() {
    method isRoot (line 26) | isRoot() {
    method namespace (line 35) | namespace() {
    method removeNamespace (line 44) | removeNamespace() {
    method root (line 52) | root() {

FILE: src/elements/Symbol.js
  class Symbol (line 5) | class Symbol extends Container {
    method constructor (line 7) | constructor(node, attrs = node) {

FILE: src/elements/Text.js
  class Text (line 15) | class Text extends Shape {
    method constructor (line 17) | constructor(node, attrs = node) {
    method leading (line 26) | leading(value) {
    method rebuild (line 39) | rebuild(rebuild) {
    method setData (line 79) | setData(o) {
    method writeDataToDom (line 85) | writeDataToDom() {
    method text (line 91) | text(text) {

FILE: src/elements/TextPath.js
  class TextPath (line 9) | class TextPath extends Text {
    method constructor (line 11) | constructor(node, attrs = node) {
    method array (line 16) | array() {
    method plot (line 23) | plot(d) {
    method track (line 35) | track() {
  method textPath (line 78) | textPath() {
  method targets (line 94) | targets() {

FILE: src/elements/Tspan.js
  class Tspan (line 14) | class Tspan extends Shape {
    method constructor (line 16) | constructor(node, attrs = node) {
    method dx (line 22) | dx(dx) {
    method dy (line 27) | dy(dy) {
    method newLine (line 32) | newLine() {
    method text (line 56) | text(text) {

FILE: src/elements/Use.js
  class Use (line 6) | class Use extends Shape {
    method constructor (line 7) | constructor(node, attrs = node) {
    method use (line 12) | use(element, file) {

FILE: src/main.js
  constant SVG (line 65) | const SVG = makeInstance

FILE: src/modules/core/attr.js
  function registerAttrHook (line 18) | function registerAttrHook(fn) {
  function attr (line 23) | function attr(attr, val, ns) {

FILE: src/modules/core/circled.js
  function rx (line 4) | function rx(rx) {
  function ry (line 9) | function ry(ry) {
  function x (line 14) | function x(x) {
  function y (line 19) | function y(y) {
  function cx (line 24) | function cx(x) {
  function cy (line 29) | function cy(y) {
  function width (line 34) | function width(width) {
  function height (line 39) | function height(height) {

FILE: src/modules/core/containerGeometry.js
  function dmove (line 7) | function dmove(dx, dy) {
  function dx (line 42) | function dx(dx) {
  function dy (line 46) | function dy(dy) {
  function height (line 50) | function height(height, box = this.bbox()) {
  function move (line 55) | function move(x = 0, y = 0, box = this.bbox()) {
  function size (line 62) | function size(width, height, box = this.bbox()) {
  function width (line 75) | function width(width, box = this.bbox()) {
  function x (line 80) | function x(x, box = this.bbox()) {
  function y (line 85) | function y(y, box = this.bbox()) {

FILE: src/modules/core/defaults.js
  function noop (line 1) | function noop() {}

FILE: src/modules/core/event.js
  function getEvents (line 8) | function getEvents(instance) {
  function getEventTarget (line 17) | function getEventTarget(instance) {
  function clearEvents (line 21) | function clearEvents(instance) {
  function on (line 28) | function on(node, events, listener, binding, options) {
  function off (line 59) | function off(node, events, listener, options) {
  function dispatch (line 128) | function dispatch(node, event, data, options) {

FILE: src/modules/core/gradiented.js
  function from (line 3) | function from(x, y) {
  function to (line 9) | function to(x, y) {

FILE: src/modules/core/parser.js
  function parser (line 4) | function parser() {

FILE: src/modules/core/pointed.js
  function x (line 6) | function x(x) {
  function y (line 11) | function y(y) {
  function width (line 16) | function width(width) {
  function height (line 22) | function height(height) {

FILE: src/modules/core/poly.js
  function array (line 5) | function array() {
  function clear (line 10) | function clear() {
  function move (line 16) | function move(x, y) {
  function plot (line 21) | function plot(p) {
  function size (line 31) | function size(width, height) {

FILE: src/modules/core/selector.js
  function baseFind (line 6) | function baseFind(query, parent) {
  function find (line 15) | function find(query) {
  function findOne (line 19) | function findOne(query) {

FILE: src/modules/core/textable.js
  function plain (line 4) | function plain(text) {
  function length (line 17) | function length() {
  function x (line 24) | function x(x, box = this.bbox()) {
  function y (line 33) | function y(y, box = this.bbox()) {
  function move (line 41) | function move(x, y, box = this.bbox()) {
  function cx (line 46) | function cx(x, box = this.bbox()) {
  function cy (line 55) | function cy(y, box = this.bbox()) {
  function center (line 63) | function center(x, y, box = this.bbox()) {
  function ax (line 67) | function ax(x) {
  function ay (line 71) | function ay(y) {
  function amove (line 75) | function amove(x, y) {
  function build (line 80) | function build(build) {

FILE: src/modules/optional/arrange.js
  function siblings (line 5) | function siblings() {
  function position (line 10) | function position() {
  function next (line 15) | function next() {
  function prev (line 20) | function prev() {
  function forward (line 25) | function forward() {
  function backward (line 36) | function backward() {
  function front (line 46) | function front() {
  function back (line 56) | function back() {
  function before (line 66) | function before(element) {
  function after (line 78) | function after(element) {
  function insertBefore (line 89) | function insertBefore(element) {
  function insertAfter (line 95) | function insertAfter(element) {

FILE: src/modules/optional/class.js
  function classes (line 5) | function classes() {
  function hasClass (line 11) | function hasClass(name) {
  function addClass (line 16) | function addClass(name) {
  function removeClass (line 27) | function removeClass(name) {
  function toggleClass (line 43) | function toggleClass(name) {

FILE: src/modules/optional/css.js
  function css (line 5) | function css(style, val) {
  function show (line 60) | function show() {
  function hide (line 65) | function hide() {
  function visible (line 70) | function visible() {

FILE: src/modules/optional/data.js
  function data (line 5) | function data(a, v, r) {

FILE: src/modules/optional/memory.js
  function remember (line 4) | function remember(k, v) {
  function forget (line 22) | function forget() {
  function memory (line 36) | function memory() {

FILE: src/modules/optional/transform.js
  function untransform (line 7) | function untransform() {
  function matrixify (line 12) | function matrixify() {
  function toParent (line 40) | function toParent(parent, i) {
  function toRoot (line 54) | function toRoot(i) {
  function transform (line 59) | function transform(o, relative) {

FILE: src/polyfills/children.js
  function children (line 4) | function children(node) {

FILE: src/svg.js
  function SVG (line 5) | function SVG(element, isHTML) {

FILE: src/types/Base.js
  class Base (line 1) | class Base {

FILE: src/types/Box.js
  function isNulledBox (line 9) | function isNulledBox(box) {
  function domContains (line 13) | function domContains(node) {
  class Box (line 29) | class Box {
    method constructor (line 30) | constructor(...args) {
    method addOffset (line 34) | addOffset() {
    method init (line 41) | init(source) {
    method isNulled (line 73) | isNulled() {
    method merge (line 78) | merge(box) {
    method toArray (line 87) | toArray() {
    method toString (line 91) | toString() {
    method transform (line 95) | transform(m) {
  function getBox (line 124) | function getBox(el, getBBoxFn, retry) {
  function bbox (line 144) | function bbox() {
  function rbox (line 172) | function rbox(el) {
  function inside (line 196) | function inside(x, y) {
  method viewbox (line 206) | viewbox(x, y, width, height) {
  method zoom (line 214) | zoom(level, point) {

FILE: src/types/Color.js
  function sixDigitHex (line 3) | function sixDigitHex(hex) {
  function componentHex (line 17) | function componentHex(component) {
  function is (line 24) | function is(object, space) {
  function getParameters (line 33) | function getParameters(a, b) {
  function cieSpace (line 52) | function cieSpace(space) {
  function hueToRgb (line 60) | function hueToRgb(p, q, t) {
  class Color (line 69) | class Color {
    method constructor (line 70) | constructor(...inputs) {
    method isColor (line 75) | static isColor(color) {
    method isRgb (line 82) | static isRgb(color) {
    method random (line 94) | static random(mode = 'vibrant', t) {
    method test (line 146) | static test(color) {
    method cmyk (line 150) | cmyk() {
    method hsl (line 172) | hsl() {
    method init (line 207) | init(a = 0, b = 0, c = 0, d = 0, space = 'rgb') {
    method lab (line 267) | lab() {
    method lch (line 281) | lch() {
    method rgb (line 301) | rgb() {
    method toArray (line 391) | toArray() {
    method toHex (line 396) | toHex() {
    method toRgb (line 401) | toRgb() {
    method toString (line 407) | toString() {
    method xyz (line 411) | xyz() {
    method _clamped (line 440) | _clamped() {

FILE: src/types/EventTarget.js
  class EventTarget (line 5) | class EventTarget extends Base {
    method addEventListener (line 6) | addEventListener() {}
    method dispatch (line 8) | dispatch(event, data, options) {
    method dispatchEvent (line 12) | dispatchEvent(event) {
    method fire (line 28) | fire(event, data, options) {
    method getEventHolder (line 33) | getEventHolder() {
    method getEventTarget (line 37) | getEventTarget() {
    method off (line 42) | off(event, listener, options) {
    method on (line 48) | on(event, listener, binding, options) {
    method removeEventListener (line 53) | removeEventListener() {}

FILE: src/types/List.js
  class List (line 4) | class List extends Array {
    method constructor (line 5) | constructor(arr = [], ...args) {
  method each (line 23) | each(fnOrMethodName, ...args) {
  method toArray (line 35) | toArray() {

FILE: src/types/Matrix.js
  function closeEnough (line 7) | function closeEnough(a, b, threshold) {
  class Matrix (line 11) | class Matrix {
    method constructor (line 12) | constructor(...args) {
    method formatTransforms (line 16) | static formatTransforms(o) {
    method fromArray (line 100) | static fromArray(a) {
    method isMatrixLike (line 104) | static isMatrixLike(o) {
    method matrixMultiply (line 116) | static matrixMultiply(l, r, o) {
    method around (line 136) | around(cx, cy, matrix) {
    method aroundO (line 141) | aroundO(cx, cy, matrix) {
    method clone (line 148) | clone() {
    method decompose (line 153) | decompose(cx = 0, cy = 0) {
    method equals (line 206) | equals(other) {
    method flip (line 220) | flip(axis, around) {
    method flipO (line 224) | flipO(axis, around) {
    method init (line 233) | init(source) {
    method inverse (line 263) | inverse() {
    method inverseO (line 268) | inverseO() {
    method lmultiply (line 302) | lmultiply(matrix) {
    method lmultiplyO (line 306) | lmultiplyO(matrix) {
    method multiply (line 314) | multiply(matrix) {
    method multiplyO (line 318) | multiplyO(matrix) {
    method rotate (line 327) | rotate(r, cx, cy) {
    method rotateO (line 331) | rotateO(r, cx = 0, cy = 0) {
    method scale (line 351) | scale() {
    method scaleO (line 355) | scaleO(x, y = x, cx = 0, cy = 0) {
    method shear (line 376) | shear(a, cx, cy) {
    method shearO (line 381) | shearO(lx, cx = 0, cy = 0) {
    method skew (line 392) | skew() {
    method skewO (line 396) | skewO(x, y = x, cx = 0, cy = 0) {
    method skewX (line 424) | skewX(x, cx, cy) {
    method skewY (line 429) | skewY(y, cx, cy) {
    method toArray (line 433) | toArray() {
    method toString (line 438) | toString() {
    method transform (line 457) | transform(o) {
    method translate (line 496) | translate(x, y) {
    method translateO (line 500) | translateO(x, y) {
    method valueOf (line 506) | valueOf() {
  function ctm (line 518) | function ctm() {
  function screenCTM (line 522) | function screenCTM() {

FILE: src/types/PathArray.js
  function arrayToString (line 6) | function arrayToString(a) {
  class PathArray (line 43) | class PathArray extends SVGArray {
    method bbox (line 45) | bbox() {
    method move (line 51) | move(x, y) {
    method parse (line 92) | parse(d = 'M0 0') {
    method size (line 101) | size(width, height) {
    method toString (line 147) | toString() {

FILE: src/types/Point.js
  class Point (line 3) | class Point {
    method constructor (line 5) | constructor(...args) {
    method clone (line 10) | clone() {
    method init (line 14) | init(x, y) {
    method toArray (line 31) | toArray() {
    method transform (line 35) | transform(m) {
    method transformO (line 40) | transformO(m) {
  function point (line 55) | function point(x, y) {

FILE: src/types/PointArray.js
  class PointArray (line 6) | class PointArray extends SVGArray {
    method bbox (line 8) | bbox() {
    method move (line 23) | move(x, y) {
    method parse (line 41) | parse(array = [0, 0]) {
    method size (line 66) | size(width, height) {
    method toLine (line 82) | toLine() {
    method toString (line 92) | toString() {
    method transform (line 102) | transform(m) {
    method transformO (line 107) | transformO(m) {

FILE: src/types/SVGArray.js
  class SVGArray (line 3) | class SVGArray extends Array {
    method constructor (line 4) | constructor(...args) {
    method clone (line 9) | clone() {
    method init (line 13) | init(arr) {
    method parse (line 22) | parse(array = []) {
    method toArray (line 29) | toArray() {
    method toSet (line 33) | toSet() {
    method toString (line 37) | toString() {
    method valueOf (line 42) | valueOf() {

FILE: src/types/SVGNumber.js
  class SVGNumber (line 4) | class SVGNumber {
    method constructor (line 6) | constructor(...args) {
    method convert (line 10) | convert(unit) {
    method divide (line 15) | divide(number) {
    method init (line 20) | init(value, unit) {
    method minus (line 66) | minus(number) {
    method plus (line 72) | plus(number) {
    method times (line 78) | times(number) {
    method toArray (line 83) | toArray() {
    method toJSON (line 87) | toJSON() {
    method toString (line 91) | toString() {
    method valueOf (line 101) | valueOf() {

FILE: src/utils/adopter.js
  function create (line 11) | function create(name, ns = svg) {
  function makeInstance (line 16) | function makeInstance(element, isHTML = false) {
  function nodeOrNew (line 43) | function nodeOrNew(name, node) {
  function adopt (line 53) | function adopt(node) {
  function mockAdopt (line 81) | function mockAdopt(mock = adopt) {
  function register (line 85) | function register(element, name = element.name, asRoot = false) {
  function getClass (line 94) | function getClass(name) {
  function eid (line 102) | function eid(name) {
  function assignNewId (line 107) | function assignNewId(node) {
  function extend (line 122) | function extend(modules, methods) {
  function wrapWithAttrCheck (line 134) | function wrapWithAttrCheck(fn) {

FILE: src/utils/methods.js
  function registerMethods (line 4) | function registerMethods(name, m) {
  function getMethodsFor (line 23) | function getMethodsFor(name) {
  function getMethodNames (line 27) | function getMethodNames() {
  function addMethodNames (line 31) | function addMethodNames(_names) {

FILE: src/utils/pathParser.js
  function makeAbsolut (line 90) | function makeAbsolut(parser) {
  function segmentComplete (line 95) | function segmentComplete(parser) {
  function startNewSegment (line 103) | function startNewSegment(parser, token) {
  function finalizeNumber (line 122) | function finalizeNumber(parser, inNumber) {
  function finalizeSegment (line 135) | function finalizeSegment(parser) {
  function isArcFlag (line 143) | function isArcFlag(parser) {
  function isExponential (line 151) | function isExponential(parser) {
  function pathParser (line 156) | function pathParser(d, toAbsolute = true) {

FILE: src/utils/utils.js
  function map (line 2) | function map(array, block) {
  function filter (line 15) | function filter(array, block) {
  function radians (line 30) | function radians(d) {
  function degrees (line 35) | function degrees(r) {
  function unCamelCase (line 40) | function unCamelCase(s) {
  function capitalize (line 47) | function capitalize(s) {
  function proportionalSize (line 52) | function proportionalSize(element, width, height, box) {
  function getOrigin (line 74) | function getOrigin(o, element) {

FILE: src/utils/window.js
  function registerWindow (line 6) | function registerWindow(win = null, doc = null) {
  function saveWindow (line 13) | function saveWindow() {
  function restoreWindow (line 18) | function restoreWindow() {
  function withWindow (line 23) | function withWindow(win, fn) {
  function getWindow (line 30) | function getWindow() {

FILE: svg.js.d.ts
  class BuiltInArray (line 5) | class BuiltInArray<T> extends Array<T> {}
  type CamelToKebab (line 8) | type CamelToKebab<S extends string> = S extends `${infer T}${infer U}`
  type ConvertKeysToKebab (line 14) | type ConvertKeysToKebab<T> = {
  type KebabCSSStyleDeclaration (line 18) | type KebabCSSStyleDeclaration = ConvertKeysToKebab<CSSStyleDeclaration>
  type CSSStyleName (line 21) | type CSSStyleName = Exclude<
  type CSSStyleDeclarationWithVars (line 27) | interface CSSStyleDeclarationWithVars extends KebabCSSStyleDeclaration {
  type LinkedHTMLElement (line 179) | interface LinkedHTMLElement extends HTMLElement {
  type AttrNumberValue (line 185) | type AttrNumberValue = number | 'auto'
  type CoreAttr (line 191) | interface CoreAttr {
  type StylingAttr (line 202) | interface StylingAttr {
  type GlobalAttr (line 216) | interface GlobalAttr extends CoreAttr, StylingAttr {}
  type PathBaseAttr (line 220) | interface PathBaseAttr {
  type RadiusAxisAttr (line 224) | interface RadiusAxisAttr {
  type RectAttr (line 232) | interface RectAttr extends RadiusAxisAttr, PathBaseAttr, GlobalAttr {
  type LineAttr (line 242) | interface LineAttr extends PathBaseAttr, GlobalAttr {
  type CircleAttr (line 252) | interface CircleAttr extends PathBaseAttr, GlobalAttr {
  type EllipseAttr (line 261) | interface EllipseAttr extends PathBaseAttr, GlobalAttr {
  type PathAttr (line 271) | interface PathAttr extends PathBaseAttr, GlobalAttr {
  type PolyAttr (line 279) | interface PolyAttr extends PathBaseAttr, GlobalAttr {
  type TextAttr (line 286) | interface TextAttr extends GlobalAttr {
  type TextPathAttr (line 302) | interface TextPathAttr extends GlobalAttr {
  type DOMRect (line 320) | interface DOMRect {
  type SVGTypeMapping (line 333) | type SVGTypeMapping<T> = T extends HTMLElement
  type SvgType (line 376) | type SvgType = 'svg'
  type ClipPathType (line 377) | type ClipPathType = 'clipPath'
  type TextType (line 378) | type TextType = 'text'
  type GType (line 379) | type GType = 'g'
  type AType (line 380) | type AType = 'a'
  type ParentElement (line 382) | type ParentElement = SvgType | GType | AType
  type AttrTypeMapping (line 384) | type AttrTypeMapping<T> = T extends Rect ? RectAttr : GlobalAttr
  type ElementAlias (line 386) | type ElementAlias =
  type ElementTypeAlias (line 405) | type ElementTypeAlias =
  type AttributeReference (line 424) | type AttributeReference =
  type ArrayAlias (line 449) | type ArrayAlias<T> = BuiltInArray<T> | T[] | string
  class Array (line 451) | class Array<T> extends BuiltInArray<T> {
  class Point (line 471) | class Point {
  class PointArray (line 485) | class PointArray extends Array<ArrayXY> {
  type NumberUnit (line 499) | type NumberUnit = [number, string]
  class Number (line 501) | class Number {
  type NumberAlias (line 523) | type NumberAlias = Number | number | string
  type LineCommand (line 527) | type LineCommand =
  type CurveCommand (line 532) | type CurveCommand =
  type PathCommand (line 540) | type PathCommand = LineCommand | CurveCommand
  type PathArrayAlias (line 542) | type PathArrayAlias = PathArray | PathCommand[] | (string | number)[] | ...
  class PathArray (line 544) | class PathArray extends Array<PathCommand> {
  type TransformData (line 558) | interface TransformData {
  type MatrixLike (line 570) | interface MatrixLike {
  type MatrixExtract (line 579) | interface MatrixExtract extends TransformData, MatrixLike {}
  type FlipType (line 581) | type FlipType = 'both' | 'x' | 'y' | boolean
  type ArrayXY (line 582) | type ArrayXY = [number, number]
  type CoordinateXY (line 583) | type CoordinateXY = ArrayXY | { x: number; y: number }
  type MatrixTransformParam (line 585) | interface MatrixTransformParam {
  type MatrixAlias (line 619) | type MatrixAlias =
  class Matrix (line 627) | class Matrix implements MatrixLike {
  type ListEachCallback (line 684) | type ListEachCallback<T> = (el: T, index: number, list: List<T>) => any
  class List (line 687) | class List<T> extends BuiltInArray<T> {
  class Eventobject (line 693) | class Eventobject {
  class EventTarget (line 698) | class EventTarget {
  type ColorLike (line 724) | interface ColorLike {
  type ColorAlias (line 745) | type ColorAlias = string | ColorLike
  class Color (line 747) | class Color implements ColorLike {
  type BoxLike (line 791) | interface BoxLike {
  class Box (line 804) | class Box implements BoxLike {
  type MorphValueLike (line 832) | type MorphValueLike =
  class Morphable (line 841) | class Morphable {
  class objectBag (line 857) | class objectBag {
  class NonMorphable (line 867) | class NonMorphable {
  class TransformBag (line 876) | class TransformBag {
  type Stepper (line 886) | interface Stepper {
  class Ease (line 890) | class Ease implements Stepper {
  class Controller (line 899) | class Controller implements Stepper {
  type QueueParam (line 906) | interface QueueParam {
  class Queue (line 912) | class Queue {
  type ScheduledRunnerInfo (line 923) | interface ScheduledRunnerInfo {
  class Timeline (line 930) | class Timeline extends EventTarget {
  type TimesParam (line 955) | interface TimesParam {
  type TimeLike (line 964) | type TimeLike = number | TimesParam | Stepper
  type EasingCallback (line 966) | type EasingCallback = (...any: any) => number
  type EasingLiteral (line 967) | type EasingLiteral = '<>' | '-' | '<' | '>'
  class Runner (line 969) | class Runner {
  type QuerySelector (line 1113) | type QuerySelector = string
  class Dom (line 1115) | class Dom extends EventTarget {
  class ClipPath (line 1251) | class ClipPath extends Container {
  type ViewBoxLike (line 1262) | interface ViewBoxLike {
  class Containable (line 1269) | class Containable {
  type DynamicExtends (line 1313) | type DynamicExtends<T extends {}> = {
  class Fragment (line 1321) | class Fragment extends ContainableDom {
  class Container (line 1329) | class Container extends ContainableElement {
  class Defs (line 1335) | class Defs extends Container {
  class Svg (line 1345) | class Svg extends Container {
  type EventHandler (line 1355) | type EventHandler<T extends Event> = (event: T) => void
  type Sugar (line 1357) | interface Sugar {
  class Symbol (line 1414) | class Symbol extends Container {
  class Element (line 1420) | class Element extends Dom implements Sugar {
  type CircleMethods (line 1609) | interface CircleMethods extends Shape {
  class Circle (line 1616) | class Circle extends Shape implements CircleMethods {
  class Ellipse (line 1628) | class Ellipse extends Shape implements CircleMethods {
  type StopProperties (line 1640) | interface StopProperties {
  class Stop (line 1647) | class Stop extends Element {
  class Gradient (line 1651) | class Gradient extends Container {
  class G (line 1676) | class G extends Container {
  class A (line 1683) | class A extends Container {
  class ForeignObject (line 1694) | class ForeignObject extends Element {
  class Image (line 1701) | class Image extends Shape {
  type PointArrayAlias (line 1709) | type PointArrayAlias = number[] | ArrayXY[] | PointArray | string
  class Line (line 1711) | class Line extends Shape {
  class Marker (line 1734) | class Marker extends Container {
  class Mask (line 1746) | class Mask extends Container {
  class Path (line 1755) | class Path extends Shape {
  class Pattern (line 1782) | class Pattern extends Container {
  type poly (line 1790) | interface poly {
  type pointed (line 1800) | interface pointed {
  class Polyline (line 1811) | class Polyline extends Shape implements poly, pointed {
  class Polygon (line 1839) | class Polygon extends Shape implements poly, pointed {
  class Rect (line 1866) | class Rect extends Shape {
  class Shape (line 1874) | class Shape extends Element {}
  type StrokeData (line 1877) | interface StrokeData {
  type FillData (line 1888) | interface FillData {
  type FontData (line 1894) | interface FontData {
  type Textable (line 1903) | interface Textable {
  class Text (line 1909) | class Text extends Shape implements Textable {
  class Tspan (line 1940) | class Tspan extends Text implements Textable {
  class TextPath (line 1958) | class TextPath extends Text {
  class Style (line 1969) | class Style extends Element {
  class Use (line 1979) | class Use extends Shape {
  type ViewBoxAlias (line 1984) | type ViewBoxAlias = ViewBoxLike | number[] | string | Element
  type ViewBox (line 1986) | interface ViewBox {
Condensed preview — 200 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (851K chars).
[
  {
    "path": ".config/karma.conf.cjs",
    "chars": 2582,
    "preview": "// Karma configuration\nconst karmaCommon = require('./karma.conf.common.cjs')\n\nlet chromeBin = 'ChromeHeadless'\nif (proc"
  },
  {
    "path": ".config/karma.conf.common.cjs",
    "chars": 1675,
    "preview": "// Karma shared configuration\n\nconst os = require('os')\nconst cpuCount = os.cpus().length\n\nmodule.exports = function (co"
  },
  {
    "path": ".config/karma.conf.saucelabs.cjs",
    "chars": 4392,
    "preview": "// Karma configuration\n// https://wiki.saucelabs.com/display/DOCS/Platform+Configurator\n\n// TODO: remove dotenv after lo"
  },
  {
    "path": ".config/polyfillListIE.js",
    "chars": 858,
    "preview": "/* global SVGElement */\n/* eslint no-new-object: \"off\" */\n\nimport CustomEventPolyfill from '@target/custom-event-polyfil"
  },
  {
    "path": ".config/pretest.js",
    "chars": 498,
    "preview": "/* global XMLHttpRequest */\n'use strict'\n\nfunction get(uri) {\n  var xhr = new XMLHttpRequest()\n  xhr.open('GET', uri, fa"
  },
  {
    "path": ".config/rollup.config.js",
    "chars": 2896,
    "preview": "import pkg from '../package.json' with { type: 'json' }\nimport babel from '@rollup/plugin-babel'\nimport resolve from '@r"
  },
  {
    "path": ".config/rollup.polyfills.js",
    "chars": 465,
    "preview": "import resolve from '@rollup/plugin-node-resolve'\nimport commonjs from '@rollup/plugin-commonjs'\nimport filesize from 'r"
  },
  {
    "path": ".config/rollup.tests.js",
    "chars": 1376,
    "preview": "import * as pkg from '../package.json'\nimport babel from '@rollup/plugin-babel'\nimport multiEntry from '@rollup/plugin-m"
  },
  {
    "path": ".eslintrc.json",
    "chars": 417,
    "preview": "{\n  \"parserOptions\": {\n    \"ecmaVersion\": \"latest\",\n    \"sourceType\": \"module\"\n  },\n  \"env\": {\n    \"browser\": true,\n    "
  },
  {
    "path": ".github/CONTRIBUTING.md",
    "chars": 1614,
    "preview": "# Contributing\n\nWhen contributing to this repository, please first discuss the change you wish to make on gitter, or wit"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 65,
    "preview": "# These are supported funding model platforms\n\ngithub: [fuzzyma]\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report.md",
    "chars": 692,
    "preview": "---\nname: Bug Report\nabout: 🐞 Report a bug that you found\n---\n\n# Bug report\n\n> **For support questions, please use [stac"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature-request.md",
    "chars": 1336,
    "preview": "---\nname: Feature Request\nabout: 🎂 Ask nicely for something you reaaaaaaaally want\n---\n\n# Feature request\n\n> **For suppo"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/other.md",
    "chars": 320,
    "preview": "---\nname: Other Issue\nabout: 🍺 Something else...\n---\n\n> **For support questions, please use [stackoverflow](https://stac"
  },
  {
    "path": ".gitignore",
    "chars": 127,
    "preview": ".DS_Store\n.idea\n.importjs.js\ntest/\nnode_modules/\n.vscode/\ncoverage/\nspec/es5TestBundle.js\n.env\ndist\nindex.html\nindex.js\n"
  },
  {
    "path": ".prettierignore",
    "chars": 118,
    "preview": ".DS_Store\n.idea\n.importjs.js\ntest/\nnode_modules/\n.vscode/\ncoverage/\nspec/es5TestBundle.js\n.env\ndist\npackage-lock.json\n"
  },
  {
    "path": ".prettierrc.json",
    "chars": 87,
    "preview": "{\n  \"trailingComma\": \"none\",\n  \"tabWidth\": 2,\n  \"semi\": false,\n  \"singleQuote\": true\n}\n"
  },
  {
    "path": ".travis.yml",
    "chars": 231,
    "preview": "language: node_js\nnode_js:\n  - 'stable'\nservices:\n  - xvfb\naddons:\n  firefox: latest\n  chrome: stable\ninstall:\n  - npm i"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 41181,
    "preview": "# Change Log\n\nAll notable changes to this project will be documented in this file.\n\nThe document follows the conventions"
  },
  {
    "path": "LICENSE.txt",
    "chars": 1089,
    "preview": "Copyright (c) 2012-2018 Wout Fierens\nhttps://svgdotjs.github.io/\n\nPermission is hereby granted, free of charge, to any p"
  },
  {
    "path": "README.md",
    "chars": 1740,
    "preview": "# SVG.js\n\n[![Build Status](https://travis-ci.org/svgdotjs/svg.js.svg?branch=master)](https://travis-ci.org/svgdotjs/svg."
  },
  {
    "path": "bench/runner.html",
    "chars": 1628,
    "preview": "<!doctype html>\n<html>\n  <head>\n    <title>SVG.js benchmarker</title>\n    <style>\n      @import url('https://fonts.googl"
  },
  {
    "path": "bench/svg.bench.js",
    "chars": 2004,
    "preview": "/* global Snap */\n\n;(function () {\n  SVG.bench = {\n    // Initalize test store\n    _chain: [],\n    _before: function () "
  },
  {
    "path": "bench/tests/10000-accesses.js",
    "chars": 1009,
    "preview": "SVG.bench.describe(\n  'Access a dom attributes vs dom properties vs object properties',\n  function (bench) {\n    bench.t"
  },
  {
    "path": "bench/tests/10000-boxes.js",
    "chars": 1565,
    "preview": "SVG.bench.describe('Generate 100000 bbox', function (bench) {\n  var rect = bench.draw.rect(100, 100)\n\n  bench.test('usin"
  },
  {
    "path": "bench/tests/10000-circles.js",
    "chars": 1295,
    "preview": "SVG.bench.describe('Generate 10000 circles', function (bench) {\n  bench.test('using SVG.js v2.5.3', function () {\n    fo"
  },
  {
    "path": "bench/tests/10000-each.js",
    "chars": 520,
    "preview": "SVG.bench.describe('each() vs forEach()', function (bench) {\n  // preparation\n  var list = []\n\n  for (var i = 99; i >= 0"
  },
  {
    "path": "bench/tests/10000-pathArray-bbox.js",
    "chars": 17302,
    "preview": "SVG.bench.describe('Generate 10000 pathArrays bbox', function (bench) {\n  var data =\n    'M97.499,75.211l5.652,-4.874c-1"
  },
  {
    "path": "bench/tests/10000-pathArrays.js",
    "chars": 16170,
    "preview": "SVG.bench.describe('Generate 10000 pathArrays', function (bench) {\n  var data =\n    'M97.499,75.211l5.652,-4.874c-1.235,"
  },
  {
    "path": "bench/tests/10000-paths.js",
    "chars": 631,
    "preview": "SVG.bench.describe('Generate 10000 paths', function (bench) {\n  var data =\n    'M 100 200 C 200 100 300  0 400 100 C 500"
  },
  {
    "path": "bench/tests/10000-pointArray-bbox.js",
    "chars": 1336,
    "preview": "SVG.bench.describe('Generate 10000 pathArrays bbox', function (bench) {\n  var data =\n    '209,153 389,107 547,188 482,28"
  },
  {
    "path": "bench/tests/10000-rects.js",
    "chars": 3721,
    "preview": "SVG.bench.describe('Generate 10000 rects', function (bench) {\n  bench.test('using SVG.js v3.0.6', function () {\n    for "
  },
  {
    "path": "bench/tests/10000-textContent.js",
    "chars": 603,
    "preview": "SVG.bench.describe('Change textContent 10000 times', function (bench) {\n  var data =\n    'M 100 200 C 200 100 300  0 400"
  },
  {
    "path": "bench/tests/10000-transform.js",
    "chars": 753,
    "preview": "SVG.bench.describe('Transform 1000000 rects', function (bench) {\n  let parameters = {\n    translate: [20, 30],\n    origi"
  },
  {
    "path": "package.json",
    "chars": 3906,
    "preview": "{\n  \"name\": \"@svgdotjs/svg.js\",\n  \"version\": \"3.2.5\",\n  \"type\": \"module\",\n  \"description\": \"A lightweight library for ma"
  },
  {
    "path": "playgrounds/colors/main.js",
    "chars": 722,
    "preview": "let canvas = SVG('#canvas').group().translate(-150, 230)\n\n// Make a bunch of rectangles\nfunction rectangles(method = 'Vi"
  },
  {
    "path": "playgrounds/colors/style.css",
    "chars": 907,
    "preview": "* {\n  box-sizing: border-box;\n}\n\nhtml {\n  background-color: #fefefe;\n}\n\nbody {\n  margin: 0;\n  width: 100vw;\n  height: 99"
  },
  {
    "path": "playgrounds/matrix/drag.js",
    "chars": 1613,
    "preview": "function reactToDrag(element, onDrag, beforeDrag) {\n  let xStart, yStart\n  let startDrag = (event) => {\n    // Avoid the"
  },
  {
    "path": "playgrounds/matrix/matrix.js",
    "chars": 886,
    "preview": "function print(mat) {\n  let { a, b, c, d } = mat\n  console.log(`\n    a: ${a.toFixed(2)}\n    b: ${b.toFixed(2)}\n    c: ${"
  },
  {
    "path": "playgrounds/matrix/style.css",
    "chars": 907,
    "preview": "* {\n  box-sizing: border-box;\n}\n\nhtml {\n  background-color: #fefefe;\n}\n\nbody {\n  margin: 0;\n  width: 100vw;\n  height: 99"
  },
  {
    "path": "playgrounds/transforms/style.css",
    "chars": 907,
    "preview": "* {\n  box-sizing: border-box;\n}\n\nhtml {\n  background-color: #fefefe;\n}\n\nbody {\n  margin: 0;\n  width: 100vw;\n  height: 99"
  },
  {
    "path": "playgrounds/transforms/transforms.js",
    "chars": 516,
    "preview": "let canvas = SVG('#canvas')\n\n// Make the green rectangle\ncanvas.rect(200, 400).move(200, 400).attr('opacity', 0.3).addCl"
  },
  {
    "path": "playgrounds/webpack.config.js",
    "chars": 555,
    "preview": "var path = require('path')\nmodule.exports = function (env) {\n  let currentTest = path.resolve(__dirname, env)\n  return {"
  },
  {
    "path": "spec/RAFPlugin.js",
    "chars": 1925,
    "preview": "/* globals jasmine */\n/**\n * Jasmine RequestAnimationFrame: a set of helpers for testing functionality\n * that uses requ"
  },
  {
    "path": "spec/SpecRunner.html",
    "chars": 889,
    "preview": "<!doctype html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>SVG.js - Jasmine Spec Runner</title>\n\n    <link\n"
  },
  {
    "path": "spec/SpecRunnerEs6.html",
    "chars": 2227,
    "preview": "<!doctype html>\n<html>\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>SVG.js - Jasmine Spec Runner</title>\n\n    <link\n"
  },
  {
    "path": "spec/checkForAllTests.js",
    "chars": 607,
    "preview": "const glob = require('glob')\nconst path = require('path')\n\nglob('./spec/*/**/*.js', (err, tests) => {\n  if (err) {\n    t"
  },
  {
    "path": "spec/fixtures/fixture.css",
    "chars": 80,
    "preview": "#drawing {\n  width: 500px;\n  height: 500px;\n  position: fixed;\n  z-index: -1;\n}\n"
  },
  {
    "path": "spec/helpers.js",
    "chars": 4213,
    "preview": "import { getWindow } from '../src/utils/window.js'\nimport { svg } from '../src/modules/core/namespaces.js'\n\nfunction tag"
  },
  {
    "path": "spec/runSVGDomTest.js",
    "chars": 401,
    "preview": "/*\n  This file has to be run with esm because node does not understand imports yet:\n  node -r esm ./spec/runSvgdomTest.j"
  },
  {
    "path": "spec/setupBrowser.js",
    "chars": 308,
    "preview": "/* globals beforeEach, afterEach, jasmine */\nimport { buildCanvas, clear } from './helpers.js'\n\njasmine.DEFAULT_TIMEOUT_"
  },
  {
    "path": "spec/setupSVGDom.js",
    "chars": 556,
    "preview": "import './RAFPlugin.js'\nimport { createHTMLWindow } from 'svgdom'\n\n/* globals beforeEach, afterEach, jasmine */\nimport {"
  },
  {
    "path": "spec/spec/animation/Animator.js",
    "chars": 2607,
    "preview": "/* globals describe, expect, it, beforeEach, afterEach, jasmine */\n\nimport { Animator, Queue } from '../../../src/main.j"
  },
  {
    "path": "spec/spec/animation/Controller.js",
    "chars": 12164,
    "preview": "/* globals describe, expect, it, jasmine */\n\nimport { easing, defaults } from '../../../src/main.js'\nimport {\n  Stepper,"
  },
  {
    "path": "spec/spec/animation/Morphable.js",
    "chars": 16046,
    "preview": "/* globals describe, expect, it, jasmine */\n\nimport {\n  Morphable,\n  NonMorphable,\n  ObjectBag,\n  Color,\n  Box,\n  Matrix"
  },
  {
    "path": "spec/spec/animation/Queue.js",
    "chars": 2544,
    "preview": "/* globals describe, expect, it */\n\nimport { Queue } from '../../../src/main.js'\n\ndescribe('Queue.js', function () {\n  d"
  },
  {
    "path": "spec/spec/animation/Runner.js",
    "chars": 70038,
    "preview": "/* globals describe, expect, it, beforeEach, afterEach, spyOn, jasmine */\n\nimport {\n  Runner,\n  defaults,\n  Ease,\n  Cont"
  },
  {
    "path": "spec/spec/animation/Timeline.js",
    "chars": 16848,
    "preview": "/* globals describe, expect, it, beforeEach, afterEach, spyOn, container, jasmine */\n\nimport {\n  Timeline,\n  SVG,\n  Runn"
  },
  {
    "path": "spec/spec/elements/A.js",
    "chars": 3154,
    "preview": "/* globals describe, expect, it, jasmine */\n\nimport { A, G, Rect } from '../../../src/main.js'\n\nconst { any } = jasmine\n"
  },
  {
    "path": "spec/spec/elements/Circle.js",
    "chars": 1818,
    "preview": "/* globals describe, expect, it, beforeEach, spyOn, jasmine */\n\nimport { Circle, G } from '../../../src/main.js'\n\nconst "
  },
  {
    "path": "spec/spec/elements/ClipPath.js",
    "chars": 3006,
    "preview": "/* globals describe, expect, it, spyOn, jasmine, container */\n\nimport { ClipPath, SVG, Container, Rect } from '../../../"
  },
  {
    "path": "spec/spec/elements/Container.js",
    "chars": 3582,
    "preview": "/* globals describe, expect, it, beforeEach, jasmine, container */\n\nimport { Container, create, SVG } from '../../../src"
  },
  {
    "path": "spec/spec/elements/Defs.js",
    "chars": 758,
    "preview": "/* globals describe, expect, it, jasmine */\n\nimport { Defs } from '../../../src/main.js'\n\nconst { any } = jasmine\n\ndescr"
  },
  {
    "path": "spec/spec/elements/Dom.js",
    "chars": 22652,
    "preview": "/* globals describe, expect, it, beforeEach, spyOn, jasmine, container */\n\nimport {\n  SVG,\n  G,\n  Rect,\n  Svg,\n  Dom,\n  "
  },
  {
    "path": "spec/spec/elements/Element.js",
    "chars": 10734,
    "preview": "/* globals describe, expect, it, beforeEach, spyOn, jasmine, container */\n\nimport { Element, create, Rect, G, SVG, Text "
  },
  {
    "path": "spec/spec/elements/Ellipse.js",
    "chars": 2770,
    "preview": "/* globals describe, expect, it, spyOn, jasmine, container */\n\nimport { Ellipse, SVG, G } from '../../../src/main.js'\n\nc"
  },
  {
    "path": "spec/spec/elements/ForeignObject.js",
    "chars": 1594,
    "preview": "/* globals describe, expect, it, jasmine */\n\nimport { makeInstance, ForeignObject } from '../../../src/main.js'\n\nconst {"
  },
  {
    "path": "spec/spec/elements/Fragment.js",
    "chars": 2043,
    "preview": "/* globals describe, expect, it, spyOn, jasmine */\n\nimport { Fragment, Dom } from '../../../src/main.js'\nimport { getWin"
  },
  {
    "path": "spec/spec/elements/G.js",
    "chars": 688,
    "preview": "/* globals describe, expect, it, jasmine, container */\n\nimport { G, SVG } from '../../../src/main.js'\n\nconst { any } = j"
  },
  {
    "path": "spec/spec/elements/Gradient.js",
    "chars": 3364,
    "preview": "/* globals describe, expect, it, spyOn, jasmine, container */\n\nimport { Gradient, SVG, Container } from '../../../src/ma"
  },
  {
    "path": "spec/spec/elements/Image.js",
    "chars": 3949,
    "preview": "/* globals describe, expect, it, jasmine */\n\nimport { Image, Pattern, SVG } from '../../../src/main.js'\nimport { getWind"
  },
  {
    "path": "spec/spec/elements/Line.js",
    "chars": 4274,
    "preview": "/* globals describe, expect, it, beforeEach, spyOn, jasmine, container */\n\nimport { Line, PointArray, SVG, G } from '../"
  },
  {
    "path": "spec/spec/elements/Marker.js",
    "chars": 5295,
    "preview": "/* globals describe, expect, it, beforeEach, jasmine, container */\n\nimport { Marker, SVG, Defs } from '../../../src/main"
  },
  {
    "path": "spec/spec/elements/Mask.js",
    "chars": 2933,
    "preview": "/* globals describe, expect, it, spyOn, jasmine, container */\n\nimport { Mask, SVG, Container, Rect } from '../../../src/"
  },
  {
    "path": "spec/spec/elements/Path.js",
    "chars": 5518,
    "preview": "/* globals describe, expect, beforeEach, it, spyOn, jasmine, container */\n\nimport { Path, SVG, PathArray } from '../../."
  },
  {
    "path": "spec/spec/elements/Pattern.js",
    "chars": 3096,
    "preview": "/* globals describe, expect, it, spyOn, jasmine, container */\n\nimport { Pattern, SVG, Container } from '../../../src/mai"
  },
  {
    "path": "spec/spec/elements/Polygon.js",
    "chars": 1007,
    "preview": "/* globals describe, expect, it, jasmine */\n\nimport { Polygon, G } from '../../../src/main.js'\n\nconst { any } = jasmine\n"
  },
  {
    "path": "spec/spec/elements/Polyline.js",
    "chars": 1038,
    "preview": "/* globals describe, expect, it, jasmine */\n\nimport { Polyline, G } from '../../../src/main.js'\n\nconst { any } = jasmine"
  },
  {
    "path": "spec/spec/elements/Rect.js",
    "chars": 761,
    "preview": "/* globals describe, expect, it, jasmine */\n\nimport { Rect, G } from '../../../src/main.js'\n\nconst { any } = jasmine\n\nde"
  },
  {
    "path": "spec/spec/elements/Shape.js",
    "chars": 441,
    "preview": "/* globals describe, expect, it, jasmine */\n\nimport { Shape, create } from '../../../src/main.js'\n\nconst { any } = jasmi"
  },
  {
    "path": "spec/spec/elements/Stop.js",
    "chars": 2602,
    "preview": "/* globals describe, expect, it, jasmine */\n\nimport { Stop, Gradient } from '../../../src/main.js'\n\nconst { any } = jasm"
  },
  {
    "path": "spec/spec/elements/Style.js",
    "chars": 2780,
    "preview": "/* globals describe, expect, it, jasmine */\n\nimport { Style, G } from '../../../src/main.js'\n\nconst { any } = jasmine\n\nd"
  },
  {
    "path": "spec/spec/elements/Svg.js",
    "chars": 4231,
    "preview": "/* globals describe, expect, it, jasmine, container */\n\nimport { Svg, SVG, Defs } from '../../../src/main.js'\nimport { s"
  },
  {
    "path": "spec/spec/elements/Symbol.js",
    "chars": 705,
    "preview": "/* globals describe, expect, it, jasmine */\n\nimport { Symbol, G } from '../../../src/main.js'\n\nconst { any } = jasmine\n\n"
  },
  {
    "path": "spec/spec/elements/Text.js",
    "chars": 5864,
    "preview": "/* globals describe, expect, it, spyOn jasmine, container */\n\nimport {\n  Text,\n  Number as SVGNumber,\n  SVG,\n  G,\n  Path"
  },
  {
    "path": "spec/spec/elements/TextPath.js",
    "chars": 4812,
    "preview": "/* globals describe, expect, it, beforeEach, jasmine, container */\n\nimport { Text, SVG, TextPath, Path } from '../../../"
  },
  {
    "path": "spec/spec/elements/Tspan.js",
    "chars": 3977,
    "preview": "/* globals describe, expect, it, jasmine, container */\n\nimport { Tspan, Text, Number as SVGNumber, SVG } from '../../../"
  },
  {
    "path": "spec/spec/elements/Use.js",
    "chars": 1157,
    "preview": "/* globals describe, expect, it, jasmine, container */\n\nimport { Use, Rect, SVG } from '../../../src/main.js'\n\nconst { a"
  },
  {
    "path": "spec/spec/modules/core/attr.js",
    "chars": 4300,
    "preview": "/* globals describe, expect, it, beforeEach, spyOn, jasmine */\n\nimport { Element, create, Text, Rect } from '../../../.."
  },
  {
    "path": "spec/spec/modules/core/circled.js",
    "chars": 2737,
    "preview": "/* globals describe, expect, it, beforeEach, spyOn, jasmine, container */\n\nimport { Ellipse, SVG } from '../../../../src"
  },
  {
    "path": "spec/spec/modules/core/containerGeometry.js",
    "chars": 10132,
    "preview": "/* globals describe, expect, it, jasmine, spyOn, container */\n\nimport { Box, create, Element, G, Rect, SVG } from '../.."
  },
  {
    "path": "spec/spec/modules/core/event.js",
    "chars": 7801,
    "preview": "/* globals describe, expect, it, spyOn, jasmine */\nimport {\n  windowEvents,\n  getEvents,\n  getEventTarget,\n  clearEvents"
  },
  {
    "path": "spec/spec/modules/core/gradiented.js",
    "chars": 1242,
    "preview": "/* globals describe, expect, it */\n\nimport { Gradient } from '../../../../src/main.js'\n\ndescribe('gradiented.js', () => "
  },
  {
    "path": "spec/spec/modules/core/parser.js",
    "chars": 860,
    "preview": "/* globals describe, expect, it */\n\nimport parser from '../../../../src/modules/core/parser.js'\nimport { getWindow } fro"
  },
  {
    "path": "spec/spec/modules/core/pointed.js",
    "chars": 1847,
    "preview": "/* globals describe, expect, it, beforeEach, container */\n\nimport { SVG } from '../../../../src/main.js'\n\ndescribe('poin"
  },
  {
    "path": "spec/spec/modules/core/poly.js",
    "chars": 3402,
    "preview": "/* globals describe, expect, beforeEach, it, spyOn, jasmine, container */\n\nimport { Polygon, SVG, PointArray } from '../"
  },
  {
    "path": "spec/spec/modules/core/regex.js",
    "chars": 7393,
    "preview": "/* globals describe, expect, it */\n\nimport { regex } from '../../../../src/main.js'\n\ndescribe('regex.js', () => {\n  desc"
  },
  {
    "path": "spec/spec/modules/core/selector.js",
    "chars": 2110,
    "preview": "/* globals describe, expect, it, container */\n\nimport { find, SVG, G } from '../../../../src/main.js'\nimport { getWindow"
  },
  {
    "path": "spec/spec/modules/core/textable.js",
    "chars": 11559,
    "preview": "/* globals describe, expect, it, beforeEach, spyOn, container */\n\nimport { SVG, Box, Tspan } from '../../../../src/main."
  },
  {
    "path": "spec/spec/modules/optional/arrange.js",
    "chars": 6137,
    "preview": "/* globals describe, expect, it */\n\nimport { G, Line } from '../../../../src/main.js'\n\ndescribe('arrange.js', () => {\n  "
  },
  {
    "path": "spec/spec/modules/optional/class.js",
    "chars": 3011,
    "preview": "/* globals describe, expect, it */\n\nimport { Rect } from '../../../../src/main.js'\n\ndescribe('class.js', () => {\n  descr"
  },
  {
    "path": "spec/spec/modules/optional/css.js",
    "chars": 4842,
    "preview": "/* globals describe, expect, it */\n\nimport { Rect } from '../../../../src/main.js'\n\ndescribe('css.js', () => {\n  describ"
  },
  {
    "path": "spec/spec/modules/optional/data.js",
    "chars": 3990,
    "preview": "/* globals describe, expect, it */\n\nimport { Rect } from '../../../../src/main.js'\n\ndescribe('data.js', () => {\n  descri"
  },
  {
    "path": "spec/spec/modules/optional/memory.js",
    "chars": 3188,
    "preview": "/* globals describe, expect, it */\n\nimport { Rect } from '../../../../src/main.js'\n\ndescribe('memory.js', () => {\n  desc"
  },
  {
    "path": "spec/spec/modules/optional/sugar.js",
    "chars": 14469,
    "preview": "/* globals describe, expect, it, beforeEach, spyOn, container */\n\nimport { Rect, SVG, Matrix, Ellipse, Gradient } from '"
  },
  {
    "path": "spec/spec/modules/optional/transform.js",
    "chars": 5776,
    "preview": "/* globals describe, expect, it, spyOn, container */\n\nimport { Rect, Matrix, SVG } from '../../../../src/main.js'\n\ndescr"
  },
  {
    "path": "spec/spec/types/Base.js",
    "chars": 245,
    "preview": "/* globals describe, expect, it, jasmine */\n\nimport Base from '../../../src/types/Base.js'\n\nconst { any } = jasmine\n\ndes"
  },
  {
    "path": "spec/spec/types/Box.js",
    "chars": 12575,
    "preview": "/* globals describe, expect, it, beforeEach, afterEach, spyOn, jasmine, container */\n\nimport { Box, Matrix, Rect, G, mak"
  },
  {
    "path": "spec/spec/types/Color.js",
    "chars": 14179,
    "preview": "/* globals describe, expect, it, beforeEach, spyOn, jasmine */\n\nimport { Color } from '../../../src/main.js'\n\nconst { an"
  },
  {
    "path": "spec/spec/types/EventTarget.js",
    "chars": 4249,
    "preview": "/* globals describe, expect, it, spyOn, jasmine */\n\nimport { EventTarget } from '../../../src/main.js'\nimport { getWindo"
  },
  {
    "path": "spec/spec/types/List.js",
    "chars": 3523,
    "preview": "/* globals describe, expect, it, jasmine */\n\nimport { List } from '../../../src/main.js'\n\nconst { any, createSpy, object"
  },
  {
    "path": "spec/spec/types/Matrix.js",
    "chars": 18912,
    "preview": "/* globals describe, expect, it, spyOn, jasmine */\n\nimport { Matrix, Rect, SVG } from '../../../src/main.js'\nimport { ge"
  },
  {
    "path": "spec/spec/types/PathArray.js",
    "chars": 3038,
    "preview": "/* globals describe, expect, it, beforeEach */\n\nimport { PathArray, Box } from '../../../src/main.js'\n\ndescribe('PathArr"
  },
  {
    "path": "spec/spec/types/Point.js",
    "chars": 2682,
    "preview": "/* globals describe, expect, it, beforeEach, spyOn */\n\nimport { Point, Rect, Matrix } from '../../../src/main.js'\n\ndescr"
  },
  {
    "path": "spec/spec/types/PointArray.js",
    "chars": 6012,
    "preview": "/* globals describe, expect, it */\n\nimport { PointArray, Matrix, Point } from '../../../src/main.js'\n\ndescribe('PointArr"
  },
  {
    "path": "spec/spec/types/SVGArray.js",
    "chars": 2550,
    "preview": "/* globals describe, expect, it, jasmine */\n\nimport { Array as SVGArray, PointArray, PathArray } from '../../../src/main"
  },
  {
    "path": "spec/spec/types/SVGNumber.js",
    "chars": 6480,
    "preview": "/* globals describe, expect, it, beforeEach, jasmine */\n\nimport { Number as SVGNumber } from '../../../src/main.js'\n\ncon"
  },
  {
    "path": "spec/spec/utils/adopter.js",
    "chars": 8097,
    "preview": "/* globals describe, expect, it, beforeEach, afterEach, jasmine */\n\nimport {\n  create,\n  makeInstance,\n  nodeOrNew,\n  re"
  },
  {
    "path": "spec/spec/utils/methods.js",
    "chars": 860,
    "preview": "/* globals describe, expect, it */\n\nimport {\n  registerMethods,\n  getMethodsFor,\n  getMethodNames\n} from '../../../src/u"
  },
  {
    "path": "spec/spec/utils/pathParser.js",
    "chars": 4878,
    "preview": "/* globals describe expect it */\n\nimport { pathParser } from '../../../src/utils/pathParser.js'\n\ndescribe('pathParser.js"
  },
  {
    "path": "spec/spec/utils/utils.js",
    "chars": 5107,
    "preview": "/* globals describe, expect, it, beforeEach, jasmine */\n\nimport {\n  map,\n  filter,\n  radians,\n  degrees,\n  unCamelCase,\n"
  },
  {
    "path": "spec/spec/utils/window.js",
    "chars": 1136,
    "preview": "/* globals describe, expect, it */\n\nimport {\n  registerWindow,\n  globals,\n  withWindow,\n  getWindow,\n  saveWindow,\n  res"
  },
  {
    "path": "src/animation/Animator.js",
    "chars": 2840,
    "preview": "import { globals } from '../utils/window.js'\nimport Queue from './Queue.js'\n\nconst Animator = {\n  nextDraw: null,\n  fram"
  },
  {
    "path": "src/animation/Controller.js",
    "chars": 5200,
    "preview": "import { timeline } from '../modules/core/defaults.js'\nimport { extend } from '../utils/adopter.js'\n\n/***\nBase Class\n==="
  },
  {
    "path": "src/animation/Morphable.js",
    "chars": 6766,
    "preview": "import { Ease } from './Controller.js'\nimport {\n  delimiter,\n  numberAndUnit,\n  isPathLetter\n} from '../modules/core/reg"
  },
  {
    "path": "src/animation/Queue.js",
    "chars": 1442,
    "preview": "export default class Queue {\n  constructor() {\n    this._first = null\n    this._last = null\n  }\n\n  // Shows us the first"
  },
  {
    "path": "src/animation/Runner.js",
    "chars": 28934,
    "preview": "import { Controller, Ease, Stepper } from './Controller.js'\nimport { extend, register } from '../utils/adopter.js'\nimpor"
  },
  {
    "path": "src/animation/Timeline.js",
    "chars": 9652,
    "preview": "import { globals } from '../utils/window.js'\nimport { registerMethods } from '../utils/methods.js'\nimport Animator from "
  },
  {
    "path": "src/elements/A.js",
    "chars": 1584,
    "preview": "import {\n  nodeOrNew,\n  register,\n  wrapWithAttrCheck,\n  extend\n} from '../utils/adopter.js'\nimport { registerMethods } "
  },
  {
    "path": "src/elements/Circle.js",
    "chars": 945,
    "preview": "import { cx, cy, height, width, x, y } from '../modules/core/circled.js'\nimport {\n  extend,\n  nodeOrNew,\n  register,\n  w"
  },
  {
    "path": "src/elements/ClipPath.js",
    "chars": 1357,
    "preview": "import { nodeOrNew, register, wrapWithAttrCheck } from '../utils/adopter.js'\nimport { registerMethods } from '../utils/m"
  },
  {
    "path": "src/elements/Container.js",
    "chars": 687,
    "preview": "import { register } from '../utils/adopter.js'\nimport Element from './Element.js'\n\nexport default class Container extend"
  },
  {
    "path": "src/elements/Defs.js",
    "chars": 322,
    "preview": "import { nodeOrNew, register } from '../utils/adopter.js'\nimport Container from './Container.js'\n\nexport default class D"
  },
  {
    "path": "src/elements/Dom.js",
    "chars": 8192,
    "preview": "import {\n  adopt,\n  assignNewId,\n  eid,\n  extend,\n  makeInstance,\n  create,\n  register\n} from '../utils/adopter.js'\nimpo"
  },
  {
    "path": "src/elements/Element.js",
    "chars": 3852,
    "preview": "import { bbox, rbox, inside } from '../types/Box.js'\nimport { ctm, screenCTM } from '../types/Matrix.js'\nimport {\n  exte"
  },
  {
    "path": "src/elements/Ellipse.js",
    "chars": 902,
    "preview": "import {\n  extend,\n  nodeOrNew,\n  register,\n  wrapWithAttrCheck\n} from '../utils/adopter.js'\nimport { proportionalSize }"
  },
  {
    "path": "src/elements/ForeignObject.js",
    "chars": 530,
    "preview": "import { nodeOrNew, register, wrapWithAttrCheck } from '../utils/adopter.js'\nimport { registerMethods } from '../utils/m"
  },
  {
    "path": "src/elements/Fragment.js",
    "chars": 892,
    "preview": "import Dom from './Dom.js'\nimport { globals } from '../utils/window.js'\nimport { register, create } from '../utils/adopt"
  },
  {
    "path": "src/elements/G.js",
    "chars": 585,
    "preview": "import {\n  nodeOrNew,\n  register,\n  wrapWithAttrCheck,\n  extend\n} from '../utils/adopter.js'\nimport { registerMethods } "
  },
  {
    "path": "src/elements/Gradient.js",
    "chars": 1503,
    "preview": "import {\n  extend,\n  nodeOrNew,\n  register,\n  wrapWithAttrCheck\n} from '../utils/adopter.js'\nimport { registerMethods } "
  },
  {
    "path": "src/elements/Image.js",
    "chars": 2077,
    "preview": "import { isImage } from '../modules/core/regex.js'\nimport { nodeOrNew, register, wrapWithAttrCheck } from '../utils/adop"
  },
  {
    "path": "src/elements/Line.js",
    "chars": 1639,
    "preview": "import {\n  extend,\n  nodeOrNew,\n  register,\n  wrapWithAttrCheck\n} from '../utils/adopter.js'\nimport { proportionalSize }"
  },
  {
    "path": "src/elements/Marker.js",
    "chars": 1973,
    "preview": "import { nodeOrNew, register, wrapWithAttrCheck } from '../utils/adopter.js'\nimport { registerMethods } from '../utils/m"
  },
  {
    "path": "src/elements/Mask.js",
    "chars": 1271,
    "preview": "import { nodeOrNew, register, wrapWithAttrCheck } from '../utils/adopter.js'\nimport { registerMethods } from '../utils/m"
  },
  {
    "path": "src/elements/Path.js",
    "chars": 1968,
    "preview": "import { nodeOrNew, register, wrapWithAttrCheck } from '../utils/adopter.js'\nimport { proportionalSize } from '../utils/"
  },
  {
    "path": "src/elements/Pattern.js",
    "chars": 1480,
    "preview": "import { nodeOrNew, register, wrapWithAttrCheck } from '../utils/adopter.js'\nimport { registerMethods } from '../utils/m"
  },
  {
    "path": "src/elements/Polygon.js",
    "chars": 804,
    "preview": "import {\n  extend,\n  nodeOrNew,\n  register,\n  wrapWithAttrCheck\n} from '../utils/adopter.js'\nimport { registerMethods } "
  },
  {
    "path": "src/elements/Polyline.js",
    "chars": 812,
    "preview": "import {\n  extend,\n  nodeOrNew,\n  register,\n  wrapWithAttrCheck\n} from '../utils/adopter.js'\nimport { registerMethods } "
  },
  {
    "path": "src/elements/Rect.js",
    "chars": 614,
    "preview": "import {\n  extend,\n  nodeOrNew,\n  register,\n  wrapWithAttrCheck\n} from '../utils/adopter.js'\nimport { registerMethods } "
  },
  {
    "path": "src/elements/Shape.js",
    "chars": 155,
    "preview": "import { register } from '../utils/adopter.js'\nimport Element from './Element.js'\n\nexport default class Shape extends El"
  },
  {
    "path": "src/elements/Stop.js",
    "chars": 974,
    "preview": "import { nodeOrNew, register } from '../utils/adopter.js'\nimport Element from './Element.js'\nimport SVGNumber from '../t"
  },
  {
    "path": "src/elements/Style.js",
    "chars": 1073,
    "preview": "import { nodeOrNew, register } from '../utils/adopter.js'\nimport { registerMethods } from '../utils/methods.js'\nimport {"
  },
  {
    "path": "src/elements/Svg.js",
    "chars": 1562,
    "preview": "import {\n  adopt,\n  nodeOrNew,\n  register,\n  wrapWithAttrCheck\n} from '../utils/adopter.js'\nimport { svg, xlink, xmlns }"
  },
  {
    "path": "src/elements/Symbol.js",
    "chars": 482,
    "preview": "import { nodeOrNew, register, wrapWithAttrCheck } from '../utils/adopter.js'\nimport { registerMethods } from '../utils/m"
  },
  {
    "path": "src/elements/Text.js",
    "chars": 3809,
    "preview": "import {\n  adopt,\n  extend,\n  nodeOrNew,\n  register,\n  wrapWithAttrCheck\n} from '../utils/adopter.js'\nimport { registerM"
  },
  {
    "path": "src/elements/TextPath.js",
    "chars": 2664,
    "preview": "import { nodeOrNew, register, wrapWithAttrCheck } from '../utils/adopter.js'\nimport { registerMethods } from '../utils/m"
  },
  {
    "path": "src/elements/Tspan.js",
    "chars": 1991,
    "preview": "import {\n  extend,\n  nodeOrNew,\n  register,\n  wrapWithAttrCheck\n} from '../utils/adopter.js'\nimport { globals } from '.."
  },
  {
    "path": "src/elements/Use.js",
    "chars": 696,
    "preview": "import { nodeOrNew, register, wrapWithAttrCheck } from '../utils/adopter.js'\nimport { registerMethods } from '../utils/m"
  },
  {
    "path": "src/main.js",
    "chars": 5992,
    "preview": "/* Optional Modules */\nimport './modules/optional/arrange.js'\nimport './modules/optional/class.js'\nimport './modules/opt"
  },
  {
    "path": "src/modules/core/attr.js",
    "chars": 2601,
    "preview": "import { attrs as defaults } from './defaults.js'\nimport { isNumber } from './regex.js'\nimport Color from '../../types/C"
  },
  {
    "path": "src/modules/core/circled.js",
    "chars": 888,
    "preview": "import SVGNumber from '../../types/SVGNumber.js'\n\n// Radius x value\nexport function rx(rx) {\n  return this.attr('rx', rx"
  },
  {
    "path": "src/modules/core/containerGeometry.js",
    "chars": 2640,
    "preview": "import Matrix from '../../types/Matrix.js'\nimport Point from '../../types/Point.js'\nimport Box from '../../types/Box.js'"
  },
  {
    "path": "src/modules/core/defaults.js",
    "chars": 612,
    "preview": "export function noop() {}\n\n// Default animation values\nexport const timeline = {\n  duration: 400,\n  ease: '>',\n  delay: "
  },
  {
    "path": "src/modules/core/event.js",
    "chars": 3664,
    "preview": "import { delimiter } from './regex.js'\nimport { makeInstance } from '../../utils/adopter.js'\nimport { globals } from '.."
  },
  {
    "path": "src/modules/core/gradiented.js",
    "chars": 485,
    "preview": "import SVGNumber from '../../types/SVGNumber.js'\n\nexport function from(x, y) {\n  return (this._element || this).type ==="
  },
  {
    "path": "src/modules/core/namespaces.js",
    "chars": 226,
    "preview": "// Default namespaces\nexport const svg = 'http://www.w3.org/2000/svg'\nexport const html = 'http://www.w3.org/1999/xhtml'"
  },
  {
    "path": "src/modules/core/parser.js",
    "chars": 721,
    "preview": "import { globals } from '../../utils/window.js'\nimport { makeInstance } from '../../utils/adopter.js'\n\nexport default fu"
  },
  {
    "path": "src/modules/core/pointed.js",
    "chars": 642,
    "preview": "import PointArray from '../../types/PointArray.js'\n\nexport const MorphArray = PointArray\n\n// Move by left top corner ove"
  },
  {
    "path": "src/modules/core/poly.js",
    "chars": 832,
    "preview": "import { proportionalSize } from '../../utils/utils.js'\nimport PointArray from '../../types/PointArray.js'\n\n// Get array"
  },
  {
    "path": "src/modules/core/regex.js",
    "chars": 945,
    "preview": "// Parse unit value\nexport const numberAndUnit =\n  /^([+-]?(\\d+(\\.\\d*)?|\\.\\d+)(e[+-]?\\d+)?)([a-z%]*)$/i\n\n// Parse hex va"
  },
  {
    "path": "src/modules/core/selector.js",
    "chars": 539,
    "preview": "import { adopt } from '../../utils/adopter.js'\nimport { globals } from '../../utils/window.js'\nimport { map } from '../."
  },
  {
    "path": "src/modules/core/textable.js",
    "chars": 1564,
    "preview": "import { globals } from '../../utils/window.js'\n\n// Create plain text node\nexport function plain(text) {\n  // clear if b"
  },
  {
    "path": "src/modules/optional/arrange.js",
    "chars": 2125,
    "preview": "import { makeInstance } from '../../utils/adopter.js'\nimport { registerMethods } from '../../utils/methods.js'\n\n// Get a"
  },
  {
    "path": "src/modules/optional/class.js",
    "chars": 1126,
    "preview": "import { delimiter } from '../core/regex.js'\nimport { registerMethods } from '../../utils/methods.js'\n\n// Return array o"
  },
  {
    "path": "src/modules/optional/css.js",
    "chars": 1678,
    "preview": "import { isBlank } from '../core/regex.js'\nimport { registerMethods } from '../../utils/methods.js'\n\n// Dynamic style ge"
  },
  {
    "path": "src/modules/optional/data.js",
    "chars": 1058,
    "preview": "import { registerMethods } from '../../utils/methods.js'\nimport { filter, map } from '../../utils/utils.js'\n\n// Store da"
  },
  {
    "path": "src/modules/optional/memory.js",
    "chars": 991,
    "preview": "import { registerMethods } from '../../utils/methods.js'\n\n// Remember arbitrary data\nexport function remember(k, v) {\n  "
  },
  {
    "path": "src/modules/optional/sugar.js",
    "chars": 4665,
    "preview": "import { registerMethods } from '../../utils/methods.js'\nimport Color from '../../types/Color.js'\nimport Element from '."
  },
  {
    "path": "src/modules/optional/transform.js",
    "chars": 2345,
    "preview": "import { getOrigin, isDescriptive } from '../../utils/utils.js'\nimport { delimiter, transforms } from '../core/regex.js'"
  },
  {
    "path": "src/polyfills/children.js",
    "chars": 222,
    "preview": "import { filter } from '../utils/utils.js'\n\n// IE11: children does not work for svg nodes\nexport default function childr"
  },
  {
    "path": "src/polyfills/innerHTML.js",
    "chars": 3139,
    "preview": ";(function () {\n  try {\n    if (SVGElement.prototype.innerHTML) return\n  } catch (e) {\n    return\n  }\n\n  const serialize"
  },
  {
    "path": "src/svg.js",
    "chars": 240,
    "preview": "import * as svgMembers from './main.js'\nimport { makeInstance } from './utils/adopter.js'\n\n// The main wrapping element\n"
  },
  {
    "path": "src/types/Base.js",
    "chars": 268,
    "preview": "export default class Base {\n  // constructor (node/*, {extensions = []} */) {\n  //   // this.tags = []\n  //   //\n  //   "
  },
  {
    "path": "src/types/Box.js",
    "chars": 7553,
    "preview": "import { delimiter } from '../modules/core/regex.js'\nimport { globals } from '../utils/window.js'\nimport { register } fr"
  },
  {
    "path": "src/types/Color.js",
    "chars": 13127,
    "preview": "import { hex, isHex, isRgb, rgb, whitespace } from '../modules/core/regex.js'\n\nfunction sixDigitHex(hex) {\n  return hex."
  },
  {
    "path": "src/types/EventTarget.js",
    "chars": 1117,
    "preview": "import { dispatch, off, on } from '../modules/core/event.js'\nimport { register } from '../utils/adopter.js'\nimport Base "
  },
  {
    "path": "src/types/List.js",
    "chars": 1515,
    "preview": "import { extend } from '../utils/adopter.js'\n// import { subClassArray } from './ArrayPolyfill.js'\n\nclass List extends A"
  },
  {
    "path": "src/types/Matrix.js",
    "chars": 13097,
    "preview": "import { delimiter } from '../modules/core/regex.js'\nimport { radians } from '../utils/utils.js'\nimport { register } fro"
  },
  {
    "path": "src/types/PathArray.js",
    "chars": 3944,
    "preview": "import SVGArray from './SVGArray.js'\nimport parser from '../modules/core/parser.js'\nimport Box from './Box.js'\nimport { "
  },
  {
    "path": "src/types/Point.js",
    "chars": 1051,
    "preview": "import Matrix from './Matrix.js'\n\nexport default class Point {\n  // Initialize\n  constructor(...args) {\n    this.init(.."
  },
  {
    "path": "src/types/PointArray.js",
    "chars": 2924,
    "preview": "import { delimiter } from '../modules/core/regex.js'\nimport SVGArray from './SVGArray.js'\nimport Box from './Box.js'\nimp"
  },
  {
    "path": "src/types/SVGArray.js",
    "chars": 937,
    "preview": "import { delimiter } from '../modules/core/regex.js'\n\nexport default class SVGArray extends Array {\n  constructor(...arg"
  },
  {
    "path": "src/types/SVGNumber.js",
    "chars": 2161,
    "preview": "import { numberAndUnit } from '../modules/core/regex.js'\n\n// Module for unit conversions\nexport default class SVGNumber "
  },
  {
    "path": "src/utils/adopter.js",
    "chars": 3546,
    "preview": "import { addMethodNames } from './methods.js'\nimport { capitalize } from './utils.js'\nimport { svg } from '../modules/co"
  },
  {
    "path": "src/utils/methods.js",
    "chars": 636,
    "preview": "const methods = {}\nconst names = []\n\nexport function registerMethods(name, m) {\n  if (Array.isArray(name)) {\n    for (co"
  },
  {
    "path": "src/utils/pathParser.js",
    "chars": 5433,
    "preview": "import { isPathLetter } from '../modules/core/regex.js'\nimport Point from '../types/Point.js'\n\nconst segmentParameters ="
  },
  {
    "path": "src/utils/utils.js",
    "chars": 3270,
    "preview": "// Map function\nexport function map(array, block) {\n  let i\n  const il = array.length\n  const result = []\n\n  for (i = 0;"
  },
  {
    "path": "src/utils/window.js",
    "chars": 665,
    "preview": "export const globals = {\n  window: typeof window === 'undefined' ? null : window,\n  document: typeof document === 'undef"
  },
  {
    "path": "svg.js.d.ts",
    "chars": 53566,
    "preview": "// Type definitions for @svgdotjs version 3.x\n// Project: @svgdotjs/svg.js\n\n// trick to keep reference to Array build-in"
  },
  {
    "path": "tsconfig.json",
    "chars": 3,
    "preview": "{}\n"
  }
]

About this extraction

This page contains the full source code of the svgdotjs/svg.js GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 200 files (792.6 KB), approximately 232.7k tokens, and a symbol index with 762 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.

Copied to clipboard!