├── .babelrc ├── vue-template ├── template │ ├── app.js │ ├── assets │ │ ├── url.js │ │ ├── weex-init.js │ │ ├── style.css │ │ ├── phantom-limb.js │ │ └── qrcode.js │ ├── weex.html │ ├── README.md │ └── index.html ├── package.json ├── README.md └── meta.json ├── .travis.yml ├── src ├── utils │ ├── index.js │ ├── hook.js │ ├── helper.js │ ├── logger.js │ └── server.js ├── hook │ └── post-install.js └── index.js ├── .gitignore ├── .npmignore ├── test ├── template │ ├── we │ │ └── test.we │ └── vue │ │ └── demo │ │ └── index.vue ├── index.test.js └── lib.test.js ├── README.md ├── package.json ├── bin └── weex-previewer.js ├── .eslintrc └── LICENSE /.babelrc: -------------------------------------------------------------------------------- 1 | { "presets": ["stage-0"] } 2 | -------------------------------------------------------------------------------- /vue-template/template/app.js: -------------------------------------------------------------------------------- 1 | import foo from "{{$module}}"; 2 | foo.el = '#root'; 3 | export default new Vue(foo); 4 | -------------------------------------------------------------------------------- /vue-template/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "weex-template", 3 | "version": "0.1.0", 4 | "description": "Weex template for vue-cli", 5 | "keywords": ["weex", "template"], 6 | "author": "jinjiang ", 7 | "license": "GPL-3.0" 8 | } 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | os: 4 | - linux 5 | - osx 6 | 7 | node_js: 8 | - 6 9 | - 7 10 | script: ./node_modules/mocha/bin/mocha tests/*.test.js 11 | before_install: 12 | - if [["$TRAVIS_OS_NAME" == "OSX"]]; then brew install nvm; fi; -------------------------------------------------------------------------------- /src/utils/index.js: -------------------------------------------------------------------------------- 1 | const logger = require('./logger'); 2 | const hook = require('./hook'); 3 | const helper = require('./helper'); 4 | const server = require('./server'); 5 | 6 | module.exports = { 7 | logger, 8 | hook, 9 | helper, 10 | server 11 | }; 12 | -------------------------------------------------------------------------------- /vue-template/README.md: -------------------------------------------------------------------------------- 1 | # Weex Template 2 | 3 | Weex template for [vue-cli](https://github.com/vuejs/vue-cli). 4 | 5 | ## Usage 6 | 7 | ```bash 8 | # Install vue-cli first. 9 | npm install -g vue-cli 10 | 11 | # Start a Weex Project. 12 | vue init Jinjiang/weex-template 13 | ``` 14 | -------------------------------------------------------------------------------- /vue-template/template/assets/url.js: -------------------------------------------------------------------------------- 1 | var protocol = location.protocol + '//' 2 | var hostname = typeof CURRENT_IP === 'string' ? CURRENT_IP : location.hostname 3 | var port = location.port ? ':' + location.port : '' 4 | var url = protocol + hostname + port + location.pathname.replace(/\/index\.html$/, '/').replace(/\/$/, '/dist/app.weex.js') 5 | -------------------------------------------------------------------------------- /vue-template/template/assets/weex-init.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | function getUrlParam (key) { 3 | var reg = new RegExp('[?|&]' + key + '=([^&]+)') 4 | var match = location.search.match(reg) 5 | return match && match[1] 6 | }; 7 | var page = 'dist/' + getUrlParam('page') || 'index.js'; 8 | var bundle = document.createElement('script') 9 | // only for web 10 | bundle.src = page 11 | document.body.appendChild(bundle) 12 | })(); -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | *.pbxuser 8 | !default.pbxuser 9 | *.mode1v3 10 | !default.mode1v3 11 | *.mode2v3 12 | !default.mode2v3 13 | *.perspectivev3 14 | !default.perspectivev3 15 | xcuserdata 16 | *.xccheckout 17 | *.moved-aside 18 | DerivedData 19 | *.hmap 20 | *.ipa 21 | *.xcuserstate 22 | project.xcworkspace 23 | tests/dist 24 | # Android/IJ 25 | # 26 | *.iml 27 | .idea 28 | .gradle 29 | local.properties 30 | 31 | # node.js 32 | # 33 | node_modules/ 34 | npm-debug.log 35 | 36 | # BUCK 37 | buck-out/ 38 | \.buckd/ 39 | android/app/libs 40 | android/keystores/debug.keystore 41 | .weex_tmp 42 | lib/ -------------------------------------------------------------------------------- /vue-template/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "prompts": { 3 | "name": { 4 | "type": "string", 5 | "required": true, 6 | "label": "Project name" 7 | }, 8 | "description": { 9 | "type": "string", 10 | "required": true, 11 | "label": "Project description", 12 | "default": "A Weex project" 13 | }, 14 | "author": { 15 | "type": "string", 16 | "label": "Author" 17 | } 18 | }, 19 | "skipInterpolation": "**/*.{vue,html,js}", 20 | "completeMessage": "To get started:\n\n cd {{destDirName}}\n npm install\n npm run build\n npm run serve\n open http://localhost:8080/" 21 | } 22 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | *.pbxuser 8 | !default.pbxuser 9 | *.mode1v3 10 | !default.mode1v3 11 | *.mode2v3 12 | !default.mode2v3 13 | *.perspectivev3 14 | !default.perspectivev3 15 | xcuserdata 16 | *.xccheckout 17 | *.moved-aside 18 | DerivedData 19 | *.hmap 20 | *.ipa 21 | *.xcuserstate 22 | project.xcworkspace 23 | tests/dist 24 | # Android/IJ 25 | # 26 | *.iml 27 | .idea 28 | .gradle 29 | local.properties 30 | 31 | # node.js 32 | # 33 | node_modules/ 34 | npm-debug.log 35 | 36 | # BUCK 37 | buck-out/ 38 | \.buckd/ 39 | android/app/libs 40 | android/keystores/debug.keystore 41 | .weex_tmp 42 | 43 | src/ -------------------------------------------------------------------------------- /src/utils/hook.js: -------------------------------------------------------------------------------- 1 | 2 | const request = require('request'); 3 | const dns = require('dns'); 4 | 5 | let shouldBeTelemetry = false; 6 | 7 | const record = (logkey, gokey) => { 8 | if (!shouldBeTelemetry) { 9 | return; 10 | } 11 | let url = `http://gm.mmstat.com${logkey}?`; 12 | for (const i in gokey) { 13 | if (gokey.hasOwnProperty(i)) { 14 | url += `${i}=${gokey[i]}&`; 15 | } 16 | } 17 | url += `t=${(new Date()).getTime()}`; 18 | dns.resolve('gm.mmstat.com', (err) => { 19 | if (!err) { 20 | request.get(url); 21 | } 22 | }); 23 | }; 24 | 25 | const allowTarck = () => { 26 | shouldBeTelemetry = true; 27 | }; 28 | 29 | module.exports = { 30 | record, 31 | allowTarck 32 | }; 33 | -------------------------------------------------------------------------------- /test/template/we/test.we: -------------------------------------------------------------------------------- 1 | 7 | 8 | 13 | 14 | 28 | -------------------------------------------------------------------------------- /test/index.test.js: -------------------------------------------------------------------------------- 1 | var pre = require('../src/index'); 2 | require('../lib/hook/post-install'); 3 | var pathTo = require('path'); 4 | var fse = require('fs-extra'); 5 | var fs = require('fs'); 6 | var os = require('os'); 7 | var expect = require('expect.js'); 8 | 9 | const WEEX_TEMP = '.weex_tmp'; 10 | const previewDir = pathTo.join(os.homedir(), WEEX_TEMP); 11 | fse.removeSync('./tests/dist/*'); 12 | describe('test main flow', function () { 13 | pre({ 14 | entry: './test/template/vue/demo/index.vue', 15 | open: false 16 | }); 17 | this.timeout(10000); 18 | console.log(previewDir) 19 | it('test .vue file build', function (done) { 20 | setTimeout(function () { 21 | expect(fs.existsSync(pathTo.join(previewDir,'dist/test/template/vue/demo/index.weex.js'))).to.equal(true); 22 | done(); 23 | }, 6000); 24 | }); 25 | }); 26 | 27 | -------------------------------------------------------------------------------- /src/hook/post-install.js: -------------------------------------------------------------------------------- 1 | // create an temp directory for weex file previewing 2 | const os = require('os'); 3 | const path = require('path'); 4 | const fse = require('fs-extra'); 5 | 6 | const home = os.homedir(); 7 | const WEEX_TEMP = '.weex_tmp'; 8 | const previewDir = path.join(home, WEEX_TEMP); 9 | 10 | try { 11 | if (!fse.ensureDirSync(previewDir)) { 12 | fse.mkdirsSync(previewDir); 13 | } 14 | else { 15 | fse.removeSync(previewDir); 16 | fse.mkdirsSync(previewDir); 17 | } 18 | fse.copySync('./vue-template/template', previewDir); 19 | } 20 | catch (err) { 21 | if (typeof err === 'object') { 22 | if (err.code === 'EACCES') { 23 | /* eslint no-console: ["error", { allow: ["error"] }] */ 24 | console.error('Error:permission denied.Please apply the write premission to the directory: "' + home + '" '); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /test/lib.test.js: -------------------------------------------------------------------------------- 1 | var helper = require('../src/utils/helper'); 2 | var pathTo = require('path'); 3 | var fse = require('fs-extra'); 4 | var fs = require('fs'); 5 | var expect = require('expect.js'); 6 | 7 | describe('third lib test', function () { 8 | describe('replace', function () { 9 | it('replace module', function () { 10 | var source = pathTo.resolve(pathTo.join('.', 'vue-template/template/app.js')), 11 | destPath = pathTo.resolve('./tests/dist/app.temp.js'), 12 | content = ''; 13 | fse.copySync(source, destPath); 14 | expect(fs.existsSync(destPath)).to.be(true); 15 | helper.replace(destPath, [{ 16 | rule: '{{$module}}', 17 | scripts: 'WEEX_REPLACE' 18 | }]); 19 | content = fs.readFileSync(destPath, { 20 | encoding: 'utf-8' 21 | }); 22 | expect(content.search('WEEX_REPLACE') >= 0).to.be(true); 23 | }); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /vue-template/template/weex.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | weex-vue-demo 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /test/template/vue/demo/index.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 15 | 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # weex-previewer 2 | 3 | [![npm](https://img.shields.io/npm/v/weex-previewer.svg?maxAge=2592000)]() 4 | [![Build Status](https://travis-ci.org/weexteam/weex-previewer.svg?branch=master)](https://travis-ci.org/weexteam/weex-previewer) 5 | 6 | a tool help user to preview their weex files 7 | 8 | ### how to use 9 | 10 | ``` bash 11 | npm install weex-previewer --save 12 | ``` 13 | 14 | ``` js 15 | var preview = require('weex-previewer'); 16 | preview({ 17 | entry: 'src/index.vue', 18 | port: 8081 19 | }); 20 | 21 | ``` 22 | 23 | #### use command line 24 | ``` bash 25 | npm install weex-previewer -g 26 | ``` 27 | 28 | ``` bash 29 | weex-previewer src/index.vue 30 | ``` 31 | 32 | 33 | 34 | ### Options 35 | 36 | | name | Type | Example | Description | 37 | | ------------- |:-------------:| -----:|----------:| 38 | | entry | string | 'src/index.vue' | the efile you want to preview | 39 | | open | boolean | true | auto open browser | 40 | | port | string | 8801 | specify an port for local web server | 41 | | wsport | string | 8804 | specify an websocket port for hot reload | 42 | 43 | ### ChangeLog 44 | 45 | 1.3.9 46 | 47 | - Fix ip address on server. 48 | - Replace quick-local-ip module with ip module. -------------------------------------------------------------------------------- /vue-template/template/README.md: -------------------------------------------------------------------------------- 1 | # {{ name }} 2 | 3 | > {{ description }} 4 | 5 | ## getting start 6 | 7 | ```bash 8 | npm install 9 | ``` 10 | 11 | ## file structure 12 | 13 | * `src/*`: all source code 14 | * `app.js`: entrance of the Weex page 15 | * `build/*`: webpack config files 16 | * `dist/*`: where places generated code 17 | * `assets/*`: some assets for Web preview 18 | * `index.html`: a page with Web preview and qrcode of Weex js bundle 19 | * `weex.html`: Web render 20 | * `.babelrc`: babel config (preset-2015 by default) 21 | * `.eslintrc`: eslint config (standard by default) 22 | 23 | ## npm scripts 24 | 25 | ```bash 26 | # build both two js bundles for Weex and Web 27 | npm run build 28 | 29 | # build js bundle for Weex to `dist/app.weex.js` 30 | npm run build:weex 31 | 32 | # build js bundle for Web to `dist/app.web.js` 33 | npm run build:web 34 | 35 | # build js bundle for Weex and watch to file changes 36 | npm run dev:weex 37 | 38 | # build js bundle for Web and watch to file changes 39 | npm run dev:web 40 | 41 | # start a Web server at 8080 port 42 | npm run serve 43 | 44 | # start weex-devtool for debugging with native 45 | npm run debug 46 | ``` 47 | 48 | ## notes 49 | 50 | You can config more babel, ESLint and PostCSS plugins in webpack config files in `build/webpack.*.config.js`. 51 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "weex-previewer", 3 | "version": "1.5.1", 4 | "description": "a tool help user to preview their weex files", 5 | "main": "lib/index.js", 6 | "scripts": { 7 | "test": "npm run lint && mocha test/*.test.js", 8 | "lint": "eslint src --fix", 9 | "build": "babel src --out-dir lib", 10 | "dev": "babel src --out-dir lib --watch", 11 | "prepublish": "npm run build && npm run test", 12 | "postinstall": "node ./lib/hook/post-install.js" 13 | }, 14 | "bin": { 15 | "weex-previewer": "./bin/weex-previewer.js" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/weexteam/weex-previewer.git" 20 | }, 21 | "author": "", 22 | "license": "ISC", 23 | "dependencies": { 24 | "babel-preset-stage-0": "^6.24.1", 25 | "chalk": "^1.1.3", 26 | "commander": "^2.13.0", 27 | "detect-port": "^1.2.1", 28 | "dns": "^0.2.2", 29 | "exit": "^0.1.2", 30 | "fs-extra": "^0.30.0", 31 | "http-server": "^0.9.0", 32 | "ip": "^1.1.5", 33 | "opener": "^1.4.1", 34 | "path": "^0.12.7", 35 | "request": "^2.83.0", 36 | "weex-builder": "^0.3.19", 37 | "weex-vue-render": "^0.12.21", 38 | "ws": "^1.1.0" 39 | }, 40 | "devDependencies": { 41 | "babel-cli": "^6.26.0", 42 | "babel-core": "^6.14.0", 43 | "babel-eslint": "^8.2.1", 44 | "browserify": "^13.3.0", 45 | "eslint": "^4.17.0", 46 | "expect.js": "^0.2.0", 47 | "karma": "^1.4.0", 48 | "mocha": "^3.2.0", 49 | "vinyl-source-stream": "^1.1.0" 50 | }, 51 | "bugs": { 52 | "url": "https://github.com/weexteam/weex-previewer/issues" 53 | }, 54 | "homepage": "https://github.com/weexteam/weex-previewer#readme", 55 | "changelog": { 56 | "messages": [ 57 | "Rewrite weex preview help infomation.", 58 | "Fix https://github.com/weexteam/weex-toolkit/issues/373." 59 | ] 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /vue-template/template/assets/style.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | text-align: center; 3 | } 4 | 5 | #app { 6 | display: flex; 7 | justify-content: center; 8 | } 9 | 10 | #preview { 11 | width: 750px; 12 | height: 1245px; 13 | transform: scale(0.354); 14 | transform-origin: top left; 15 | } 16 | 17 | .mock-phone { 18 | position: relative; 19 | width: 297px; 20 | min-width: 297px; 21 | height: 591px; 22 | border: 2px solid #0088fb; 23 | border-radius: 30px; 24 | } 25 | 26 | .mock-phone .inner { 27 | position: absolute; 28 | top: 60px; 29 | z-index: 26; 30 | left: 12px; 31 | width: 267px; 32 | height: 441px; 33 | border: 1px solid #0088fb; 34 | overflow: hidden; 35 | } 36 | 37 | .mock-phone .inner iframe { 38 | width: 100%; 39 | height: 100%; 40 | margin: 0; 41 | } 42 | 43 | .mock-phone .camera { 44 | position: absolute; 45 | width: 14px; 46 | height: 14px; 47 | border-radius: 14px; 48 | background: #afddff; 49 | border: 1px solid #0088fb; 50 | top: 23px; 51 | left: 94px; 52 | } 53 | 54 | .mock-phone .earpiece { 55 | position: absolute; 56 | width: 70px; 57 | height: 8px; 58 | border-radius: 8px; 59 | background: #afddff; 60 | border: 1px solid #0088fb; 61 | top: 26px; 62 | left: 124px; 63 | } 64 | 65 | .mock-phone .home-btn { 66 | position: absolute; 67 | width: 56px; 68 | height: 56px; 69 | border-radius: 56px; 70 | background: #afddff; 71 | border: 1px solid #0088fb; 72 | bottom: 14px; 73 | left: 50%; 74 | margin-left: -28px; 75 | } 76 | 77 | #qrcode { 78 | width: 400px; 79 | display: flex; 80 | flex-direction: column; 81 | justify-content: center; 82 | align-items: center; 83 | } 84 | 85 | #qrcode canvas { 86 | width: 250px; 87 | height: 250px; 88 | } 89 | 90 | #qrcode .bundle-url { 91 | font-size: 14px; 92 | line-height: 1.5; 93 | word-break: break-all; 94 | } -------------------------------------------------------------------------------- /src/utils/helper.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs-extra'); 2 | const path = require('path'); 3 | 4 | const helper = { 5 | // check entry file 6 | checkEntry: function (filename) { 7 | return /\.(we|vue)$/.test(filename); 8 | }, 9 | getFileType: function (filename) { 10 | return /\.vue$/.test(filename) ? 'vue' : 'we'; 11 | }, 12 | /** 13 | * use regular expression to replace some file contents 14 | * @param filePath 15 | * @param regarr regular expression array 16 | * */ 17 | replace: function (filePath, regarr, escape) { 18 | let content = fs.readFileSync(filePath, { 19 | encoding: 'utf-8' 20 | }); 21 | regarr.forEach((regObj) => { 22 | content = content.replace(regObj.rule, () => { 23 | if (!escape) { 24 | return regObj.scripts; 25 | } 26 | return regObj.scripts.replace(/\\/g, '\\\\'); 27 | }); 28 | }); 29 | return fs.writeFileSync(filePath, content); 30 | }, 31 | // get web preview vue app.js contents 32 | getVueAppContent: function (entryPath) { 33 | const relativePath = path.resolve(entryPath); 34 | let contents = ''; 35 | contents += 'var App = require(\'' + relativePath.replace(/\\/g, '\\\\') + '\')\n'; 36 | contents += 'App.el = \'#root\'\n'; 37 | contents += 'new Vue(App)\n'; 38 | return contents; 39 | }, 40 | createVueSrc: function (src, targetDir) { 41 | src = src || '.'; 42 | if (!this.basename) { 43 | this.basename = src; 44 | } 45 | const self = this; 46 | if (this.isDir(src)) { 47 | fs.readdirSync(src).forEach((file) => { 48 | const fullpath = path.join(src, file); 49 | const extname = path.extname(fullpath); 50 | if (self.isFile(fullpath) && extname === '.vue') { 51 | const entryFile = path.join(targetDir, path.relative(self.basename, src), path.basename(file, extname) + '.js'); 52 | fs.outputFileSync(path.join(entryFile), self.getVueAppContent(fullpath)); 53 | } 54 | else if (self.isDir(fullpath) && file !== 'build' && file !== 'include') { 55 | const subdir = path.join(src, file); 56 | self.createVueSrc(subdir, targetDir); 57 | } 58 | }); 59 | } 60 | else { 61 | const extname = path.extname(src); 62 | const entryFile = path.join(targetDir, path.basename(src, extname) + '.js'); 63 | fs.outputFileSync(path.join(entryFile), self.getVueAppContent(src)); 64 | } 65 | }, 66 | isDir: function (src) { 67 | const stat = fs.statSync(src); 68 | return stat.isDirectory(); 69 | }, 70 | isFile: function (src) { 71 | const stat = fs.statSync(src); 72 | return stat.isFile(); 73 | } 74 | }; 75 | 76 | module.exports = helper; 77 | -------------------------------------------------------------------------------- /src/utils/logger.js: -------------------------------------------------------------------------------- 1 | const chalk = require('chalk'); 2 | const EventEmitter = require('events').EventEmitter; 3 | 4 | const events = new EventEmitter(); 5 | const LOGLEVELS = ['verbose', 'log', 'info', 'warn', 'error', 'success']; 6 | 7 | // global var 8 | const LOGLEVEL = { 9 | VERBOSE: 'verbose', 10 | LOG: 'log', 11 | WARN: 'warn', 12 | INFO: 'info', 13 | ERROR: 'error', 14 | SUCCESS: 'success' 15 | }; 16 | 17 | const SEVERITY = { 18 | verbose: 1000, 19 | log: 2000, 20 | warn: 3000, 21 | info: 3000, 22 | error: 5000, 23 | success: 10000 24 | }; 25 | 26 | const LOGCOLOR = { 27 | verbose: 'grey', 28 | log: 'white', 29 | warn: 'yellow', 30 | info: 'white', 31 | error: 'red', 32 | success: 'green' 33 | }; 34 | 35 | let DEFAULT_LOGLEVEL = LOGLEVEL.LOG; 36 | 37 | const formatError = (error, isVerbose) => { 38 | let message = ''; 39 | if (error instanceof Error) { 40 | if (isVerbose) { 41 | message = error.stack; 42 | } 43 | else { 44 | message = error; 45 | } 46 | } 47 | else { 48 | // Plain text error message 49 | message = error; 50 | } 51 | if (typeof message === 'string' && message.toUpperCase().indexOf('ERROR:') !== 0) { 52 | // Needed for backward compatibility with external tools 53 | message = 'Error: ' + message; 54 | } 55 | return message; 56 | }; 57 | const fill = (num) => { 58 | return num > 9 ? num : `0${num}`; 59 | }; 60 | const log = loglevel => (message) => { 61 | const isVerbose = DEFAULT_LOGLEVEL === LOGLEVEL.VERBOSE; 62 | if (!SEVERITY[DEFAULT_LOGLEVEL] || SEVERITY[DEFAULT_LOGLEVEL] > SEVERITY[loglevel]) { 63 | // return instance to allow to chain calls 64 | return; 65 | } 66 | if (message instanceof Error || (isVerbose && loglevel === 'error')) { 67 | message = formatError(message, isVerbose); 68 | } 69 | const color = LOGCOLOR[loglevel]; 70 | let time; 71 | let prefix; 72 | let sep; 73 | if (SEVERITY[loglevel] >= SEVERITY[LOGLEVEL.INFO]) { 74 | time = new Date(); 75 | prefix = chalk.gray(`${fill(time.getHours())}:${fill(time.getMinutes())}:${fill(time.getSeconds())}`); 76 | sep = ':'; 77 | console.log(chalk.grey(prefix), sep, chalk[color](message)); 78 | } 79 | else { 80 | console.log(chalk[color](message)); 81 | } 82 | }; 83 | 84 | const subscribe = (event) => { 85 | if (!(event instanceof EventEmitter)) { 86 | throw new Error('Subscribe method only accepts an EventEmitter instance as argument'); 87 | } 88 | event 89 | .on('verbose', log('verbose')) 90 | .on('log', log('log')) 91 | .on('info', log('info')) 92 | .on('warn', log('warn')) 93 | .on('error', log('error')) 94 | .on('success', log('success')); 95 | 96 | return event; 97 | }; 98 | 99 | const setLevel = (logLevel) => { 100 | DEFAULT_LOGLEVEL = logLevel; 101 | }; 102 | 103 | const logger = { 104 | setLevel, 105 | subscribe, 106 | verbose: log('verbose'), 107 | log: log('log'), 108 | info: log('info'), 109 | warn: log('warn'), 110 | error: log('error'), 111 | success: log('success') 112 | }; 113 | 114 | module.exports = { 115 | ...logger, 116 | events, 117 | LOGLEVELS 118 | }; 119 | -------------------------------------------------------------------------------- /vue-template/template/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Weex Preview 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |

