├── .npmignore
├── .babelrc
├── src
├── index.js
├── capability.js
├── util.js
├── stage.js
└── transition.js
├── test
├── util
│ ├── css-hooks.css
│ └── util.js
├── timeout.spec.js
├── stagger.spec.js
├── transition.spec.js
└── karma.conf.js
├── .eslintrc.js
├── .travis.yml
├── .gitignore
├── docs
├── main.js
├── components
│ ├── AppHeader.san
│ ├── Nav.san
│ ├── Jumbotron.san
│ ├── GetStart.md
│ ├── API.md
│ └── Examples.san
├── pages
│ └── App.san
├── template.html
└── markdown.styl
├── LICENSE
├── README.md
└── package.json
/.npmignore:
--------------------------------------------------------------------------------
1 | docs
2 | coverage
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["env"]
3 | }
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | export {default as transition} from './transition.js'
2 |
--------------------------------------------------------------------------------
/test/util/css-hooks.css:
--------------------------------------------------------------------------------
1 | .fade-enter, .fade-leave {
2 | transition: all 1s;
3 | }
4 |
5 | .fade-enter, .fade-before-leave {
6 | opacity: 1;
7 | }
8 | .fade-before-enter, .fade-leave {
9 | opacity: 0;
10 | }
--------------------------------------------------------------------------------
/test/util/util.js:
--------------------------------------------------------------------------------
1 | function nextFrame (callback) {
2 | return requestAnimationFrame(callback)
3 | }
4 |
5 | function afterNextFrame(callback) {
6 | return nextFrame(function () {
7 | return nextFrame(callback)
8 | })
9 | }
10 |
11 | function isClassNameExists (el, name) {
12 | return (new RegExp(name)).test(el.className)
13 | }
14 |
--------------------------------------------------------------------------------
/test/timeout.spec.js:
--------------------------------------------------------------------------------
1 | import {getTimeout, addHook} from '@/util.js'
2 |
3 | describe('Compute timeout', function () {
4 | it ('transition timeout', function () {
5 | var $dom = document.createElement('div')
6 | document.body.appendChild($dom)
7 | addHook($dom, 'fade-enter')
8 | expect(getTimeout($dom)).toBe(1e3)
9 | document.body.removeChild($dom)
10 | })
11 | })
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | parser: 'babel-eslint',
4 | parserOptions: {
5 | sourceType: 'module'
6 | },
7 | // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style
8 | extends: 'standard',
9 | plugins: [
10 | 'html'
11 | ],
12 | env: {
13 | browser: true
14 | },
15 | // add your custom rules here
16 | 'rules': {
17 | // allow paren-less arrow functions
18 | 'arrow-parens': 0,
19 | // allow async-await
20 | 'generator-star-spacing': 0,
21 | // allow debugger during development
22 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "8"
4 | addons:
5 | apt:
6 | packages:
7 | - xvfb
8 | install:
9 | - export DISPLAY=:99.0
10 | - export CHROME_BIN=chromium-browser
11 | - Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
12 | - npm install
13 | before_script:
14 | - npm run build
15 | script:
16 | - npm run lint
17 | - npm test
18 | - npm run codecov
19 | - npm run build:docs
20 | branches:
21 | only: master
22 | after_script:
23 | - cd docs/dist
24 | - git init
25 | - git config user.name "Dafrok"
26 | - git config user.email "o.o@mug.dog"
27 | - git add .
28 | - git commit -m "Travis build docs"
29 | - git push --force --quiet "https://${GITHUB_TOKEN}@github.com/ecomfe/san-transition.git" master:gh-pages
30 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 |
6 | # Runtime data
7 | pids
8 | *.pid
9 | *.seed
10 |
11 | # Directory for instrumented libs generated by jscoverage/JSCover
12 | lib-cov
13 |
14 | # Coverage directory used by tools like istanbul
15 | coverage
16 |
17 | # nyc test coverage
18 | .nyc_output
19 |
20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
21 | .grunt
22 |
23 | # node-waf configuration
24 | .lock-wscript
25 |
26 | # Compiled binary addons (http://nodejs.org/api/addons.html)
27 | build/Release
28 |
29 | # Dependency directories
30 | node_modules
31 | jspm_packages
32 |
33 | # Optional npm cache directory
34 | .npm
35 |
36 | # Optional REPL history
37 | .node_repl_history
38 |
39 | docs/dist
40 | dist
--------------------------------------------------------------------------------
/docs/main.js:
--------------------------------------------------------------------------------
1 | import App from './pages/App.san'
2 | import Jumbotron from './components/Jumbotron.san'
3 | import Nav from './components/Nav.san'
4 |
5 | import 'prismjs/themes/prism.css'
6 | import 'normalize.css'
7 | import './markdown.styl'
8 |
9 | const jumbotron = new Jumbotron()
10 | const nav = new Nav()
11 | const app = new App()
12 | jumbotron.attach(document.body)
13 | nav.attach(document.body)
14 | app.attach(document.body)
15 |
16 | // const $bodyEl = document.createElement('main')
17 | // document.body.appendChild($bodyEl)
18 | // const $body = 'main'
19 |
20 | // router.add({
21 | // rule: '/',
22 | // Component: App,
23 | // target: $body
24 | // })
25 |
26 | // router.start()
27 |
28 | // router.listen(e => {
29 | // san.nextTick(() => {
30 | // Prism.highlightAll()
31 | // })
32 | // })
33 |
--------------------------------------------------------------------------------
/docs/components/AppHeader.san:
--------------------------------------------------------------------------------
1 |
2 | header.app-header
3 | a(href="https://github.com/dafrok/san-transition")
4 | h1
5 | a(href="#")
6 | img(src="https://camo.githubusercontent.com/a290f602d8248dd069fe4fc9eb7dfec86014183a/68747470733a2f2f62616964752e6769746875622e696f2f73616e2f696d672f6c6f676f2d636f6c6f7266756c2e737667" class="logo")
7 | span San Transition
8 | navigator
9 |
10 |
11 |
20 |
21 |
33 |
--------------------------------------------------------------------------------
/src/capability.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @file Runtime capability testing
3 | */
4 |
5 | const capability = ({
6 | raf: global.requestAnimationFrame,
7 | getComputedStyle: global.getComputedStyle,
8 | classList: document.createElement('a').classList
9 | })
10 |
11 | /* istanbul ignore if */
12 | if (!capability.getComputedStyle) {
13 | console.warn('`san-transition` will not to work because `getComputedStyle` API or polyfill is required.')
14 | }
15 |
16 | /* istanbul ignore if */
17 | if (!capability.raf) {
18 | console.warn('`san-transition` will not to work because `requestAnimationFrame` API or polyfill is required.')
19 | }
20 |
21 | /* istanbul ignore if */
22 | if (!capability.classList) {
23 | console.warn('`san-transition` will not to work because `Element.prototype.classList` API or polyfill is required.')
24 | }
25 |
26 | export default capability.raf && capability.classList
27 |
--------------------------------------------------------------------------------
/src/util.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @file Util functions
3 | */
4 |
5 | const getTime = (duration, delay) => Math.max.apply(this, duration.map((str, i) => getFloat(str) + parseFloat(delay[i])))
6 |
7 | const getFloat = str => (parseFloat(str) || 0) * 1000
8 |
9 | export const getTimeout = el => {
10 | const style = getComputedStyle(el)
11 | const transDuration = style.transitionDuration.split(',')
12 | const transDelay = style.transitionDelay.split(',')
13 | const aniDuration = style.animationDuration.split(',')
14 | const aniDelay = style.animationDelay.split(',')
15 | return Math.max(getTime(transDuration, transDelay), getTime(aniDuration, aniDelay))
16 | }
17 |
18 | export const afterNextFrame = fn => requestAnimationFrame(() => requestAnimationFrame(fn))
19 |
20 | export const addHook = (el, hook) => el.classList.add(hook)
21 | export const removeHook = (el, hook) => el.classList.remove(hook)
22 |
--------------------------------------------------------------------------------
/src/stage.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @file Staged transition handler
3 | */
4 |
5 | import asap from 'asap'
6 | import { afterNextFrame } from './util'
7 |
8 | const stacks = {}
9 | export default function (el, stagger, transitionHandler) {
10 | if (stagger) {
11 | const parentEl = el.parentElement
12 | if (!parentEl) {
13 | console.warn('Transition with stagger needs a parent element.')
14 | return transitionHandler()
15 | }
16 | if (!parentEl.id) {
17 | parentEl.id = `__san_transition_${Date.parse(new Date())}`
18 | }
19 | const parentId = parentEl.id
20 | stacks[parentId] = stacks[parentId] || []
21 | stacks[parentId].push(el.id)
22 | asap(() => { stacks[parentId] = [] })
23 | ;(step => setTimeout(() => afterNextFrame(transitionHandler), stagger * step))(stacks[parentId].length - 1)
24 | } else {
25 | afterNextFrame(transitionHandler)
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/docs/components/Nav.san:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
20 |
21 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 马金花儿
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/docs/components/Jumbotron.san:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # San Transition
2 |
3 | Append transition effects for elements in [san](//github.com/ecomfe/san) components.
4 |
5 | [](https://travis-ci.org/ecomfe/san-transition)
6 | [](https://img.shields.io/npm/v/san-transition.svg)
7 | [](https://codecov.io/gh/ecomfe/san-transition)
8 | []()
9 |
10 | ## Download
11 |
12 | - [NPM](https://www.npmjs.com)
13 | ```
14 | $ npm i san-transition
15 | ```
16 |
17 | - [CDN](https://www.npmjs.com/package/san-transition)
18 | ```html
19 |
20 | ```
21 |
22 | ## Documentation
23 |
24 | - [Home](https://ecomfe.github.io/san-transition)
25 | - [Get Start](https://ecomfe.github.io/san-transition#start)
26 | - [API](https://ecomfe.github.io/san-transition#api)
27 | - [Examples](https://ecomfe.github.io/san-transition#examples)
28 |
29 | ## License
30 |
31 | [MIT License](https://github.com/ecomfe/san-transition/blob/9ed0ec3e4ec1549d4e0b47c4f0ea63f61394b6ec/LICENSE)
32 |
--------------------------------------------------------------------------------
/docs/components/GetStart.md:
--------------------------------------------------------------------------------
1 | ## Get Start
2 |
3 | ### Installation
4 |
5 | #### NPM
6 |
7 | ```bash
8 | $ npm install --save san-transition
9 | ```
10 |
11 | #### CDN
12 |
13 | ```html
14 |
15 | ```
16 |
17 | ### Usage
18 |
19 | #### JavaScript
20 |
21 | ```javascript
22 | import san from 'san'
23 | import {transition} from 'san-transition'
24 |
25 | // normal transition
26 | const ChildTransition = san.defineComponent({
27 | template: `
28 |
Child elements with transition effects.
29 |
`,
30 | transition
31 | })
32 |
33 | // a list of tracked elements
34 | const ListTransition = san.defineComponent({
35 | template: `
36 | - Listed element with transition effects.
37 |
`,
38 | initData () {
39 | return {
40 | list: [1, 2, 3, 4, 5]
41 | }
42 | },
43 | transition
44 | })
45 | ```
46 |
47 | #### CSS
48 |
49 | ```css
50 | .slide-enter, .slide-leave {
51 | transition: all .5s;
52 | }
53 | .slide-enter, .slide-before-leave {
54 | opacity: 1;
55 | transform: translate(0, 0);
56 | }
57 | .slide-before-enter, .slide-leave {
58 | opacity: 0;
59 | transform: translate(100px, 0);
60 | }
61 | ```
--------------------------------------------------------------------------------
/docs/pages/App.san:
--------------------------------------------------------------------------------
1 |
2 | section.page
3 | section#start
4 | article.markdown-body
5 | include:markdown-it(html) ../components/GetStart.md
6 | section#api
7 | article.markdown-body
8 | include:markdown-it(html) ../components/API.md
9 | section#examples
10 | examples
11 |
12 |
13 |
45 |
46 |
56 |
--------------------------------------------------------------------------------
/docs/components/API.md:
--------------------------------------------------------------------------------
1 | ## API
2 |
3 | ### Functions
4 |
5 | #### **transition**
6 |
7 | To generate a transition object with properties `enter` and `leave` hooks.
8 |
9 | - Arguments
10 | - **name** {string} Declare a hook name as the prefix of the CSS hooks.
11 | - **stagger** {number} Staged transition interval.
12 | - Import
13 | ```javascript
14 | // In ES6 modules
15 | import {transition} from 'san-transition'
16 |
17 | // In CommonJS
18 | var transition = require('san-transition').transition
19 |
20 | // In browser runtime
21 | var transition = sanTransition.transition
22 | ```
23 | - Usage
24 | ```javascript
25 | // To generate a transtion object with named hooks
26 | transition('foo')
27 |
28 | // To generate a transtion object with default hooks
29 | // the same as `transition('san')`
30 | transition()
31 | ```
32 |
33 | ### CSS Hooks
34 |
35 | `{name}` is the name which is declared by `san-transition`.
36 |
37 | - **{name}-before-enter**: Applies when the component attaches DOM tree and removes in the next frame immediately.
38 | - **{name}-before-leave**: Applies when the component will dispose.
39 | - **{name}-enter**: Applies between the next frame of ***before-enter*** hook deactives and its transition ends.
40 | - **{name}-leave**: Applies between the next frame of ***before-leave*** hook deactives and its transition ends.
41 |
--------------------------------------------------------------------------------
/src/transition.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @file Transition object generator
3 | */
4 |
5 | import { getTimeout, addHook, removeHook } from './util'
6 | import stage from './stage'
7 | import capability from './capability'
8 |
9 | export default (name = 'san', stagger = 0) => {
10 | const hooks = {
11 | beforeEnter: `${name}-before-enter`,
12 | enter: `${name}-enter`,
13 | beforeLeave: `${name}-before-leave`,
14 | leave: `${name}-leave`
15 | }
16 | return {
17 | enter (el, done) {
18 | /* istanbul ignore if */
19 | if (!capability) {
20 | return done()
21 | }
22 | addHook(el, hooks.beforeEnter)
23 | const transitionHandler = () => {
24 | removeHook(el, hooks.beforeEnter)
25 | addHook(el, hooks.enter)
26 | setTimeout(() => {
27 | removeHook(el, hooks.enter)
28 | done()
29 | }, getTimeout(el))
30 | }
31 | stage(el, stagger, transitionHandler)
32 | },
33 | leave (el, done) {
34 | /* istanbul ignore if */
35 | if (!capability) {
36 | return done()
37 | }
38 | addHook(el, hooks.beforeLeave)
39 | const transitionHandler = () => {
40 | removeHook(el, hooks.beforeLeave)
41 | addHook(el, hooks.leave)
42 | setTimeout(done, getTimeout(el))
43 | }
44 | stage(el, stagger, transitionHandler)
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/test/stagger.spec.js:
--------------------------------------------------------------------------------
1 | import stage from '@/stage'
2 |
3 | describe('Staged transition', function () {
4 |
5 | it ('normal transition', function (done) {
6 | var $item1 = document.createElement('div')
7 | var $item2 = document.createElement('div')
8 | document.body.appendChild($item1)
9 | document.body.appendChild($item2)
10 | var count = 0
11 | function transitionHandler () {
12 | return count++
13 | }
14 |
15 | stage($item1, 300, transitionHandler)
16 | stage($item2, 300, transitionHandler)
17 |
18 | nextFrame(() => afterNextFrame(() => {
19 | setTimeout(() => {
20 | expect(count).toBe(1)
21 | }, 0)
22 | setTimeout(() => {
23 | expect(count).toBe(2)
24 | document.body.removeChild($item1)
25 | document.body.removeChild($item2)
26 | done()
27 | }, 300)
28 | }))
29 | })
30 |
31 | it ('without stagger', function (done) {
32 | var isDone = false
33 | function transitionHandler () {
34 | isDone = true
35 | }
36 | var $dom = document.createElement('div')
37 | stage($dom, 0, transitionHandler)
38 | nextFrame(() => afterNextFrame(() => {
39 | expect(isDone).toBe(true)
40 | done()
41 | }))
42 | })
43 |
44 | it ('without parent element', function () {
45 | var isDone = false
46 | function transitionHandler () {
47 | isDone = true
48 | }
49 | var $dom = document.createElement('div')
50 | stage($dom, 100, transitionHandler)
51 | expect(isDone).toBe(true)
52 | })
53 | })
--------------------------------------------------------------------------------
/docs/template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | san-transition
7 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/docs/components/Examples.san:
--------------------------------------------------------------------------------
1 |
2 | article.markdown-body
3 | h2 Examples
4 | h3 Single element with transition effects
5 | div.preview
6 | button(on-click="toggle") CLICK TO TOGGLE
7 | p(s-if="active" s-transition="transition('example')") Hello, san-transition!
8 | h3 Listed elements with transition effects
9 | div.preview
10 | input(value="{= query =}" placeholder="Input Keywords")
11 | ul
12 | li(s-transition="transition('example', 300)" s-for="item in filteredList trackBy item") {{item}}
13 |
14 |
15 |
40 |
41 |
--------------------------------------------------------------------------------
/test/transition.spec.js:
--------------------------------------------------------------------------------
1 | import {transition} from '@/index.js'
2 | import {getTimeout} from '@/util.js'
3 |
4 | describe('Single element transition', function () {
5 | it ('transition when attached', function (done) {
6 | var wrap = document.createElement('div');
7 | document.body.appendChild(wrap);
8 | var MyComponent = san.defineComponent({
9 | template: 'Element with transition effects.
',
10 | transition: transition('fade'),
11 | attached: function () {
12 | const el = this.el
13 | nextFrame(function () {
14 | expect(isClassNameExists(el, 'fade-before-enter')).toBe(true)
15 | expect(isClassNameExists(el, 'fade-enter')).toBe(false)
16 | afterNextFrame(function () {
17 | expect(isClassNameExists(el, 'fade-before-enter')).toBe(false)
18 | expect(isClassNameExists(el, 'fade-enter')).toBe(true)
19 | setTimeout(() => {
20 | myComponent.dispose()
21 | document.body.removeChild(wrap)
22 | done()
23 | }, getTimeout(el))
24 | })
25 | })
26 | }
27 | })
28 | var myComponent = new MyComponent()
29 | myComponent.attach(wrap)
30 | })
31 |
32 | it ('transition when dispose', function (done) {
33 | var wrap = document.createElement('div');
34 | document.body.appendChild(wrap);
35 | var MyComponent = san.defineComponent({
36 | template: 'Element with transition effects.
',
37 | transition: transition('fade'),
38 | attached: function () {
39 | const el = this.el
40 | myComponent.dispose()
41 | nextFrame(function () {
42 | expect(isClassNameExists(el, 'fade-before-leave')).toBe(true)
43 | expect(isClassNameExists(el, 'fade-leave')).toBe(false)
44 | afterNextFrame(function () {
45 | expect(isClassNameExists(el, 'fade-before-leave')).toBe(false)
46 | expect(isClassNameExists(el, 'fade-leave')).toBe(true)
47 | done()
48 | document.body.removeChild(wrap)
49 | })
50 | })
51 | }
52 | })
53 | var myComponent = new MyComponent()
54 | myComponent.attach(wrap)
55 | })
56 | })
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "san-transition",
3 | "version": "1.1.0",
4 | "description": "Append transition effects for elements in san components.",
5 | "keywords": [
6 | "san",
7 | "transition",
8 | "san-transition"
9 | ],
10 | "main": "dist/index.js",
11 | "directories": {
12 | "doc": "docs"
13 | },
14 | "scripts": {
15 | "test": "karma start ./test/karma.conf.js --single-run",
16 | "lint": "eslint --ext .js src docs build",
17 | "codecov": "codecov",
18 | "dev": "webpack-dev-server --content-base docs/dist --config ./build/webpack.docs.config.js --hot --inline",
19 | "build": "webpack -p --config ./build/webpack.prod.config.js",
20 | "build:docs": "webpack -p --config ./build/webpack.docs.config.js"
21 | },
22 | "repository": {
23 | "type": "git",
24 | "url": "git+https://github.com/Dafrok/san-transition.git"
25 | },
26 | "author": "Dafrok ",
27 | "license": "MIT",
28 | "bugs": {
29 | "url": "https://github.com/Dafrok/san-transition/issues"
30 | },
31 | "homepage": "https://github.com/Dafrok/san-transition#readme",
32 | "devDependencies": {
33 | "babel-core": "^6.26.0",
34 | "babel-eslint": "^7.2.3",
35 | "babel-loader": "^7.1.2",
36 | "babel-preset-env": "^1.6.1",
37 | "babel-preset-es2015": "^6.24.1",
38 | "codecov": "^3.0.0",
39 | "css-loader": "^0.25.0",
40 | "eslint": "^3.19.0",
41 | "eslint-config-standard": "^10.2.1",
42 | "eslint-loader": "^1.9.0",
43 | "eslint-plugin-html": "^2.0.3",
44 | "eslint-plugin-import": "^2.7.0",
45 | "eslint-plugin-node": "^4.2.3",
46 | "eslint-plugin-promise": "^3.5.0",
47 | "eslint-plugin-standard": "^3.0.1",
48 | "html-loader": "^0.4.5",
49 | "html-webpack-plugin": "^2.30.1",
50 | "istanbul-instrumenter-loader": "^3.0.0",
51 | "jasmine-core": "^2.8.0",
52 | "jstransformer-markdown-it": "^2.0.0",
53 | "karma": "^1.7.1",
54 | "karma-chrome-launcher": "^2.2.0",
55 | "karma-coverage": "^1.1.1",
56 | "karma-jasmine": "^1.1.1",
57 | "karma-webpack": "^2.0.6",
58 | "normalize.css": "^6.0.0",
59 | "prismjs": "^1.8.1",
60 | "pug": "^2.0.0-rc.4",
61 | "san": "^3.6.1",
62 | "san-loader": "0.0.4",
63 | "style-loader": "^0.13.2",
64 | "stylus": "^0.54.5",
65 | "stylus-loader": "^3.0.1",
66 | "webpack": "^3.9.1",
67 | "webpack-dev-server": "^2.9.5"
68 | },
69 | "peerDependencies": {
70 | "san": "^3.6.0"
71 | },
72 | "dependencies": {
73 | "asap": "^2.0.6"
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/test/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration
2 | // Generated on Wed Mar 29 2017 16:16:32 GMT+0800 (CST)
3 |
4 | module.exports = function (config) {
5 | var configuration = {
6 |
7 | // base path that will be used to resolve all patterns (eg. files, exclude)
8 | basePath: '..',
9 |
10 | // frameworks to use
11 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
12 | frameworks: ['jasmine'],
13 |
14 | // list of files / patterns to load in the browser
15 | files: [
16 | './node_modules/san/dist/san.dev.js',
17 | './test/util/**',
18 | './test/**/*spec.js'
19 | ],
20 |
21 | // preprocess matching files before serving them to the browser
22 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
23 | preprocessors: {
24 | 'test/*.js': ['webpack'],
25 | 'src/*.js': ['webpack', 'coverage']
26 | },
27 |
28 | // test results reporter to use
29 | // possible values: 'dots', 'progress'
30 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter
31 | reporters: ['progress', 'coverage'],
32 | coverageReporter: {
33 | reporters: [{type: 'lcov'}]
34 | // type: 'html',
35 | // dir: 'test/coverage/'
36 | },
37 | webpack: require('../build/webpack.test.config.js'),
38 | webpackMiddleware: {
39 | noInfo: true
40 | },
41 | // web server port
42 | port: 9876,
43 |
44 | // enable / disable colors in the output (reporters and logs)
45 | colors: true,
46 |
47 | // level of logging
48 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
49 | logLevel: config.LOG_INFO,
50 |
51 | // enable / disable watching file and executing tests whenever any file changes
52 | autoWatch: true,
53 |
54 | // start these browsers
55 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
56 | browsers: ['Chrome'],
57 |
58 | customLaunchers: {
59 | Chrome_travis_ci: {
60 | base: 'Chrome',
61 | flags: ['--no-sandbox']
62 | }
63 | },
64 |
65 | // Continuous Integration mode
66 | // if true, Karma captures browsers, runs the tests and exits
67 | singleRun: false,
68 |
69 | // Concurrency level
70 | // how many browser should be started simultaneous
71 | concurrency: Infinity
72 | }
73 |
74 | if (process.env.TRAVIS) {
75 | configuration.browsers = ['Chrome_travis_ci'];
76 | }
77 |
78 | config.set(configuration)
79 | }
80 |
--------------------------------------------------------------------------------
/docs/markdown.styl:
--------------------------------------------------------------------------------
1 | .markdown-body
2 | padding 20px
3 | color #333
4 | table
5 | width 100%
6 | a
7 | color #4183C4
8 | &.absent
9 | color #c00
10 | &.anchor
11 | display block
12 | padding-left 30px
13 | margin-left -30px
14 | cursor pointer
15 | position absolute
16 | top 0
17 | left 0
18 | bottom 0
19 | &:first-child
20 | h1, h2, h3, h4, h5, h6
21 | margin-top 0
22 | padding-top 0
23 |
24 | h1, h2, h3, h4, h5, h6
25 | color #34495e
26 | margin 20px 0 10px
27 | padding 0
28 | font-weight bold
29 | -webkit-font-smoothing antialiased
30 | cursor text
31 | position relative
32 | &:hover a.anchor
33 | text-decoration none
34 | tt, code
35 | font-size inherit
36 | p
37 | margin-top 0
38 |
39 | h4, h5, h6
40 | font-weight 400
41 |
42 | h1
43 | font-size 32px
44 |
45 | h2
46 | font-size 28px
47 | border-bottom 1px solid #ccc
48 |
49 | h3
50 | font-size 24px
51 |
52 | h4
53 | font-size 20px
54 |
55 | h5
56 | font-size 18px
57 |
58 | h6
59 | color #777777
60 | font-size 16px
61 |
62 | p, blockquote, ul, ol, dl, li, table, pre
63 | margin 15px 0
64 |
65 | hr
66 | border 0 none
67 | color #ccc
68 | height 4px
69 | padding 0
70 |
71 | li
72 | p.first
73 | display inline-block
74 |
75 | ul, ol
76 | padding-left 30px
77 | &:first-child
78 | margin-top 0
79 |
80 | dl
81 | padding 0
82 | dt
83 | font-size 14px
84 | font-weight bold
85 | font-style italic
86 | padding 0
87 | margin 15px 0 5px
88 | &:first-child
89 | padding 0
90 | & > :first-child
91 | margin-top 0
92 | & > :last-child
93 | margin-bottom 0
94 | dd
95 | margin 0 0 15px
96 | padding 0 15px
97 | & > :first-child
98 | margin-top 0
99 | & > :last-child
100 | margin-bottom 0
101 |
102 | blockquote
103 | border-left 4px solid #ddd
104 | padding 0 15px
105 | color #777
106 | & > :first-child
107 | margin-top 0
108 | & > :last-child
109 | margin-bottom 0
110 |
111 | table
112 | padding 0
113 | border-collapse collapse
114 | tr
115 | border-top 1px solid #ccc
116 | background-color white
117 | margin 0
118 | padding 0
119 | &:nth-child(2n)
120 | background-color #f8f8f8
121 | th
122 | font-weight bold
123 | border 1px solid #ccc
124 | margin 0
125 | padding 6px 13px
126 | background #ccc
127 | td
128 | border 1px solid #ccc
129 | margin 0
130 | padding 6px 13px
131 | th, td
132 | &:first-child
133 | margin-top 0
134 | &:last-child
135 | margin-bottom 0
136 |
137 | img
138 | max-width 100%
139 |
140 | span
141 | &.frame
142 | display block
143 | overflow hidden
144 | & > span
145 | border 1px solid #ddd
146 | display block
147 | float left
148 | overflow hidden
149 | margin 13px 0 0
150 | padding 7px
151 | width auto
152 | span
153 | span
154 | clear both
155 | color #333
156 | display block
157 | padding 5px 0 0
158 | img
159 | display block
160 | float left
161 |
162 | .align-center
163 | display block
164 | overflow hidden
165 | clear both
166 | & > span
167 | display block
168 | overflow hidden
169 | margin 13px auto 0
170 | text-align center
171 | span img
172 | margin 0 auto
173 | text-align center
174 | .align-right
175 | display block
176 | overflow hidden
177 | clear both
178 | & > span
179 | display block
180 | overflow hidden
181 | margin 13px 0 0
182 | text-align right
183 | span img
184 | margin 0
185 | text-align right
186 | .float-left
187 | display block
188 | margin-right 13px
189 | overflow hidden
190 | float left
191 | span
192 | margin 13px 0 0
193 | .float-right
194 | display block
195 | margin-left 13px
196 | overflow hidden
197 | float right
198 | & > span
199 | display block
200 | overflow hidden
201 | margin 13px auto 0
202 | text-align right
203 |
204 | code, tt
205 | margin 0 2px
206 | padding 0 5px
207 | white-space nowrap
208 | border 1px solid #eaeaea
209 | background-color #f8f8f8
210 | border-radius 3px
211 |
212 | pre code
213 | margin 0
214 | padding 0
215 | white-space pre
216 | border none
217 | background transparent
218 |
219 | .highlight pre
220 | background-color #f8f8f8
221 | border 1px solid #ccc
222 | font-size 13px
223 | line-height 19px
224 | overflow auto
225 | padding 6px 10px
226 | border-radius 3px
227 |
228 | pre
229 | // background-color #f8f8f8
230 | border 1px solid #ccc
231 | font-size 13px
232 | line-height 19px
233 | overflow auto
234 | padding 6px 10px
235 | border-radius 3px
236 | pre code, pre tt
237 | background-color transparent
238 | border none
239 |
240 | sup
241 | font-size 0.83em
242 | vertical-align super
243 | line-height 0
244 |
245 | *
246 | -webkit-print-color-adjust exact
247 |
248 | @media screen and (min-width 914px)
249 | body
250 | width 854px
251 | margin0 auto
252 |
253 |
254 | @media print
255 | table, pre
256 | page-break-inside avoid
257 | pre
258 | word-wrap break-word
--------------------------------------------------------------------------------