Weex Preview

17 |
18 | 36 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /bin/weex-previewer.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const fs = require('fs-extra'); 4 | const pkg = require('../package.json'); 5 | const exit = require('exit'); 6 | const path = require('path'); 7 | const program = require('commander'); 8 | const chalk = require('chalk'); 9 | const detect = require('detect-port'); 10 | const preview = require('../lib'); 11 | 12 | const binname = 'weex'; 13 | 14 | // rename the cmdname for weex-toolkit 15 | program._name = `${binname} preview`; 16 | 17 | const { 18 | logger, 19 | hook, 20 | helper 21 | } = require('../lib/utils') 22 | 23 | program 24 | .option('-v, --version', 'output version') 25 | .option('-h, --help', 'output usage information') 26 | .option('-e, --entry [target]', 'set the entry file') 27 | .option('-c, --config [path]', 'set webpack configuration file to override the built-in configuration') 28 | .option('-p, --port [port]', 'set preview server port, default: 8081', '8081') 29 | .option('--telemetry', 'upload usage data to help us improve the toolkit') 30 | .option('--verbose', 'display all logs of debugger server') 31 | .option('--loglevel [loglevel]', 'set log level silent|error|warn|info|log|debug', 'error') 32 | .parse(process.argv) 33 | 34 | // Supporting add the file / directory parameter after the command. 35 | program['arguments']('[target]').action(function (target) { 36 | program.target = target; 37 | }); 38 | 39 | // Fix tj's commander bug overwrite --help 40 | if (program.help === undefined) { 41 | program.outputHelp(); 42 | exit(0); 43 | } 44 | 45 | 46 | // Fix tj's commander bug overwrite --version 47 | if (program.version === undefined) { 48 | logger.log(pkg.version); 49 | exit(0); 50 | } 51 | 52 | if (program.loglevel) { 53 | program.loglevel = program.loglevel.toLowercase && program.loglevel.toLowercase() 54 | if(logger.LOGLEVELS.indexOf(program.loglevel) > -1) { 55 | logger.setLevel(program.loglevel) 56 | } 57 | } 58 | 59 | if (program.verbose) { 60 | logger.setLevel('verbose') 61 | } 62 | 63 | if (program.telemetry) { 64 | hook.allowTarck() 65 | } 66 | 67 | process.on('uncaughtException', (err) => { 68 | logger.error(err.stack) 69 | }); 70 | process.on('unhandledRejection', (err) => { 71 | logger.error(err.stack); 72 | }); 73 | 74 | const pipe = (args) => { 75 | if (!args || !args[0]) { 76 | program.outputHelp(); 77 | return false; 78 | } 79 | const target = args[0]; 80 | const ext = path.extname(target); 81 | let result = { 82 | folder: '', 83 | entry: '' 84 | } 85 | if(!fs.existsSync(target)){ 86 | logger.error(`Not found file ${target}`); 87 | return false; 88 | } 89 | if (!ext) { 90 | result.folder = target; 91 | if (!program.entry) { 92 | logger.error(`Need to config the entry file like: \`${binname} ${target} --entry ${path.join(target, 'index.vue')}\``); 93 | return false; 94 | } 95 | else { 96 | result.entry = program.entry 97 | } 98 | } 99 | else { 100 | result.entry = target || '' 101 | } 102 | return result; 103 | } 104 | 105 | detect(program.port).then((open) => { 106 | const target = pipe(program.args) 107 | if (target) { 108 | // If permission to track use 109 | let entryCount = 0; 110 | let fileType; 111 | let options; 112 | let optionflags; 113 | const entryType = { 114 | 2: 'single', 115 | 6: 'folder' 116 | } 117 | if (target.entry) { 118 | entryCount+=2; 119 | fileType = helper.getFileType(path.basename(target.entry)) 120 | } 121 | if (target.folder) { 122 | entryCount+=4; 123 | } 124 | optionflags = { 125 | entry: !!program.entry, 126 | port:!!program.port, 127 | verbose:!!program.verbose, 128 | config:!!program.config, 129 | loglevel:!!program.loglevel 130 | } 131 | hook.record('/weex_tool.weex-previewer.sence', { file_type: fileType, entry: entryType[entryCount], options: options}); 132 | 133 | options = { 134 | config:program.config 135 | } 136 | logger.info('Bundling source...') 137 | preview(target, open, options); 138 | } 139 | }) -------------------------------------------------------------------------------- /src/utils/server.js: -------------------------------------------------------------------------------- 1 | const httpServer = require('http-server'); 2 | const localIP = require('ip'); 3 | const fse = require('fs-extra'); 4 | const opener = require('opener'); 5 | const WebSocket = require('ws'); 6 | const logger = require('./logger'); 7 | 8 | const wsServer = WebSocket.Server; 9 | const clients = []; 10 | 11 | const server = { 12 | run (args) { 13 | const params = args; 14 | const options = { 15 | root: params.dir, 16 | cache: '-1', 17 | showDir: true, 18 | autoIndex: true 19 | }; 20 | this.rootDir = params.dir; 21 | if (!this.checkPort(params.port)) { 22 | return logger.info('HTTP port is illegal and please try another'); 23 | } 24 | this.bindProcessEvent(); 25 | const servers = httpServer.createServer(options); 26 | servers.listen(params.port, '0.0.0.0', () => { 27 | logger.info((new Date()) + `http is listening on port ${params.port}`); 28 | const IP = this.getLocalIP(); 29 | const previewUrl = `http://${IP}:${params.port}/?hot-reload_controller&page=${params.module}.js&loader=xhr&wsport=${params.wsport}&type=${params.fileType}`; 30 | if (params.open) { 31 | opener(previewUrl); 32 | } 33 | logger.info(previewUrl); 34 | }); 35 | this.startWebSocket(params.wsport, params.wsSuccessCallback); 36 | return servers; 37 | }, 38 | startWebSocket (wsport, wsSuccessCallback) { 39 | if (!this.checkPort(wsport)) { 40 | return logger.info('websocket port is illegal and please try another'); 41 | } 42 | const wss = wsServer({ 43 | port: wsport 44 | }); 45 | logger.info((new Date()) + `WebSocket is listening on port ${wsport}`); 46 | wss.on('connection', (ws) => { 47 | clients.push(ws); 48 | ws.on('message', (message) => { 49 | logger.info('received: %s', message); 50 | clients.forEach((client) => { 51 | if (client.readyState === WebSocket.OPEN) { 52 | client.send('ws server ok', (err) => { 53 | if (err) { 54 | logger.error(err); 55 | } 56 | }); 57 | } 58 | }); 59 | }); 60 | // websocket close handle 61 | ws.on('close', () => { 62 | ws.close(); 63 | ws._socket.destroy(); 64 | clients.splice(this.findClient(ws.upgradeReq.url)); 65 | }); 66 | ws.on('error', (error) => { 67 | if (error) { 68 | logger.error(error); 69 | ws.close(); 70 | ws._socket.destroy(); 71 | clients.splice(this.findClient(ws.upgradeReq.url), 1); 72 | } 73 | }); 74 | }); 75 | wsSuccessCallback(); 76 | this.wss = wss; 77 | return wss; 78 | }, 79 | findClient (url) { 80 | for (let i = 0; i < clients.length; i++) { 81 | if (clients[i].upgradeReq.url === url) { 82 | return i; 83 | } 84 | } 85 | return null; 86 | }, 87 | // send web socket messsage to client 88 | sendSocketMessage (message) { 89 | clients.forEach((client) => { 90 | if (client.readyState === WebSocket.OPEN) { 91 | client.send(message || 'refresh', (err) => { 92 | if (err) { 93 | logger.error(err); 94 | } 95 | }); 96 | } 97 | }); 98 | }, 99 | bindProcessEvent () { 100 | process.on('uncaughtException', (err) => { 101 | if (err.errno === 'EADDRINUSE') { 102 | logger.info('The server has been setted up.'); 103 | } 104 | else { 105 | logger.error(err); 106 | } 107 | process.exit(1); 108 | }); 109 | process.on('SIGINT', () => { 110 | logger.info('weex server stoped'); 111 | process.exit(); 112 | }); 113 | process.on('SIGTERM', () => { 114 | logger.info('weex server stoped'); 115 | process.exit(); 116 | }); 117 | }, 118 | // remove cache file if in user project directory 119 | removeWebFile () { 120 | if (this.rootDir === '.weex_tmp') { 121 | try { 122 | fse.removeSync(this.rootDir); 123 | } 124 | catch (err) { 125 | logger.error(err); 126 | } 127 | } 128 | }, 129 | // get local network ip 130 | getLocalIP: function () { 131 | return localIP.address(); 132 | }, 133 | checkPort: function (port) { 134 | port = parseInt(port, 10); 135 | return !!(port >= 0 && port < 65336 && port !== 80 && port !== 23); 136 | } 137 | }; 138 | 139 | module.exports = server; 140 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | 4 | "parserOptions": { 5 | "ecmaVersion": 6, 6 | "sourceType": "module" 7 | }, 8 | 9 | "env": { 10 | "es6": true, 11 | "node": true, 12 | "mocha": true 13 | }, 14 | 15 | "globals": { 16 | "weex": false, 17 | "document": false, 18 | "navigator": false, 19 | "window": false, 20 | "location": false, 21 | "callNative": false, 22 | "callNativeModule": false, 23 | "callAddElement":false, 24 | "callJS": false, 25 | "notifyTrimMemory": false, 26 | "markupState": false, 27 | "compileAndRunBundle": false, 28 | "expect": false, 29 | "sinon": false 30 | }, 31 | 32 | "rules": { 33 | "accessor-pairs": 2, 34 | "arrow-spacing": [2, { "before": true, "after": true }], 35 | "block-spacing": [2, "always"], 36 | "brace-style": [2, "stroustrup", { "allowSingleLine": true }], 37 | "camelcase": [2, { "properties": "never" }], 38 | "comma-dangle": [2, "never"], 39 | "comma-spacing": [2, { "before": false, "after": true }], 40 | "comma-style": [2, "last"], 41 | "constructor-super": 2, 42 | "curly": [2, "multi-line"], 43 | "dot-location": [2, "property"], 44 | "eol-last": 2, 45 | "eqeqeq": [2, "allow-null"], 46 | "generator-star-spacing": [2, { "before": true, "after": true }], 47 | "handle-callback-err": [2, "^(err|error)$" ], 48 | "indent": [2, 2, { "SwitchCase": 1 }], 49 | "key-spacing": [2, { "beforeColon": false, "afterColon": true }], 50 | "keyword-spacing": [2, { "before": true, "after": true }], 51 | "new-cap": [2, { "newIsCap": true, "capIsNew": false }], 52 | "new-parens": 2, 53 | "no-array-constructor": 2, 54 | "no-caller": 2, 55 | "no-class-assign": 2, 56 | "no-cond-assign": 2, 57 | "no-const-assign": 2, 58 | "no-control-regex": 2, 59 | "no-debugger": 2, 60 | "no-delete-var": 2, 61 | "no-dupe-args": 2, 62 | "no-dupe-class-members": 2, 63 | "no-dupe-keys": 2, 64 | "no-duplicate-case": 2, 65 | "no-empty-character-class": 2, 66 | "no-empty-pattern": 2, 67 | "no-eval": 2, 68 | "no-ex-assign": 2, 69 | "no-extend-native": 2, 70 | "no-extra-bind": 2, 71 | "no-extra-boolean-cast": 2, 72 | "no-extra-parens": [2, "functions"], 73 | "no-fallthrough": 2, 74 | "no-floating-decimal": 2, 75 | "no-func-assign": 2, 76 | "no-implied-eval": 2, 77 | "no-inner-declarations": [2, "functions"], 78 | "no-invalid-regexp": 2, 79 | "no-irregular-whitespace": 2, 80 | "no-iterator": 2, 81 | "no-label-var": 2, 82 | "no-labels": [2, { "allowLoop": false, "allowSwitch": false }], 83 | "no-lone-blocks": 2, 84 | "no-mixed-spaces-and-tabs": 2, 85 | "no-multi-spaces": 2, 86 | "no-multi-str": 2, 87 | "no-multiple-empty-lines": [2, { "max": 1 }], 88 | "no-native-reassign": 2, 89 | "no-negated-in-lhs": 2, 90 | "no-new-object": 2, 91 | "no-new-require": 2, 92 | "no-new-symbol": 2, 93 | "no-new-wrappers": 2, 94 | "no-obj-calls": 2, 95 | "no-octal": 2, 96 | "no-octal-escape": 2, 97 | "no-path-concat": 2, 98 | "no-proto": 2, 99 | "no-redeclare": 2, 100 | "no-regex-spaces": 2, 101 | "no-return-assign": [2, "except-parens"], 102 | "no-self-assign": 2, 103 | "no-self-compare": 2, 104 | "no-sequences": 2, 105 | "no-shadow-restricted-names": 2, 106 | "no-spaced-func": 2, 107 | "no-sparse-arrays": 2, 108 | "no-this-before-super": 2, 109 | "no-throw-literal": 2, 110 | "no-trailing-spaces": 2, 111 | "no-undef": 2, 112 | "no-undef-init": 2, 113 | "no-unexpected-multiline": 2, 114 | "no-unmodified-loop-condition": 2, 115 | "no-unneeded-ternary": [2, { "defaultAssignment": false }], 116 | "no-unreachable": 2, 117 | "no-unsafe-finally": 2, 118 | "no-unused-vars": [2, { "vars": "all", "args": "none" }], 119 | "no-useless-call": 2, 120 | "no-useless-computed-key": 2, 121 | "no-useless-constructor": 2, 122 | "no-useless-escape": 2, 123 | "no-whitespace-before-property": 2, 124 | "no-with": 2, 125 | "one-var": [2, { "initialized": "never" }], 126 | // "operator-linebreak": [2, "after", { "overrides": { "?": "before", ":": "before" } }], 127 | "padded-blocks": [2, "never"], 128 | "quotes": [2, "single", {"avoidEscape": true, "allowTemplateLiterals": true}], 129 | "semi": [2, "always"], 130 | "semi-spacing": [2, { "before": false, "after": true }], 131 | "space-before-blocks": [2, "always"], 132 | "space-before-function-paren": [2, "always"], 133 | "space-in-parens": [2, "never"], 134 | "space-infix-ops": 2, 135 | "space-unary-ops": [2, { "words": true, "nonwords": false }], 136 | "spaced-comment": [2, "always", { "markers": ["global", "globals", "eslint", "eslint-disable", "*package", "!", ","] }], 137 | "template-curly-spacing": [2, "never"], 138 | "use-isnan": 2, 139 | "valid-typeof": 2, 140 | "wrap-iife": [2, "any"], 141 | "yield-star-spacing": [2, "both"], 142 | "yoda": [2, "never"], 143 | "no-var": 2, 144 | "prefer-const": 2, 145 | "object-curly-spacing": [2, "always", { 146 | "objectsInObjects": false 147 | }], 148 | "array-bracket-spacing": [2, "never"] 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs-extra'); 2 | const path = require('path'); 3 | const os = require('os'); 4 | const builder = require('weex-builder'); 5 | 6 | const { 7 | logger, 8 | helper, 9 | server 10 | } = require('./utils'); 11 | 12 | const WEEX_TMP_DIR = '.weex_tmp'; 13 | 14 | const defaultParams = { 15 | entry: '', 16 | folder: '', 17 | output: '', 18 | fileExt: ['vue', 'we'], 19 | temDir: path.join(os.homedir(), WEEX_TMP_DIR), 20 | port: '8081', 21 | host: '127.0.0.1', 22 | wsport: '8082', 23 | open: true, 24 | options: {} 25 | }; 26 | const Previewer = { 27 | init: function (args, port, options) { 28 | if (!helper.checkEntry(args.entry)) { 29 | return logger.error('Not a ".vue" or ".we" file'); 30 | } 31 | this.params = Object.assign({}, defaultParams, args); 32 | this.params.options = options; 33 | this.params.port = port; 34 | this.params.wsport = port + 1; 35 | this.params.source = this.params.folder || this.params.entry; 36 | if (this.params.folder) { 37 | this.file = path.relative(this.params.source, this.params.entry); 38 | } 39 | else { 40 | this.file = this.params.entry; 41 | } 42 | this.fileType = helper.getFileType(this.file); 43 | this.module = this.file.replace(path.extname(this.file), ''); 44 | this.fileDir = process.cwd(); 45 | return this.fileFlow(); 46 | }, 47 | fileFlow () { 48 | logger.verbose(`init template diretory to ${this.params.temDir}`); 49 | this.initTemDir(); 50 | logger.verbose('building JS file'); 51 | this.buildJSFile(() => { 52 | logger.verbose('start server'); 53 | this.startServer(); 54 | }); 55 | }, 56 | // build temporary directory for web preview 57 | initTemDir () { 58 | if (!fs.existsSync(this.params.temDir)) { 59 | this.params.temDir = WEEX_TMP_DIR; 60 | fs.mkdirsSync(WEEX_TMP_DIR); 61 | fs.copySync(`${__dirname}/../vue-template/template/`, WEEX_TMP_DIR); 62 | } 63 | // replace old file 64 | fs.copySync(`${__dirname}/../vue-template/template/weex.html`, `${this.params.temDir}/weex.html`); 65 | const vueRegArr = [{ 66 | rule: /{{\$script}}/, 67 | scripts: ` 68 | 69 | 70 | ` 71 | }]; 72 | const weRegArr = [{ 73 | rule: /{{\$script}}/, 74 | scripts: ` 75 | 76 | ` 77 | }]; 78 | let regarr = vueRegArr; 79 | if (this.fileType === 'we') { 80 | regarr = weRegArr; 81 | } 82 | else { 83 | this.params.webSource = path.join(this.params.temDir, 'temp'); 84 | if (fs.existsSync(this.params.webSource)) { 85 | fs.removeSync(this.params.webSource); 86 | } 87 | helper.createVueSrc(this.params.source, this.params.webSource); 88 | } 89 | helper.replace(path.join(`${this.params.temDir}/`, 'weex.html'), regarr); 90 | }, 91 | // only for vue previewing on web 92 | createVueAppEntry () { 93 | helper.replace(`${this.params.temDir}/app.js`, [{ 94 | rule: '{{$module}}', 95 | scripts: path.join(process.cwd(), this.params.source) 96 | }], true); 97 | this.params.entry = this.params.temDir + '/app.js'; 98 | }, 99 | buildJSFile (callback) { 100 | const buildOpt = { 101 | watch: true, 102 | ext: /\.js$/.test(this.params.entry) ? 'js' : this.fileType, 103 | ...this.params.options 104 | }; 105 | let source = this.params.entry; 106 | const dest = path.join(this.params.temDir, 'dist'); 107 | let webDest; 108 | let vueSource = this.params.source; 109 | if (this.params.folder) { 110 | source = this.params.folder; 111 | vueSource = this.params.folder; 112 | buildOpt.entry = this.params.entry; 113 | } 114 | else { 115 | webDest = path.join(this.params.temDir, 'dist', this.params.entry.replace(path.basename(this.params.entry), '')); 116 | } 117 | if (this.fileType === 'vue') { 118 | if (buildOpt.entry) { 119 | buildOpt.entry = this.params.entry; 120 | } 121 | else { 122 | source = this.params.entry; 123 | } 124 | // for weex 125 | this.build(vueSource, dest, buildOpt, () => { 126 | logger.info('weex JS bundle saved at ' + path.resolve(this.params.temDir)); 127 | // for web 128 | this.build(this.params.webSource, webDest || dest, { 129 | web: true, 130 | ext: 'js' 131 | }, callback); 132 | }, () => { 133 | // for web 134 | this.build(this.params.webSource, webDest || dest, { 135 | web: true, 136 | ext: 'js' 137 | }, callback); 138 | }); 139 | } 140 | else { 141 | this.build(source, dest, buildOpt, callback); 142 | } 143 | }, 144 | build (src, dest, opts, buildcallback, watchCallback) { 145 | if (!opts.web && path.extname(src) === '.vue') { 146 | dest += '/[name].weex.js'; 147 | } 148 | else if (!opts.web && path.extname(src) !== '.vue') { 149 | opts['filename'] = '[name].weex.js'; 150 | } 151 | builder.build(src, dest, 152 | { 153 | ...opts, 154 | ...this.params.options 155 | }, 156 | (err, fileStream) => { 157 | if (!err) { 158 | if (this.wsSuccess) { 159 | if (typeof watchCallback !== 'undefined') { 160 | watchCallback(); 161 | } 162 | logger.info(fileStream); 163 | server.sendSocketMessage(); 164 | } 165 | else { 166 | buildcallback(); 167 | } 168 | } 169 | else { 170 | logger.error(err); 171 | } 172 | }); 173 | }, 174 | startServer () { 175 | const self = this; 176 | server.run({ 177 | dir: this.params.temDir, 178 | module: this.module, 179 | fileType: this.fileType, 180 | port: this.params.port, 181 | wsport: this.params.wsport, 182 | open: this.params.open, 183 | wsSuccessCallback () { 184 | self.wsSuccess = true; 185 | } 186 | }); 187 | } 188 | }; 189 | module.exports = function (args, port, options) { 190 | Previewer.init(args, port, options); 191 | }; 192 | -------------------------------------------------------------------------------- /vue-template/template/assets/phantom-limb.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | // Phantom Limb 3 | // ------------ 4 | // http://viewinglens.com/phantom-limb 5 | // https://github.com/brian-c/phantom-limb 6 | // brian.carstensen@gmail.com 7 | 8 | "use strict"; 9 | 10 | // Default configuration 11 | var config = { 12 | style: true, 13 | startOnLoad: true 14 | }; 15 | 16 | // Apply overrides 17 | for (var param in window.phantomLimbConfig) { 18 | config[param] = window.phantomLimbConfig[param]; 19 | } 20 | 21 | // Keep track of whether the mouse is down. 22 | var mouseIsDown = false; 23 | 24 | // A Finger is a representation on the screen. 25 | // It keeps track of its position and the node that it's over. 26 | function Finger() { 27 | this.node = document.createElement('span'); 28 | this.node.classList.add('_phantom-limb_finger'); 29 | this.place(); 30 | } 31 | 32 | Finger.prototype = { 33 | node: null, 34 | 35 | x: NaN, 36 | y: NaN, 37 | 38 | target: null, 39 | 40 | place: function() { 41 | document.body.appendChild(this.node); 42 | }, 43 | 44 | hide: function() { 45 | this.node.style.display = 'none'; 46 | }, 47 | 48 | show: function() { 49 | this.node.style.display = ''; 50 | }, 51 | 52 | move: function(x, y) { 53 | if (isNaN(x) || isNaN(y)) { 54 | this.hide(); 55 | this.target = null; 56 | } else { 57 | this.show(); 58 | 59 | this.node.style.left = x + 'px'; 60 | this.node.style.top = y + 'px'; 61 | 62 | this.x = x; 63 | this.y = y; 64 | 65 | if (!mouseIsDown) this.target = document.elementFromPoint(x, y); 66 | } 67 | } 68 | }; 69 | 70 | // We'll instantiate the fingers when we start. 71 | var fingers = []; 72 | 73 | // Create a synthetic event from a real event and a finger. 74 | function createMouseEvent(eventName, originalEvent, finger) { 75 | var e = document.createEvent('MouseEvent'); 76 | 77 | e.initMouseEvent(eventName, true, true, 78 | originalEvent.view, originalEvent.detail, 79 | finger.x || originalEvent.screenX, finger.y || originalEvent.screenY, 80 | finger.x || originalEvent.clientX, finger.y || originalEvent.clientY, 81 | originalEvent.ctrlKey, originalEvent.shiftKey, 82 | originalEvent.altKey, originalEvent.metaKey, 83 | originalEvent.button, finger.target || originalEvent.relatedTarget 84 | ); 85 | 86 | e.synthetic = true; 87 | 88 | // Set this so we can match shared targets later. 89 | e._finger = finger; 90 | 91 | return e; 92 | } 93 | 94 | var startDistance = NaN; 95 | var startAngle = NaN; 96 | 97 | // Given a mouse event, fire a touch event for each finger. 98 | // Add the appropriate touch-specific event properties. 99 | function fireTouchEvents(eventName, originalEvent) { 100 | // All touch events, including "touchend". 101 | var events = []; 102 | var gestures = []; 103 | 104 | // For each finger with a target, create a touch event. 105 | fingers.forEach(function(finger) { 106 | if (!finger.target) return; 107 | 108 | // Convert "ontouch*" properties and attributes to listeners. 109 | var onEventName = 'on' + eventName; 110 | 111 | if (onEventName in finger.target) { 112 | console.warn('Converting `' + onEventName + '` property to event listener.', finger.target); 113 | finger.target.addEventListener(eventName, finger.target[onEventName], false); 114 | delete finger.target[onEventName]; 115 | } 116 | 117 | if (finger.target.hasAttribute(onEventName)) { 118 | console.warn('Converting `' + onEventName + '` attribute to event listener.', finger.target); 119 | var handler = new Function('event', finger.target.getAttribute(onEventName)); 120 | finger.target.addEventListener(eventName, handler, false); 121 | finger.target.removeAttribute(onEventName); 122 | } 123 | 124 | // Set up a new event with the coordinates of the finger. 125 | var touch = createMouseEvent(eventName, originalEvent, finger); 126 | 127 | events.push(touch); 128 | }); 129 | 130 | // Figure out scale and rotation. 131 | if (events.length > 1) { 132 | var x = events[0].pageX - events[1].pageX; 133 | var y = events[0].pageY - events[1].pageY; 134 | 135 | var distance = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); 136 | var angle = Math.atan2(x, y) * (180 / Math.PI); 137 | 138 | var gestureName = 'gesturechange'; 139 | 140 | if (eventName === 'touchstart') { 141 | gestureName = 'gesturestart'; 142 | startDistance = distance; 143 | startAngle = angle; 144 | } 145 | 146 | if (eventName === 'touchend') gestureName = 'gestureend'; 147 | 148 | events.forEach(function(event) { 149 | var gesture = createMouseEvent(gestureName, event, event._finger); 150 | gestures.push(gesture); 151 | }); 152 | 153 | events.concat(gestures).forEach(function(event) { 154 | event.scale = distance / startDistance; 155 | event.rotation = startAngle - angle; 156 | }); 157 | } 158 | 159 | // Loop through the events array and fill in each touch array. 160 | events.forEach(function(touch) { 161 | touch.touches = events.filter(function(e) { 162 | return ~e.type.indexOf('touch') && e.type !== 'touchend'; 163 | }); 164 | 165 | touch.changedTouches = events.filter(function(e) { 166 | return ~e.type.indexOf('touch') && e._finger.target === touch._finger.target; 167 | }); 168 | 169 | touch.targetTouches = touch.changedTouches.filter(function(e) { 170 | return ~e.type.indexOf('touch') && e.type !== 'touchend'; 171 | }); 172 | }); 173 | 174 | // Then fire the events. 175 | events.concat(gestures).forEach(function(event, i) { 176 | event.identifier = i; 177 | event._finger.target.dispatchEvent(event); 178 | }); 179 | } 180 | 181 | // Prevent all mousedown event from doing anything. 182 | // We'll fire one manually at touchend. 183 | function phantomTouchStart(e) { 184 | if (e.synthetic) return; 185 | 186 | mouseIsDown = true; 187 | 188 | e.preventDefault(); 189 | e.stopPropagation(); 190 | 191 | fireTouchEvents('touchstart', e); 192 | } 193 | 194 | // The center between two fingers 195 | var centerX = NaN; 196 | var centerY = NaN; 197 | 198 | // Set each finger's position target. 199 | // Pressing alt engages the second finger. 200 | // Pressing shift locks the second finger's position relative to the first's. 201 | function moveFingers(e) { 202 | // We'll use this if the second is locked with the first. 203 | var changeX = e.clientX - fingers[0].x || 0; 204 | var changeY = e.clientY - fingers[0].y || 0; 205 | 206 | // The first finger just follows the mouse. 207 | fingers[0].move(e.clientX, e.clientY); 208 | 209 | // TODO: Determine modifier keys independent of mouse movement. 210 | 211 | if (e.altKey) { 212 | // Reset the center. 213 | if (!centerX && !centerY) { 214 | centerX = innerWidth / 2; 215 | centerY = innerHeight / 2; 216 | } 217 | 218 | // Lock the center with the first finger. 219 | if (e.shiftKey) { 220 | centerX += changeX; 221 | centerY += changeY; 222 | } 223 | 224 | var secondX = centerX + (centerX - e.clientX); 225 | var secondY = centerY + (centerY - e.clientY); 226 | 227 | fingers[1].move(secondX, secondY); 228 | } else { 229 | // Disengage the second finger. 230 | fingers[1].move(NaN, NaN); 231 | 232 | // Reset the center next time the alt key is held. 233 | centerX = NaN; 234 | centerY = NaN; 235 | } 236 | } 237 | 238 | // Prevent all mousemove events from firing. 239 | // We'll fire one (and only one) manually at touchend. 240 | function phantomTouchMove(e) { 241 | if (e.synthetic) return; 242 | 243 | e.preventDefault(); 244 | e.stopPropagation(); 245 | 246 | moveFingers(e); 247 | 248 | if (mouseIsDown) { 249 | fireTouchEvents('touchmove', e); 250 | } 251 | } 252 | 253 | // Prevent all mouseup events from firing. 254 | // We'll fire one manually at touchend. 255 | function phantomTouchEnd(e) { 256 | if (e.synthetic) return; 257 | 258 | mouseIsDown = false; 259 | 260 | e.preventDefault(); 261 | e.stopPropagation(); 262 | 263 | fireTouchEvents('touchend', e); 264 | 265 | fingers.forEach(function(finger) { 266 | if (!finger.target) return; 267 | 268 | // Mobile Safari moves all the mouse event to fire after the touchend event. 269 | finger.target.dispatchEvent(createMouseEvent('mouseover', e, finger)); 270 | finger.target.dispatchEvent(createMouseEvent('mousemove', e, finger)); 271 | finger.target.dispatchEvent(createMouseEvent('mousedown', e, finger)); 272 | 273 | // TODO: These two only fire if content didn't change. How can we tell? 274 | finger.target.dispatchEvent(createMouseEvent('mouseup', e, finger)); 275 | finger.target.dispatchEvent(createMouseEvent('click', e, finger)); 276 | }); 277 | } 278 | 279 | // Prevent clicks. We'll handle them manually. 280 | function phantomClick(e) { 281 | if (e.synthetic) return; 282 | 283 | e.preventDefault(); 284 | e.stopPropagation(); 285 | } 286 | 287 | // Not entirely proud of this, but I can't serve CSS from GitHub 288 | // and I want the bookmarklet to be as simple as possible. 289 | var defaultCSS = ([ 290 | '._phantom-limb,', 291 | '._phantom-limb a {', 292 | 'cursor: none !important;', 293 | '}', 294 | '._phantom-limb_finger {', 295 | 'background: rgba(128, 128, 128, 0.5);', 296 | 'border: 2px solid rgb(128, 128, 128);', 297 | 'border-radius: 50%;', 298 | 'display: none;', 299 | 'height: 44px;', 300 | 'margin: -22px 0 0 -22px;', 301 | 'pointer-events: none;', 302 | 'position: fixed;', 303 | 'width: 44px;', 304 | 'z-index: 999999' + 305 | '}', 306 | '._phantom-limb ._phantom-limb_finger {', 307 | 'display: block;', 308 | '}' 309 | ]).join('\n'); 310 | 311 | if (config.style) { 312 | var styleTag = document.createElement('style'); 313 | styleTag.id = '_phantom-limb_default-style'; 314 | styleTag.innerHTML = defaultCSS; 315 | document.querySelector('head').appendChild(styleTag); 316 | } 317 | 318 | // On/off switch 319 | function start() { 320 | if (fingers.length === 0) fingers.push(new Finger(), new Finger()); 321 | 322 | document.addEventListener('mousedown', phantomTouchStart, true); 323 | document.addEventListener('mousemove', phantomTouchMove, true); 324 | document.addEventListener('mouseup', phantomTouchEnd, true); 325 | document.addEventListener('click', phantomClick, true); 326 | 327 | document.documentElement.classList.add('_phantom-limb'); 328 | } 329 | 330 | function stop() { 331 | document.removeEventListener('mousedown', phantomTouchStart, true); 332 | document.removeEventListener('mousemove', phantomTouchMove, true); 333 | document.removeEventListener('mouseup', phantomTouchEnd, true); 334 | document.removeEventListener('click', phantomClick, true); 335 | 336 | document.documentElement.classList.remove('_phantom-limb'); 337 | } 338 | 339 | // Detect keyup, exit when esc. 340 | function phantomKeyUp(e) { 341 | if (e.keyCode === 27) { 342 | if (document.documentElement.classList.contains('_phantom-limb')) { 343 | stop(); 344 | } else { 345 | start(); 346 | } 347 | } 348 | } 349 | 350 | var phantomLimb = { 351 | start: start, 352 | stop: stop 353 | }; 354 | 355 | if (typeof define === 'function' && define.amd) define(phantomLimb); 356 | if (typeof module !== 'undefined') module.exports = phantomLimb; 357 | window.phantomLimb = phantomLimb; 358 | 359 | document.addEventListener('keyup', phantomKeyUp, false); 360 | 361 | if (config.startOnLoad) addEventListener('DOMContentLoaded', start, false); 362 | }()); 363 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | Weex 635 | Copyright (C) 2016 Alibaba.inc 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Weex Copyright (C) 2016 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . -------------------------------------------------------------------------------- /vue-template/template/assets/qrcode.js: -------------------------------------------------------------------------------- 1 | ;(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o margin) && margin > 0){ 297 | margin = this.scale * this.marginScaleFactor; 298 | } 299 | return margin; 300 | }, 301 | dataWidth:function(qr,scale){ 302 | return qr.getModuleCount()*(scale||this.scale||4); 303 | }, 304 | resetCanvas:function(canvas,ctx,width){ 305 | ctx.clearRect(0,0,canvas.width,canvas.height); 306 | if(!canvas.style) canvas.style = {}; 307 | canvas.style.height = canvas.height = width;//square! 308 | canvas.style.width = canvas.width = width; 309 | 310 | if(this.color.light){ 311 | ctx.fillStyle = this.color.light; 312 | ctx.fillRect(0,0,canvas.width,canvas.height); 313 | } else { 314 | //support transparent backgrounds? 315 | //not exactly to spec but i really would like someone to be able to add a background with heavily reduced luminosity for simple branding 316 | //i could just ditch this because you could also just set #******00 as the color =P 317 | ctx.clearRect(0,0,canvas.width,canvas.height); 318 | } 319 | } 320 | }; 321 | 322 | 323 | },{"./qrcapacitytable.js":1,"./qrcode.js":3,"bops":4}],3:[function(require,module,exports){ 324 | var bops = require('bops'); 325 | 326 | /** 327 | * QRCode for JavaScript 328 | * 329 | * modified by Ryan Day for nodejs support 330 | * Copyright (c) 2011 Ryan Day 331 | * 332 | * Licensed under the MIT license: 333 | * http://www.opensource.org/licenses/mit-license.php 334 | * 335 | * EXPORTS: 336 | * { 337 | * QRCode:QRCode 338 | * QRErrorCorrectLevel:QRErrorCorrectLevel 339 | * } 340 | //--------------------------------------------------------------------- 341 | // QRCode for JavaScript 342 | // 343 | // Copyright (c) 2009 Kazuhiko Arase 344 | // 345 | // URL: http://www.d-project.com/ 346 | // 347 | // Licensed under the MIT license: 348 | // http://www.opensource.org/licenses/mit-license.php 349 | // 350 | // The word "QR Code" is registered trademark of 351 | // DENSO WAVE INCORPORATED 352 | // http://www.denso-wave.com/qrcode/faqpatent-e.html 353 | // 354 | //--------------------------------------------------------------------- 355 | */ 356 | 357 | //--------------------------------------------------------------------- 358 | // QRCode 359 | //--------------------------------------------------------------------- 360 | 361 | exports.QRCode = QRCode; 362 | 363 | var QRDataArray = (typeof Uint32Array == 'undefined'?Uint32Array:Array); 364 | 365 | function QRCode(typeNumber, errorCorrectLevel) { 366 | this.typeNumber = typeNumber; 367 | this.errorCorrectLevel = errorCorrectLevel; 368 | this.modules = null; 369 | this.moduleCount = 0; 370 | this.dataCache = null; 371 | this.dataList = new QRDataArray(); 372 | } 373 | 374 | QRCode.prototype = { 375 | 376 | addData : function(data) { 377 | var newData = new QR8bitByte(data); 378 | 379 | this.dataList.push(newData); 380 | this.dataCache = null; 381 | }, 382 | 383 | isDark : function(row, col) { 384 | if (row < 0 || this.moduleCount <= row || col < 0 || this.moduleCount <= col) { 385 | throw new Error(row + "," + col); 386 | } 387 | return this.modules[row][col]; 388 | }, 389 | 390 | getModuleCount : function() { 391 | return this.moduleCount; 392 | }, 393 | 394 | make : function() { 395 | this.makeImpl(false, this.getBestMaskPattern() ); 396 | }, 397 | 398 | makeImpl : function(test, maskPattern) { 399 | 400 | this.moduleCount = this.typeNumber * 4 + 17; 401 | this.modules = new QRDataArray(this.moduleCount); 402 | 403 | for (var row = 0; row < this.moduleCount; row++) { 404 | 405 | this.modules[row] = new QRDataArray(this.moduleCount); 406 | 407 | for (var col = 0; col < this.moduleCount; col++) { 408 | this.modules[row][col] = null;//(col + row) % 3; 409 | } 410 | } 411 | 412 | this.setupPositionProbePattern(0, 0); 413 | this.setupPositionProbePattern(this.moduleCount - 7, 0); 414 | this.setupPositionProbePattern(0, this.moduleCount - 7); 415 | this.setupPositionAdjustPattern(); 416 | this.setupTimingPattern(); 417 | this.setupTypeInfo(test, maskPattern); 418 | 419 | if (this.typeNumber >= 7) { 420 | this.setupTypeNumber(test); 421 | } 422 | 423 | if (this.dataCache == null) { 424 | this.dataCache = QRCode.createData(this.typeNumber, this.errorCorrectLevel, this.dataList); 425 | } 426 | 427 | this.mapData(this.dataCache, maskPattern); 428 | }, 429 | 430 | setupPositionProbePattern : function(row, col) { 431 | 432 | for (var r = -1; r <= 7; r++) { 433 | 434 | if (row + r <= -1 || this.moduleCount <= row + r) continue; 435 | 436 | for (var c = -1; c <= 7; c++) { 437 | 438 | if (col + c <= -1 || this.moduleCount <= col + c) continue; 439 | 440 | if ( (0 <= r && r <= 6 && (c == 0 || c == 6) ) 441 | || (0 <= c && c <= 6 && (r == 0 || r == 6) ) 442 | || (2 <= r && r <= 4 && 2 <= c && c <= 4) ) { 443 | this.modules[row + r][col + c] = true; 444 | } else { 445 | this.modules[row + r][col + c] = false; 446 | } 447 | } 448 | } 449 | }, 450 | 451 | getBestMaskPattern : function() { 452 | 453 | var minLostPoint = 0; 454 | var pattern = 0; 455 | 456 | for (var i = 0; i < 8; i++) { 457 | 458 | this.makeImpl(true, i); 459 | 460 | var lostPoint = QRUtil.getLostPoint(this); 461 | 462 | if (i == 0 || minLostPoint > lostPoint) { 463 | minLostPoint = lostPoint; 464 | pattern = i; 465 | } 466 | } 467 | 468 | return pattern; 469 | }, 470 | 471 | setupTimingPattern : function() { 472 | 473 | for (var r = 8; r < this.moduleCount - 8; r++) { 474 | if (this.modules[r][6] != null) { 475 | continue; 476 | } 477 | this.modules[r][6] = (r % 2 == 0); 478 | } 479 | 480 | for (var c = 8; c < this.moduleCount - 8; c++) { 481 | if (this.modules[6][c] != null) { 482 | continue; 483 | } 484 | this.modules[6][c] = (c % 2 == 0); 485 | } 486 | }, 487 | 488 | setupPositionAdjustPattern : function() { 489 | 490 | var pos = QRUtil.getPatternPosition(this.typeNumber); 491 | pos = pos || ''; 492 | for (var i = 0; i < pos.length; i++) { 493 | 494 | for (var j = 0; j < pos.length; j++) { 495 | 496 | var row = pos[i]; 497 | var col = pos[j]; 498 | 499 | if (this.modules[row][col] != null) { 500 | continue; 501 | } 502 | 503 | for (var r = -2; r <= 2; r++) { 504 | 505 | for (var c = -2; c <= 2; c++) { 506 | 507 | if (r == -2 || r == 2 || c == -2 || c == 2 508 | || (r == 0 && c == 0) ) { 509 | this.modules[row + r][col + c] = true; 510 | } else { 511 | this.modules[row + r][col + c] = false; 512 | } 513 | } 514 | } 515 | } 516 | } 517 | }, 518 | 519 | setupTypeNumber : function(test) { 520 | 521 | var bits = QRUtil.getBCHTypeNumber(this.typeNumber); 522 | 523 | for (var i = 0; i < 18; i++) { 524 | var mod = (!test && ( (bits >> i) & 1) == 1); 525 | this.modules[Math.floor(i / 3)][i % 3 + this.moduleCount - 8 - 3] = mod; 526 | } 527 | 528 | for (var i = 0; i < 18; i++) { 529 | var mod = (!test && ( (bits >> i) & 1) == 1); 530 | this.modules[i % 3 + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod; 531 | } 532 | }, 533 | 534 | setupTypeInfo : function(test, maskPattern) { 535 | 536 | var data = (this.errorCorrectLevel << 3) | maskPattern; 537 | var bits = QRUtil.getBCHTypeInfo(data); 538 | 539 | // vertical 540 | for (var i = 0; i < 15; i++) { 541 | 542 | var mod = (!test && ( (bits >> i) & 1) == 1); 543 | 544 | if (i < 6) { 545 | this.modules[i][8] = mod; 546 | } else if (i < 8) { 547 | this.modules[i + 1][8] = mod; 548 | } else { 549 | this.modules[this.moduleCount - 15 + i][8] = mod; 550 | } 551 | } 552 | 553 | // horizontal 554 | for (var i = 0; i < 15; i++) { 555 | 556 | var mod = (!test && ( (bits >> i) & 1) == 1); 557 | 558 | if (i < 8) { 559 | this.modules[8][this.moduleCount - i - 1] = mod; 560 | } else if (i < 9) { 561 | this.modules[8][15 - i - 1 + 1] = mod; 562 | } else { 563 | this.modules[8][15 - i - 1] = mod; 564 | } 565 | } 566 | 567 | // fixed module 568 | this.modules[this.moduleCount - 8][8] = (!test); 569 | 570 | }, 571 | 572 | mapData : function(data, maskPattern) { 573 | 574 | var inc = -1; 575 | var row = this.moduleCount - 1; 576 | var bitIndex = 7; 577 | var byteIndex = 0; 578 | 579 | for (var col = this.moduleCount - 1; col > 0; col -= 2) { 580 | 581 | if (col == 6) col--; 582 | 583 | while (true) { 584 | 585 | for (var c = 0; c < 2; c++) { 586 | 587 | if (this.modules[row][col - c] == null) { 588 | 589 | var dark = false; 590 | 591 | if (byteIndex < data.length) { 592 | dark = ( ( (data[byteIndex] >>> bitIndex) & 1) == 1); 593 | } 594 | 595 | var mask = QRUtil.getMask(maskPattern, row, col - c); 596 | 597 | if (mask) { 598 | dark = !dark; 599 | } 600 | 601 | this.modules[row][col - c] = dark; 602 | bitIndex--; 603 | 604 | if (bitIndex == -1) { 605 | byteIndex++; 606 | bitIndex = 7; 607 | } 608 | } 609 | } 610 | 611 | row += inc; 612 | 613 | if (row < 0 || this.moduleCount <= row) { 614 | row -= inc; 615 | inc = -inc; 616 | break; 617 | } 618 | } 619 | } 620 | 621 | } 622 | 623 | }; 624 | 625 | QRCode.PAD0 = 0xEC; 626 | QRCode.PAD1 = 0x11; 627 | 628 | QRCode.createData = function(typeNumber, errorCorrectLevel, dataList) { 629 | 630 | var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel); 631 | 632 | var buffer = new QRBitBuffer(); 633 | 634 | for (var i = 0; i < dataList.length; i++) { 635 | var data = dataList[i]; 636 | buffer.put(data.mode, 4); 637 | buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber) ); 638 | data.write(buffer); 639 | } 640 | 641 | // calc num max data. 642 | var totalDataCount = 0; 643 | for (var i = 0; i < rsBlocks.length; i++) { 644 | totalDataCount += rsBlocks[i].dataCount; 645 | } 646 | 647 | if (buffer.getLengthInBits() > totalDataCount * 8) { 648 | throw new Error("code length overflow. (" 649 | + buffer.getLengthInBits() 650 | + ">" 651 | + totalDataCount * 8 652 | + ")"); 653 | } 654 | 655 | // end code 656 | if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) { 657 | buffer.put(0, 4); 658 | } 659 | 660 | // padding 661 | while (buffer.getLengthInBits() % 8 != 0) { 662 | buffer.putBit(false); 663 | } 664 | 665 | // padding 666 | while (true) { 667 | 668 | if (buffer.getLengthInBits() >= totalDataCount * 8) { 669 | break; 670 | } 671 | buffer.put(QRCode.PAD0, 8); 672 | 673 | if (buffer.getLengthInBits() >= totalDataCount * 8) { 674 | break; 675 | } 676 | buffer.put(QRCode.PAD1, 8); 677 | } 678 | 679 | return QRCode.createBytes(buffer, rsBlocks); 680 | }; 681 | 682 | QRCode.createBytes = function(buffer, rsBlocks) { 683 | 684 | var offset = 0; 685 | 686 | var maxDcCount = 0; 687 | var maxEcCount = 0; 688 | 689 | var dcdata = new QRDataArray(rsBlocks.length); 690 | var ecdata = new QRDataArray(rsBlocks.length); 691 | 692 | for (var r = 0; r < rsBlocks.length; r++) { 693 | 694 | var dcCount = rsBlocks[r].dataCount; 695 | var ecCount = rsBlocks[r].totalCount - dcCount; 696 | 697 | maxDcCount = Math.max(maxDcCount, dcCount); 698 | maxEcCount = Math.max(maxEcCount, ecCount); 699 | 700 | dcdata[r] = new QRDataArray(dcCount); 701 | 702 | for (var i = 0; i < dcdata[r].length; i++) { 703 | dcdata[r][i] = 0xff & buffer.buffer[i + offset]; 704 | } 705 | offset += dcCount; 706 | 707 | var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount); 708 | var rawPoly = new QRPolynomial(dcdata[r], rsPoly.getLength() - 1); 709 | 710 | var modPoly = rawPoly.mod(rsPoly); 711 | ecdata[r] = new QRDataArray(rsPoly.getLength() - 1); 712 | for (var i = 0; i < ecdata[r].length; i++) { 713 | var modIndex = i + modPoly.getLength() - ecdata[r].length; 714 | ecdata[r][i] = (modIndex >= 0)? modPoly.get(modIndex) : 0; 715 | } 716 | 717 | } 718 | 719 | var totalCodeCount = 0; 720 | for (var i = 0; i < rsBlocks.length; i++) { 721 | totalCodeCount += rsBlocks[i].totalCount; 722 | } 723 | 724 | var data = new QRDataArray(totalCodeCount); 725 | var index = 0; 726 | 727 | for (var i = 0; i < maxDcCount; i++) { 728 | for (var r = 0; r < rsBlocks.length; r++) { 729 | if (i < dcdata[r].length) { 730 | data[index++] = dcdata[r][i]; 731 | } 732 | } 733 | } 734 | 735 | for (var i = 0; i < maxEcCount; i++) { 736 | for (var r = 0; r < rsBlocks.length; r++) { 737 | if (i < ecdata[r].length) { 738 | data[index++] = ecdata[r][i]; 739 | } 740 | } 741 | } 742 | 743 | return data; 744 | 745 | }; 746 | 747 | //--------------------------------------------------------------------- 748 | // QR8bitByte 749 | //--------------------------------------------------------------------- 750 | function QR8bitByte(data) { 751 | this.mode = QRMode.MODE_8BIT_BYTE; 752 | this.data = data; 753 | var byteArray = []; 754 | 755 | this.parsedData = bops.from(data); 756 | } 757 | 758 | QR8bitByte.prototype = { 759 | getLength: function (buffer) { 760 | return this.parsedData.length; 761 | }, 762 | write: function (buffer) { 763 | for (var i = 0, l = this.parsedData.length; i < l; i++) { 764 | buffer.put(this.parsedData[i], 8); 765 | } 766 | } 767 | }; 768 | 769 | 770 | //--------------------------------------------------------------------- 771 | // QRMode 772 | //--------------------------------------------------------------------- 773 | 774 | var QRMode = { 775 | MODE_NUMBER : 1 << 0, 776 | MODE_ALPHA_NUM : 1 << 1, 777 | MODE_8BIT_BYTE : 1 << 2, 778 | MODE_KANJI : 1 << 3 779 | }; 780 | 781 | //--------------------------------------------------------------------- 782 | // QRErrorCorrectLevel 783 | //--------------------------------------------------------------------- 784 | //exported 785 | 786 | var QRErrorCorrectLevel = exports.QRErrorCorrectLevel = { 787 | L : 1, 788 | M : 0, 789 | Q : 3, 790 | H : 2 791 | }; 792 | 793 | //--------------------------------------------------------------------- 794 | // QRMaskPattern 795 | //--------------------------------------------------------------------- 796 | 797 | var QRMaskPattern = { 798 | PATTERN000 : 0, 799 | PATTERN001 : 1, 800 | PATTERN010 : 2, 801 | PATTERN011 : 3, 802 | PATTERN100 : 4, 803 | PATTERN101 : 5, 804 | PATTERN110 : 6, 805 | PATTERN111 : 7 806 | }; 807 | 808 | //--------------------------------------------------------------------- 809 | // QRUtil 810 | //--------------------------------------------------------------------- 811 | 812 | var QRUtil = { 813 | 814 | PATTERN_POSITION_TABLE : [ 815 | [], 816 | [6, 18], 817 | [6, 22], 818 | [6, 26], 819 | [6, 30], 820 | [6, 34], 821 | [6, 22, 38], 822 | [6, 24, 42], 823 | [6, 26, 46], 824 | [6, 28, 50], 825 | [6, 30, 54], 826 | [6, 32, 58], 827 | [6, 34, 62], 828 | [6, 26, 46, 66], 829 | [6, 26, 48, 70], 830 | [6, 26, 50, 74], 831 | [6, 30, 54, 78], 832 | [6, 30, 56, 82], 833 | [6, 30, 58, 86], 834 | [6, 34, 62, 90], 835 | [6, 28, 50, 72, 94], 836 | [6, 26, 50, 74, 98], 837 | [6, 30, 54, 78, 102], 838 | [6, 28, 54, 80, 106], 839 | [6, 32, 58, 84, 110], 840 | [6, 30, 58, 86, 114], 841 | [6, 34, 62, 90, 118], 842 | [6, 26, 50, 74, 98, 122], 843 | [6, 30, 54, 78, 102, 126], 844 | [6, 26, 52, 78, 104, 130], 845 | [6, 30, 56, 82, 108, 134], 846 | [6, 34, 60, 86, 112, 138], 847 | [6, 30, 58, 86, 114, 142], 848 | [6, 34, 62, 90, 118, 146], 849 | [6, 30, 54, 78, 102, 126, 150], 850 | [6, 24, 50, 76, 102, 128, 154], 851 | [6, 28, 54, 80, 106, 132, 158], 852 | [6, 32, 58, 84, 110, 136, 162], 853 | [6, 26, 54, 82, 110, 138, 166], 854 | [6, 30, 58, 86, 114, 142, 170] 855 | ], 856 | 857 | G15 : (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0), 858 | G18 : (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0), 859 | G15_MASK : (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1), 860 | 861 | getBCHTypeInfo : function(data) { 862 | var d = data << 10; 863 | while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) { 864 | d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) ) ); 865 | } 866 | return ( (data << 10) | d) ^ QRUtil.G15_MASK; 867 | }, 868 | 869 | getBCHTypeNumber : function(data) { 870 | var d = data << 12; 871 | while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) { 872 | d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) ) ); 873 | } 874 | return (data << 12) | d; 875 | }, 876 | 877 | getBCHDigit : function(data) { 878 | 879 | var digit = 0; 880 | 881 | while (data != 0) { 882 | digit++; 883 | data >>>= 1; 884 | } 885 | 886 | return digit; 887 | }, 888 | 889 | getPatternPosition : function(typeNumber) { 890 | return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1]; 891 | }, 892 | 893 | getMask : function(maskPattern, i, j) { 894 | 895 | switch (maskPattern) { 896 | 897 | case QRMaskPattern.PATTERN000 : return (i + j) % 2 == 0; 898 | case QRMaskPattern.PATTERN001 : return i % 2 == 0; 899 | case QRMaskPattern.PATTERN010 : return j % 3 == 0; 900 | case QRMaskPattern.PATTERN011 : return (i + j) % 3 == 0; 901 | case QRMaskPattern.PATTERN100 : return (Math.floor(i / 2) + Math.floor(j / 3) ) % 2 == 0; 902 | case QRMaskPattern.PATTERN101 : return (i * j) % 2 + (i * j) % 3 == 0; 903 | case QRMaskPattern.PATTERN110 : return ( (i * j) % 2 + (i * j) % 3) % 2 == 0; 904 | case QRMaskPattern.PATTERN111 : return ( (i * j) % 3 + (i + j) % 2) % 2 == 0; 905 | 906 | default : 907 | throw new Error("bad maskPattern:" + maskPattern); 908 | } 909 | }, 910 | 911 | getErrorCorrectPolynomial : function(errorCorrectLength) { 912 | 913 | var a = new QRPolynomial([1], 0); 914 | 915 | for (var i = 0; i < errorCorrectLength; i++) { 916 | a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0) ); 917 | } 918 | 919 | return a; 920 | }, 921 | 922 | getLengthInBits : function(mode, type) { 923 | 924 | if (1 <= type && type < 10) { 925 | 926 | // 1 - 9 927 | 928 | switch(mode) { 929 | case QRMode.MODE_NUMBER : return 10; 930 | case QRMode.MODE_ALPHA_NUM : return 9; 931 | case QRMode.MODE_8BIT_BYTE : return 8; 932 | case QRMode.MODE_KANJI : return 8; 933 | default : 934 | throw new Error("mode:" + mode); 935 | } 936 | 937 | } else if (type < 27) { 938 | 939 | // 10 - 26 940 | 941 | switch(mode) { 942 | case QRMode.MODE_NUMBER : return 12; 943 | case QRMode.MODE_ALPHA_NUM : return 11; 944 | case QRMode.MODE_8BIT_BYTE : return 16; 945 | case QRMode.MODE_KANJI : return 10; 946 | default : 947 | throw new Error("mode:" + mode); 948 | } 949 | 950 | } else if (type < 41) { 951 | 952 | // 27 - 40 953 | 954 | switch(mode) { 955 | case QRMode.MODE_NUMBER : return 14; 956 | case QRMode.MODE_ALPHA_NUM : return 13; 957 | case QRMode.MODE_8BIT_BYTE : return 16; 958 | case QRMode.MODE_KANJI : return 12; 959 | default : 960 | throw new Error("mode:" + mode); 961 | } 962 | 963 | } else { 964 | throw new Error("type:" + type); 965 | } 966 | }, 967 | 968 | getLostPoint : function(qrCode) { 969 | 970 | var moduleCount = qrCode.getModuleCount(); 971 | 972 | var lostPoint = 0; 973 | 974 | // LEVEL1 975 | 976 | for (var row = 0; row < moduleCount; row++) { 977 | 978 | for (var col = 0; col < moduleCount; col++) { 979 | 980 | var sameCount = 0; 981 | var dark = qrCode.isDark(row, col); 982 | 983 | for (var r = -1; r <= 1; r++) { 984 | 985 | if (row + r < 0 || moduleCount <= row + r) { 986 | continue; 987 | } 988 | 989 | for (var c = -1; c <= 1; c++) { 990 | 991 | if (col + c < 0 || moduleCount <= col + c) { 992 | continue; 993 | } 994 | 995 | if (r == 0 && c == 0) { 996 | continue; 997 | } 998 | 999 | if (dark == qrCode.isDark(row + r, col + c) ) { 1000 | sameCount++; 1001 | } 1002 | } 1003 | } 1004 | 1005 | if (sameCount > 5) { 1006 | lostPoint += (3 + sameCount - 5); 1007 | } 1008 | } 1009 | } 1010 | 1011 | // LEVEL2 1012 | 1013 | for (var row = 0; row < moduleCount - 1; row++) { 1014 | for (var col = 0; col < moduleCount - 1; col++) { 1015 | var count = 0; 1016 | if (qrCode.isDark(row, col ) ) count++; 1017 | if (qrCode.isDark(row + 1, col ) ) count++; 1018 | if (qrCode.isDark(row, col + 1) ) count++; 1019 | if (qrCode.isDark(row + 1, col + 1) ) count++; 1020 | if (count == 0 || count == 4) { 1021 | lostPoint += 3; 1022 | } 1023 | } 1024 | } 1025 | 1026 | // LEVEL3 1027 | 1028 | for (var row = 0; row < moduleCount; row++) { 1029 | for (var col = 0; col < moduleCount - 6; col++) { 1030 | if (qrCode.isDark(row, col) 1031 | && !qrCode.isDark(row, col + 1) 1032 | && qrCode.isDark(row, col + 2) 1033 | && qrCode.isDark(row, col + 3) 1034 | && qrCode.isDark(row, col + 4) 1035 | && !qrCode.isDark(row, col + 5) 1036 | && qrCode.isDark(row, col + 6) ) { 1037 | lostPoint += 40; 1038 | } 1039 | } 1040 | } 1041 | 1042 | for (var col = 0; col < moduleCount; col++) { 1043 | for (var row = 0; row < moduleCount - 6; row++) { 1044 | if (qrCode.isDark(row, col) 1045 | && !qrCode.isDark(row + 1, col) 1046 | && qrCode.isDark(row + 2, col) 1047 | && qrCode.isDark(row + 3, col) 1048 | && qrCode.isDark(row + 4, col) 1049 | && !qrCode.isDark(row + 5, col) 1050 | && qrCode.isDark(row + 6, col) ) { 1051 | lostPoint += 40; 1052 | } 1053 | } 1054 | } 1055 | 1056 | // LEVEL4 1057 | 1058 | var darkCount = 0; 1059 | 1060 | for (var col = 0; col < moduleCount; col++) { 1061 | for (var row = 0; row < moduleCount; row++) { 1062 | if (qrCode.isDark(row, col) ) { 1063 | darkCount++; 1064 | } 1065 | } 1066 | } 1067 | 1068 | var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5; 1069 | lostPoint += ratio * 10; 1070 | 1071 | return lostPoint; 1072 | } 1073 | 1074 | }; 1075 | 1076 | 1077 | //--------------------------------------------------------------------- 1078 | // QRMath 1079 | //--------------------------------------------------------------------- 1080 | 1081 | var QRMath = { 1082 | 1083 | glog : function(n) { 1084 | 1085 | if (n < 1) { 1086 | throw new Error("glog(" + n + ")"); 1087 | } 1088 | 1089 | return QRMath.LOG_TABLE[n]; 1090 | }, 1091 | 1092 | gexp : function(n) { 1093 | 1094 | while (n < 0) { 1095 | n += 255; 1096 | } 1097 | 1098 | while (n >= 256) { 1099 | n -= 255; 1100 | } 1101 | 1102 | return QRMath.EXP_TABLE[n]; 1103 | }, 1104 | 1105 | EXP_TABLE : new Array(256), 1106 | 1107 | LOG_TABLE : new Array(256) 1108 | 1109 | }; 1110 | 1111 | for (var i = 0; i < 8; i++) { 1112 | QRMath.EXP_TABLE[i] = 1 << i; 1113 | } 1114 | for (var i = 8; i < 256; i++) { 1115 | QRMath.EXP_TABLE[i] = QRMath.EXP_TABLE[i - 4] 1116 | ^ QRMath.EXP_TABLE[i - 5] 1117 | ^ QRMath.EXP_TABLE[i - 6] 1118 | ^ QRMath.EXP_TABLE[i - 8]; 1119 | } 1120 | for (var i = 0; i < 255; i++) { 1121 | QRMath.LOG_TABLE[QRMath.EXP_TABLE[i] ] = i; 1122 | } 1123 | 1124 | //--------------------------------------------------------------------- 1125 | // QRPolynomial 1126 | //--------------------------------------------------------------------- 1127 | 1128 | function QRPolynomial(num, shift) { 1129 | 1130 | if (num.length == undefined) { 1131 | throw new Error(num.length + "/" + shift); 1132 | } 1133 | 1134 | var offset = 0; 1135 | 1136 | while (offset < num.length && num[offset] == 0) { 1137 | offset++; 1138 | } 1139 | 1140 | this.num = new Array(num.length - offset + shift); 1141 | for (var i = 0; i < num.length - offset; i++) { 1142 | this.num[i] = num[i + offset]; 1143 | } 1144 | } 1145 | 1146 | QRPolynomial.prototype = { 1147 | 1148 | get : function(index) { 1149 | return this.num[index]; 1150 | }, 1151 | 1152 | getLength : function() { 1153 | return this.num.length; 1154 | }, 1155 | 1156 | multiply : function(e) { 1157 | 1158 | var num = new Array(this.getLength() + e.getLength() - 1); 1159 | 1160 | for (var i = 0; i < this.getLength(); i++) { 1161 | for (var j = 0; j < e.getLength(); j++) { 1162 | num[i + j] ^= QRMath.gexp(QRMath.glog(this.get(i) ) + QRMath.glog(e.get(j) ) ); 1163 | } 1164 | } 1165 | 1166 | return new QRPolynomial(num, 0); 1167 | }, 1168 | 1169 | mod : function(e) { 1170 | 1171 | if (this.getLength() - e.getLength() < 0) { 1172 | return this; 1173 | } 1174 | 1175 | var ratio = QRMath.glog(this.get(0) ) - QRMath.glog(e.get(0) ); 1176 | 1177 | var num = new Array(this.getLength() ); 1178 | 1179 | for (var i = 0; i < this.getLength(); i++) { 1180 | num[i] = this.get(i); 1181 | } 1182 | 1183 | for (var i = 0; i < e.getLength(); i++) { 1184 | num[i] ^= QRMath.gexp(QRMath.glog(e.get(i) ) + ratio); 1185 | } 1186 | 1187 | // recursive call 1188 | return new QRPolynomial(num, 0).mod(e); 1189 | } 1190 | }; 1191 | 1192 | //--------------------------------------------------------------------- 1193 | // QRRSBlock 1194 | //--------------------------------------------------------------------- 1195 | 1196 | function QRRSBlock(totalCount, dataCount) { 1197 | this.totalCount = totalCount; 1198 | this.dataCount = dataCount; 1199 | } 1200 | 1201 | QRRSBlock.RS_BLOCK_TABLE = [ 1202 | // L 1203 | // M 1204 | // Q 1205 | // H 1206 | 1207 | // 1 1208 | [1, 26, 19], 1209 | [1, 26, 16], 1210 | [1, 26, 13], 1211 | [1, 26, 9], 1212 | // 2 1213 | [1, 44, 34], 1214 | [1, 44, 28], 1215 | [1, 44, 22], 1216 | [1, 44, 16], 1217 | // 3 1218 | [1, 70, 55], 1219 | [1, 70, 44], 1220 | [2, 35, 17], 1221 | [2, 35, 13], 1222 | // 4 1223 | [1, 100, 80], 1224 | [2, 50, 32], 1225 | [2, 50, 24], 1226 | [4, 25, 9], 1227 | // 5 1228 | [1, 134, 108], 1229 | [2, 67, 43], 1230 | [2, 33, 15, 2, 34, 16], 1231 | [2, 33, 11, 2, 34, 12], 1232 | // 6 1233 | [2, 86, 68], 1234 | [4, 43, 27], 1235 | [4, 43, 19], 1236 | [4, 43, 15], 1237 | // 7 1238 | [2, 98, 78], 1239 | [4, 49, 31], 1240 | [2, 32, 14, 4, 33, 15], 1241 | [4, 39, 13, 1, 40, 14], 1242 | // 8 1243 | [2, 121, 97], 1244 | [2, 60, 38, 2, 61, 39], 1245 | [4, 40, 18, 2, 41, 19], 1246 | [4, 40, 14, 2, 41, 15], 1247 | // 9 1248 | [2, 146, 116], 1249 | [3, 58, 36, 2, 59, 37], 1250 | [4, 36, 16, 4, 37, 17], 1251 | [4, 36, 12, 4, 37, 13], 1252 | // 10 1253 | [2, 86, 68, 2, 87, 69], 1254 | [4, 69, 43, 1, 70, 44], 1255 | [6, 43, 19, 2, 44, 20], 1256 | [6, 43, 15, 2, 44, 16] 1257 | //NOTE added by Ryan Day.to make greater than version 10 qrcodes 1258 | // this table starts on page 40 of the spec PDF. google ISO/IEC 18004 1259 | // 11 1260 | ,[4,101,81] 1261 | ,[1,80,50,4,81,51] 1262 | ,[4,50,22,4,51,23] 1263 | ,[3,36,12,8,37,13] 1264 | //12 1265 | ,[2,116,92,2,117,93] 1266 | ,[6,58,36,2,59,37] 1267 | ,[4,46,20,6,47,21] 1268 | ,[7,42,14,4,43,15] 1269 | //13 1270 | ,[4,133,107] 1271 | ,[8,59,37,1,60,38] 1272 | ,[8,44,20,4,45,21] 1273 | ,[12,33,11,4,34,12] 1274 | //14 1275 | ,[3,145,115,1,146,116] 1276 | ,[4,64,40,5,65,41] 1277 | ,[11,36,16,5,37,17] 1278 | ,[11,36,12,5,37,13] 1279 | //15 1280 | ,[5,109,87,1,110,88] 1281 | ,[5,65,41,5,66,42] 1282 | ,[5,54,24,7,55,25] 1283 | ,[11,36,12,7,37,13] 1284 | //16 1285 | ,[5,122,98,1,123,99] 1286 | ,[7,73,45,3,74,46] 1287 | ,[15,43,19,2,44,20] 1288 | ,[3,45,15,13,46,16] 1289 | //17 1290 | ,[1,135,107,5,136,108] 1291 | ,[10,74,46,1,75,47] 1292 | ,[1,50,22,15,51,23] 1293 | ,[2,42,14,17,43,15] 1294 | //18 1295 | ,[5,150,120,1,151,121] 1296 | ,[9,69,43,4,70,44] 1297 | ,[17,50,22,1,51,23] 1298 | ,[2,42,14,19,43,15] 1299 | //19 1300 | ,[3,141,113,4,142,114] 1301 | ,[3,70,44,11,71,45] 1302 | ,[17,47,21,4,48,22] 1303 | ,[9,39,13,16,40,14] 1304 | //20 1305 | ,[3,135,107,5,136,108] 1306 | ,[3,67,41,13,68,42] 1307 | ,[15,54,24,5,55,25] 1308 | ,[15,43,15,10,44,16] 1309 | //21 1310 | ,[4,144,116,4,145,117] 1311 | ,[17,68,42] 1312 | ,[17,50,22,6,51,23] 1313 | ,[19,46,16,6,47,17] 1314 | //22 1315 | ,[2,139,111,7,140,112] 1316 | ,[17,74,46] 1317 | ,[7,54,24,16,55,25] 1318 | ,[34,37,13] 1319 | //23 1320 | ,[4,151,121,5,152,122] 1321 | ,[4,75,47,14,76,48] 1322 | ,[11,54,24,14,55,25] 1323 | ,[16,45,15,14,46,16] 1324 | //24 1325 | ,[6,147,117,4,148,118] 1326 | ,[6,73,45,14,74,46] 1327 | ,[11,54,24,16,55,25] 1328 | ,[30,46,16,2,47,17] 1329 | //25 1330 | ,[8,132,106,4,133,107] 1331 | ,[8,75,47,13,76,48] 1332 | ,[7,54,24,22,55,25] 1333 | ,[22,45,15,13,46,16] 1334 | //26 1335 | ,[10,142,114,2,143,115] 1336 | ,[19,74,46,4,75,47] 1337 | ,[28,50,22,6,51,23] 1338 | ,[33,46,16,4,47,17] 1339 | //27 1340 | ,[8,152,122,4,153,123] 1341 | ,[22,73,45,3,74,46] 1342 | ,[8,53,23,26,54,24] 1343 | ,[12,45,15,28,46,16] 1344 | //28 1345 | ,[3,147,117,10,148,118] 1346 | ,[3,73,45,23,74,46] 1347 | ,[4,54,24,31,55,25] 1348 | ,[11,45,15,31,46,16] 1349 | //29 1350 | ,[7,146,116,7,147,117] 1351 | ,[21,73,45,7,74,46] 1352 | ,[1,53,23,37,54,24] 1353 | ,[19,45,15,26,46,16] 1354 | //30 1355 | ,[5,145,115,10,146,116] 1356 | ,[19,75,47,10,76,48] 1357 | ,[15,54,24,25,55,25] 1358 | ,[23,45,15,25,46,16] 1359 | //31 1360 | ,[13,145,115,3,146,116] 1361 | ,[2,74,46,29,75,47] 1362 | ,[42,54,24,1,55,25] 1363 | ,[23,45,15,28,46,16] 1364 | //32 1365 | ,[17,145,115] 1366 | ,[10,74,46,23,75,47] 1367 | ,[10,54,24,35,55,25] 1368 | ,[19,45,15,35,46,16] 1369 | //33 1370 | ,[17,145,115,1,146,116] 1371 | ,[14,74,46,21,75,47] 1372 | ,[29,54,24,19,55,25] 1373 | ,[11,45,15,46,46,16] 1374 | //34 1375 | ,[13,145,115,6,146,116] 1376 | ,[14,74,46,23,75,47] 1377 | ,[44,54,24,7,55,25] 1378 | ,[59,46,16,1,47,17] 1379 | //35 1380 | ,[12,151,121,7,152,122] 1381 | ,[12,75,47,26,76,48] 1382 | ,[39,54,24,14,55,25] 1383 | ,[22,45,15,41,46,16] 1384 | //36 1385 | ,[6,151,121,14,152,122] 1386 | ,[6,75,47,34,76,48] 1387 | ,[46,54,24,10,55,25] 1388 | ,[2,45,15,64,46,16] 1389 | //37 1390 | ,[17,152,122,4,153,123] 1391 | ,[29,74,46,14,75,47] 1392 | ,[49,54,24,10,55,25] 1393 | ,[24,45,15,46,46,16] 1394 | //38 1395 | ,[4,152,122,18,153,123] 1396 | ,[13,74,46,32,75,47] 1397 | ,[48,54,24,14,55,25] 1398 | ,[42,45,15,32,46,16] 1399 | //39 1400 | ,[20,147,117,4,148,118] 1401 | ,[40,75,47,7,76,48] 1402 | ,[43,54,24,22,55,25] 1403 | ,[10,45,15,67,46,16] 1404 | //40 1405 | ,[19,148,118,6,149,119] 1406 | ,[18,75,47,31,76,48] 1407 | ,[34,54,24,34,55,25] 1408 | ,[20,45,15,61,46,16] 1409 | ]; 1410 | 1411 | QRRSBlock.getRSBlocks = function(typeNumber, errorCorrectLevel) { 1412 | 1413 | var rsBlock = QRRSBlock.getRsBlockTable(typeNumber, errorCorrectLevel); 1414 | 1415 | if (rsBlock == undefined) { 1416 | throw new Error("bad rs block @ typeNumber:" + typeNumber + "/errorCorrectLevel:" + errorCorrectLevel); 1417 | } 1418 | 1419 | var length = rsBlock.length / 3; 1420 | 1421 | var list = new Array(); 1422 | 1423 | for (var i = 0; i < length; i++) { 1424 | 1425 | var count = rsBlock[i * 3 + 0]; 1426 | var totalCount = rsBlock[i * 3 + 1]; 1427 | var dataCount = rsBlock[i * 3 + 2]; 1428 | 1429 | for (var j = 0; j < count; j++) { 1430 | list.push(new QRRSBlock(totalCount, dataCount) ); 1431 | } 1432 | } 1433 | 1434 | return list; 1435 | } 1436 | 1437 | QRRSBlock.getRsBlockTable = function(typeNumber, errorCorrectLevel) { 1438 | 1439 | switch(errorCorrectLevel) { 1440 | case QRErrorCorrectLevel.L : 1441 | return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0]; 1442 | case QRErrorCorrectLevel.M : 1443 | return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1]; 1444 | case QRErrorCorrectLevel.Q : 1445 | return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2]; 1446 | case QRErrorCorrectLevel.H : 1447 | return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3]; 1448 | default : 1449 | return undefined; 1450 | } 1451 | } 1452 | 1453 | //--------------------------------------------------------------------- 1454 | // QRBitBuffer 1455 | //--------------------------------------------------------------------- 1456 | 1457 | function QRBitBuffer() { 1458 | this.buffer = new Array(); 1459 | this.length = 0; 1460 | } 1461 | 1462 | QRBitBuffer.prototype = { 1463 | 1464 | get : function(index) { 1465 | var bufIndex = Math.floor(index / 8); 1466 | return ( (this.buffer[bufIndex] >>> (7 - index % 8) ) & 1) == 1; 1467 | }, 1468 | 1469 | put : function(num, length) { 1470 | for (var i = 0; i < length; i++) { 1471 | this.putBit( ( (num >>> (length - i - 1) ) & 1) == 1); 1472 | } 1473 | }, 1474 | 1475 | getLengthInBits : function() { 1476 | return this.length; 1477 | }, 1478 | 1479 | putBit : function(bit) { 1480 | 1481 | var bufIndex = Math.floor(this.length / 8); 1482 | if (this.buffer.length <= bufIndex) { 1483 | this.buffer.push(0); 1484 | } 1485 | 1486 | if (bit) { 1487 | this.buffer[bufIndex] |= (0x80 >>> (this.length % 8) ); 1488 | } 1489 | 1490 | this.length++; 1491 | } 1492 | }; 1493 | 1494 | },{"bops":4}],4:[function(require,module,exports){ 1495 | var proto = {} 1496 | module.exports = proto 1497 | 1498 | proto.from = require('./from.js') 1499 | proto.to = require('./to.js') 1500 | proto.is = require('./is.js') 1501 | proto.subarray = require('./subarray.js') 1502 | proto.join = require('./join.js') 1503 | proto.copy = require('./copy.js') 1504 | proto.create = require('./create.js') 1505 | 1506 | mix(require('./read.js'), proto) 1507 | mix(require('./write.js'), proto) 1508 | 1509 | function mix(from, into) { 1510 | for(var key in from) { 1511 | into[key] = from[key] 1512 | } 1513 | } 1514 | 1515 | },{"./copy.js":7,"./create.js":8,"./from.js":9,"./is.js":10,"./join.js":11,"./read.js":13,"./subarray.js":14,"./to.js":15,"./write.js":16}],5:[function(require,module,exports){ 1516 | (function (exports) { 1517 | 'use strict'; 1518 | 1519 | var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; 1520 | 1521 | function b64ToByteArray(b64) { 1522 | var i, j, l, tmp, placeHolders, arr; 1523 | 1524 | if (b64.length % 4 > 0) { 1525 | throw 'Invalid string. Length must be a multiple of 4'; 1526 | } 1527 | 1528 | // the number of equal signs (place holders) 1529 | // if there are two placeholders, than the two characters before it 1530 | // represent one byte 1531 | // if there is only one, then the three characters before it represent 2 bytes 1532 | // this is just a cheap hack to not do indexOf twice 1533 | placeHolders = b64.indexOf('='); 1534 | placeHolders = placeHolders > 0 ? b64.length - placeHolders : 0; 1535 | 1536 | // base64 is 4/3 + up to two characters of the original data 1537 | arr = [];//new Uint8Array(b64.length * 3 / 4 - placeHolders); 1538 | 1539 | // if there are placeholders, only get up to the last complete 4 chars 1540 | l = placeHolders > 0 ? b64.length - 4 : b64.length; 1541 | 1542 | for (i = 0, j = 0; i < l; i += 4, j += 3) { 1543 | tmp = (lookup.indexOf(b64[i]) << 18) | (lookup.indexOf(b64[i + 1]) << 12) | (lookup.indexOf(b64[i + 2]) << 6) | lookup.indexOf(b64[i + 3]); 1544 | arr.push((tmp & 0xFF0000) >> 16); 1545 | arr.push((tmp & 0xFF00) >> 8); 1546 | arr.push(tmp & 0xFF); 1547 | } 1548 | 1549 | if (placeHolders === 2) { 1550 | tmp = (lookup.indexOf(b64[i]) << 2) | (lookup.indexOf(b64[i + 1]) >> 4); 1551 | arr.push(tmp & 0xFF); 1552 | } else if (placeHolders === 1) { 1553 | tmp = (lookup.indexOf(b64[i]) << 10) | (lookup.indexOf(b64[i + 1]) << 4) | (lookup.indexOf(b64[i + 2]) >> 2); 1554 | arr.push((tmp >> 8) & 0xFF); 1555 | arr.push(tmp & 0xFF); 1556 | } 1557 | 1558 | return arr; 1559 | } 1560 | 1561 | function uint8ToBase64(uint8) { 1562 | var i, 1563 | extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes 1564 | output = "", 1565 | temp, length; 1566 | 1567 | function tripletToBase64 (num) { 1568 | return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F]; 1569 | }; 1570 | 1571 | // go through the array every three bytes, we'll deal with trailing stuff later 1572 | for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) { 1573 | temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]); 1574 | output += tripletToBase64(temp); 1575 | } 1576 | 1577 | // pad the end with zeros, but make sure to not forget the extra bytes 1578 | switch (extraBytes) { 1579 | case 1: 1580 | temp = uint8[uint8.length - 1]; 1581 | output += lookup[temp >> 2]; 1582 | output += lookup[(temp << 4) & 0x3F]; 1583 | output += '=='; 1584 | break; 1585 | case 2: 1586 | temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]); 1587 | output += lookup[temp >> 10]; 1588 | output += lookup[(temp >> 4) & 0x3F]; 1589 | output += lookup[(temp << 2) & 0x3F]; 1590 | output += '='; 1591 | break; 1592 | } 1593 | 1594 | return output; 1595 | } 1596 | 1597 | module.exports.toByteArray = b64ToByteArray; 1598 | module.exports.fromByteArray = uint8ToBase64; 1599 | }()); 1600 | 1601 | },{}],6:[function(require,module,exports){ 1602 | module.exports = to_utf8 1603 | 1604 | var out = [] 1605 | , col = [] 1606 | , fcc = String.fromCharCode 1607 | , mask = [0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01] 1608 | , unmask = [ 1609 | 0x00 1610 | , 0x01 1611 | , 0x02 | 0x01 1612 | , 0x04 | 0x02 | 0x01 1613 | , 0x08 | 0x04 | 0x02 | 0x01 1614 | , 0x10 | 0x08 | 0x04 | 0x02 | 0x01 1615 | , 0x20 | 0x10 | 0x08 | 0x04 | 0x02 | 0x01 1616 | , 0x40 | 0x20 | 0x10 | 0x08 | 0x04 | 0x02 | 0x01 1617 | ] 1618 | 1619 | function to_utf8(bytes, start, end) { 1620 | start = start === undefined ? 0 : start 1621 | end = end === undefined ? bytes.length : end 1622 | 1623 | var idx = 0 1624 | , hi = 0x80 1625 | , collecting = 0 1626 | , pos 1627 | , by 1628 | 1629 | col.length = 1630 | out.length = 0 1631 | 1632 | while(idx < bytes.length) { 1633 | by = bytes[idx] 1634 | if(!collecting && by & hi) { 1635 | pos = find_pad_position(by) 1636 | collecting += pos 1637 | if(pos < 8) { 1638 | col[col.length] = by & unmask[6 - pos] 1639 | } 1640 | } else if(collecting) { 1641 | col[col.length] = by & unmask[6] 1642 | --collecting 1643 | if(!collecting && col.length) { 1644 | out[out.length] = fcc(reduced(col, pos)) 1645 | col.length = 0 1646 | } 1647 | } else { 1648 | out[out.length] = fcc(by) 1649 | } 1650 | ++idx 1651 | } 1652 | if(col.length && !collecting) { 1653 | out[out.length] = fcc(reduced(col, pos)) 1654 | col.length = 0 1655 | } 1656 | return out.join('') 1657 | } 1658 | 1659 | function find_pad_position(byt) { 1660 | for(var i = 0; i < 7; ++i) { 1661 | if(!(byt & mask[i])) { 1662 | break 1663 | } 1664 | } 1665 | return i 1666 | } 1667 | 1668 | function reduced(list) { 1669 | var out = 0 1670 | for(var i = 0, len = list.length; i < len; ++i) { 1671 | out |= list[i] << ((len - i - 1) * 6) 1672 | } 1673 | return out 1674 | } 1675 | 1676 | },{}],7:[function(require,module,exports){ 1677 | module.exports = copy 1678 | 1679 | var slice = [].slice 1680 | 1681 | function copy(source, target, target_start, source_start, source_end) { 1682 | target_start = arguments.length < 3 ? 0 : target_start 1683 | source_start = arguments.length < 4 ? 0 : source_start 1684 | source_end = arguments.length < 5 ? source.length : source_end 1685 | 1686 | if(source_end === source_start) { 1687 | return 1688 | } 1689 | 1690 | if(target.length === 0 || source.length === 0) { 1691 | return 1692 | } 1693 | 1694 | if(source_end > source.length) { 1695 | source_end = source.length 1696 | } 1697 | 1698 | if(target.length - target_start < source_end - source_start) { 1699 | source_end = target.length - target_start + start 1700 | } 1701 | 1702 | if(source.buffer !== target.buffer) { 1703 | return fast_copy(source, target, target_start, source_start, source_end) 1704 | } 1705 | return slow_copy(source, target, target_start, source_start, source_end) 1706 | } 1707 | 1708 | function fast_copy(source, target, target_start, source_start, source_end) { 1709 | var len = (source_end - source_start) + target_start 1710 | 1711 | for(var i = target_start, j = source_start; 1712 | i < len; 1713 | ++i, 1714 | ++j) { 1715 | target[i] = source[j] 1716 | } 1717 | } 1718 | 1719 | function slow_copy(from, to, j, i, jend) { 1720 | // the buffers could overlap. 1721 | var iend = jend + i 1722 | , tmp = new Uint8Array(slice.call(from, i, iend)) 1723 | , x = 0 1724 | 1725 | for(; i < iend; ++i, ++x) { 1726 | to[j++] = tmp[x] 1727 | } 1728 | } 1729 | 1730 | },{}],8:[function(require,module,exports){ 1731 | module.exports = function(size) { 1732 | return new Uint8Array(size) 1733 | } 1734 | 1735 | },{}],9:[function(require,module,exports){ 1736 | module.exports = from 1737 | 1738 | var base64 = require('base64-js') 1739 | 1740 | var decoders = { 1741 | hex: from_hex 1742 | , utf8: from_utf 1743 | , base64: from_base64 1744 | } 1745 | 1746 | function from(source, encoding) { 1747 | if(Array.isArray(source)) { 1748 | return new Uint8Array(source) 1749 | } 1750 | 1751 | return decoders[encoding || 'utf8'](source) 1752 | } 1753 | 1754 | function from_hex(str) { 1755 | var size = str.length / 2 1756 | , buf = new Uint8Array(size) 1757 | , character = '' 1758 | 1759 | for(var i = 0, len = str.length; i < len; ++i) { 1760 | character += str.charAt(i) 1761 | 1762 | if(i > 0 && (i % 2) === 1) { 1763 | buf[i>>>1] = parseInt(character, 16) 1764 | character = '' 1765 | } 1766 | } 1767 | 1768 | return buf 1769 | } 1770 | 1771 | function from_utf(str) { 1772 | var bytes = [] 1773 | , tmp 1774 | , ch 1775 | 1776 | for(var i = 0, len = str.length; i < len; ++i) { 1777 | ch = str.charCodeAt(i) 1778 | if(ch & 0x80) { 1779 | tmp = encodeURIComponent(str.charAt(i)).substr(1).split('%') 1780 | for(var j = 0, jlen = tmp.length; j < jlen; ++j) { 1781 | bytes[bytes.length] = parseInt(tmp[j], 16) 1782 | } 1783 | } else { 1784 | bytes[bytes.length] = ch 1785 | } 1786 | } 1787 | 1788 | return new Uint8Array(bytes) 1789 | } 1790 | 1791 | function from_base64(str) { 1792 | return new Uint8Array(base64.toByteArray(str)) 1793 | } 1794 | 1795 | },{"base64-js":5}],10:[function(require,module,exports){ 1796 | 1797 | module.exports = function(buffer) { 1798 | return buffer instanceof Uint8Array; 1799 | } 1800 | 1801 | },{}],11:[function(require,module,exports){ 1802 | module.exports = join 1803 | 1804 | function join(targets, hint) { 1805 | if(!targets.length) { 1806 | return new Uint8Array(0) 1807 | } 1808 | 1809 | var len = hint !== undefined ? hint : get_length(targets) 1810 | , out = new Uint8Array(len) 1811 | , cur = targets[0] 1812 | , curlen = cur.length 1813 | , curidx = 0 1814 | , curoff = 0 1815 | , i = 0 1816 | 1817 | while(i < len) { 1818 | if(curoff === curlen) { 1819 | curoff = 0 1820 | ++curidx 1821 | cur = targets[curidx] 1822 | curlen = cur && cur.length 1823 | continue 1824 | } 1825 | out[i++] = cur[curoff++] 1826 | } 1827 | 1828 | return out 1829 | } 1830 | 1831 | function get_length(targets) { 1832 | var size = 0 1833 | for(var i = 0, len = targets.length; i < len; ++i) { 1834 | size += targets[i].byteLength 1835 | } 1836 | return size 1837 | } 1838 | 1839 | },{}],12:[function(require,module,exports){ 1840 | var proto 1841 | , map 1842 | 1843 | module.exports = proto = {} 1844 | 1845 | map = typeof WeakMap === 'undefined' ? null : new WeakMap 1846 | 1847 | proto.get = !map ? no_weakmap_get : get 1848 | 1849 | function no_weakmap_get(target) { 1850 | return new DataView(target.buffer, 0) 1851 | } 1852 | 1853 | function get(target) { 1854 | var out = map.get(target.buffer) 1855 | if(!out) { 1856 | map.set(target.buffer, out = new DataView(target.buffer, 0)) 1857 | } 1858 | return out 1859 | } 1860 | 1861 | },{}],13:[function(require,module,exports){ 1862 | module.exports = { 1863 | readUInt8: read_uint8 1864 | , readInt8: read_int8 1865 | , readUInt16LE: read_uint16_le 1866 | , readUInt32LE: read_uint32_le 1867 | , readInt16LE: read_int16_le 1868 | , readInt32LE: read_int32_le 1869 | , readFloatLE: read_float_le 1870 | , readDoubleLE: read_double_le 1871 | , readUInt16BE: read_uint16_be 1872 | , readUInt32BE: read_uint32_be 1873 | , readInt16BE: read_int16_be 1874 | , readInt32BE: read_int32_be 1875 | , readFloatBE: read_float_be 1876 | , readDoubleBE: read_double_be 1877 | } 1878 | 1879 | var map = require('./mapped.js') 1880 | 1881 | function read_uint8(target, at) { 1882 | return target[at] 1883 | } 1884 | 1885 | function read_int8(target, at) { 1886 | var v = target[at]; 1887 | return v < 0x80 ? v : v - 0x100 1888 | } 1889 | 1890 | function read_uint16_le(target, at) { 1891 | var dv = map.get(target); 1892 | return dv.getUint16(at + target.byteOffset, true) 1893 | } 1894 | 1895 | function read_uint32_le(target, at) { 1896 | var dv = map.get(target); 1897 | return dv.getUint32(at + target.byteOffset, true) 1898 | } 1899 | 1900 | function read_int16_le(target, at) { 1901 | var dv = map.get(target); 1902 | return dv.getInt16(at + target.byteOffset, true) 1903 | } 1904 | 1905 | function read_int32_le(target, at) { 1906 | var dv = map.get(target); 1907 | return dv.getInt32(at + target.byteOffset, true) 1908 | } 1909 | 1910 | function read_float_le(target, at) { 1911 | var dv = map.get(target); 1912 | return dv.getFloat32(at + target.byteOffset, true) 1913 | } 1914 | 1915 | function read_double_le(target, at) { 1916 | var dv = map.get(target); 1917 | return dv.getFloat64(at + target.byteOffset, true) 1918 | } 1919 | 1920 | function read_uint16_be(target, at) { 1921 | var dv = map.get(target); 1922 | return dv.getUint16(at + target.byteOffset, false) 1923 | } 1924 | 1925 | function read_uint32_be(target, at) { 1926 | var dv = map.get(target); 1927 | return dv.getUint32(at + target.byteOffset, false) 1928 | } 1929 | 1930 | function read_int16_be(target, at) { 1931 | var dv = map.get(target); 1932 | return dv.getInt16(at + target.byteOffset, false) 1933 | } 1934 | 1935 | function read_int32_be(target, at) { 1936 | var dv = map.get(target); 1937 | return dv.getInt32(at + target.byteOffset, false) 1938 | } 1939 | 1940 | function read_float_be(target, at) { 1941 | var dv = map.get(target); 1942 | return dv.getFloat32(at + target.byteOffset, false) 1943 | } 1944 | 1945 | function read_double_be(target, at) { 1946 | var dv = map.get(target); 1947 | return dv.getFloat64(at + target.byteOffset, false) 1948 | } 1949 | 1950 | },{"./mapped.js":12}],14:[function(require,module,exports){ 1951 | module.exports = subarray 1952 | 1953 | function subarray(buf, from, to) { 1954 | return buf.subarray(from || 0, to || buf.length) 1955 | } 1956 | 1957 | },{}],15:[function(require,module,exports){ 1958 | module.exports = to 1959 | 1960 | var base64 = require('base64-js') 1961 | , toutf8 = require('to-utf8') 1962 | 1963 | var encoders = { 1964 | hex: to_hex 1965 | , utf8: to_utf 1966 | , base64: to_base64 1967 | } 1968 | 1969 | function to(buf, encoding) { 1970 | return encoders[encoding || 'utf8'](buf) 1971 | } 1972 | 1973 | function to_hex(buf) { 1974 | var str = '' 1975 | , byt 1976 | 1977 | for(var i = 0, len = buf.length; i < len; ++i) { 1978 | byt = buf[i] 1979 | str += ((byt & 0xF0) >>> 4).toString(16) 1980 | str += (byt & 0x0F).toString(16) 1981 | } 1982 | 1983 | return str 1984 | } 1985 | 1986 | function to_utf(buf) { 1987 | return toutf8(buf) 1988 | } 1989 | 1990 | function to_base64(buf) { 1991 | return base64.fromByteArray(buf) 1992 | } 1993 | 1994 | 1995 | },{"base64-js":5,"to-utf8":6}],16:[function(require,module,exports){ 1996 | module.exports = { 1997 | writeUInt8: write_uint8 1998 | , writeInt8: write_int8 1999 | , writeUInt16LE: write_uint16_le 2000 | , writeUInt32LE: write_uint32_le 2001 | , writeInt16LE: write_int16_le 2002 | , writeInt32LE: write_int32_le 2003 | , writeFloatLE: write_float_le 2004 | , writeDoubleLE: write_double_le 2005 | , writeUInt16BE: write_uint16_be 2006 | , writeUInt32BE: write_uint32_be 2007 | , writeInt16BE: write_int16_be 2008 | , writeInt32BE: write_int32_be 2009 | , writeFloatBE: write_float_be 2010 | , writeDoubleBE: write_double_be 2011 | } 2012 | 2013 | var map = require('./mapped.js') 2014 | 2015 | function write_uint8(target, value, at) { 2016 | return target[at] = value 2017 | } 2018 | 2019 | function write_int8(target, value, at) { 2020 | return target[at] = value < 0 ? value + 0x100 : value 2021 | } 2022 | 2023 | function write_uint16_le(target, value, at) { 2024 | var dv = map.get(target); 2025 | return dv.setUint16(at + target.byteOffset, value, true) 2026 | } 2027 | 2028 | function write_uint32_le(target, value, at) { 2029 | var dv = map.get(target); 2030 | return dv.setUint32(at + target.byteOffset, value, true) 2031 | } 2032 | 2033 | function write_int16_le(target, value, at) { 2034 | var dv = map.get(target); 2035 | return dv.setInt16(at + target.byteOffset, value, true) 2036 | } 2037 | 2038 | function write_int32_le(target, value, at) { 2039 | var dv = map.get(target); 2040 | return dv.setInt32(at + target.byteOffset, value, true) 2041 | } 2042 | 2043 | function write_float_le(target, value, at) { 2044 | var dv = map.get(target); 2045 | return dv.setFloat32(at + target.byteOffset, value, true) 2046 | } 2047 | 2048 | function write_double_le(target, value, at) { 2049 | var dv = map.get(target); 2050 | return dv.setFloat64(at + target.byteOffset, value, true) 2051 | } 2052 | 2053 | function write_uint16_be(target, value, at) { 2054 | var dv = map.get(target); 2055 | return dv.setUint16(at + target.byteOffset, value, false) 2056 | } 2057 | 2058 | function write_uint32_be(target, value, at) { 2059 | var dv = map.get(target); 2060 | return dv.setUint32(at + target.byteOffset, value, false) 2061 | } 2062 | 2063 | function write_int16_be(target, value, at) { 2064 | var dv = map.get(target); 2065 | return dv.setInt16(at + target.byteOffset, value, false) 2066 | } 2067 | 2068 | function write_int32_be(target, value, at) { 2069 | var dv = map.get(target); 2070 | return dv.setInt32(at + target.byteOffset, value, false) 2071 | } 2072 | 2073 | function write_float_be(target, value, at) { 2074 | var dv = map.get(target); 2075 | return dv.setFloat32(at + target.byteOffset, value, false) 2076 | } 2077 | 2078 | function write_double_be(target, value, at) { 2079 | var dv = map.get(target); 2080 | return dv.setFloat64(at + target.byteOffset, value, false) 2081 | } 2082 | 2083 | },{"./mapped.js":12}],17:[function(require,module,exports){ 2084 | 2085 | var QRCodeLib = require('./lib/qrcode-draw.js'); 2086 | 2087 | if(typeof window !== "undefined") { 2088 | window.qrcodelib = window.QRCodeLib = QRCodeLib; 2089 | // monkey patch old api 2090 | QRCodeLib.qrcodedraw = QRCodeLib.QRCodeDraw; 2091 | } 2092 | 2093 | },{"./lib/qrcode-draw.js":2}]},{},[17]) 2094 | ; --------------------------------------------------------------------------------