diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000000..1fb20f9b5c --- /dev/null +++ b/.babelrc @@ -0,0 +1,23 @@ +{ + "presets": [ + [ + "env", + { + "loose": true, + "exclude": [ + "transform-es2015-typeof-symbol" + ], + "targets": { + "browsers": [ + "last 2 versions", + "IE >= 9" + ] + } + } + ] + ], + "plugins": [ + "transform-object-rest-spread", + "transform-react-jsx" + ] +} diff --git a/.gitignore b/.gitignore index 0afcc7aa2b..40acf3f76e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,6 @@ /dist /_dev /coverage -/.package.json # Additional bundles /devtools.js diff --git a/config/donation-message.js b/config/donation-message.js deleted file mode 100755 index 1c9cae3dba..0000000000 --- a/config/donation-message.js +++ /dev/null @@ -1 +0,0 @@ -console.log("\u001b[35m\u001b[1mLove Preact? You can now donate to our open collective:\u001b[22m\u001b[39m\n > \u001b[34mhttps://opencollective.com/preact/donate\u001b[0m") diff --git a/config/prepublish.js b/config/prepublish.js deleted file mode 100644 index 073c6caa8f..0000000000 --- a/config/prepublish.js +++ /dev/null @@ -1,22 +0,0 @@ -const path = require('path').join(__dirname, '..', 'package.json'); -const pkg = require(path); - -const UNNECESSARY_KEYS = [ - 'babel', - 'greenkeeper', - 'bundlesize', - 'devDependencies', - 'eslintConfig' -]; - -UNNECESSARY_KEYS.forEach(function (key) { - delete pkg[key]; -}); - -pkg.scripts = { - donate: pkg.scripts.donate, - postinstall: pkg.scripts.postinstall, - postpublish: 'mv -f .package.json package.json' -}; - -require('fs').writeFileSync(path, JSON.stringify(pkg, null, 2)); diff --git a/config/rollup.config.devtools.js b/config/rollup.config.devtools.js index 60e93356be..8a5aa3dbc3 100644 --- a/config/rollup.config.devtools.js +++ b/config/rollup.config.devtools.js @@ -1,13 +1,17 @@ import babel from 'rollup-plugin-babel'; export default { - entry: 'devtools/index.js', + input: 'devtools/index.js', + output: { + format: 'umd', + file: 'devtools.js', + name: 'preactDevTools', + sourcemap: true + }, external: ['preact'], - format: 'umd', globals: { preact: 'preact' }, - moduleName: 'preactDevTools', plugins: [ babel({ sourceMap: true, diff --git a/config/rollup.config.esm.js b/config/rollup.config.esm.js index 5078a1171b..d646683f40 100644 --- a/config/rollup.config.esm.js +++ b/config/rollup.config.esm.js @@ -1,7 +1,8 @@ import config from './rollup.config'; // ES output -config.format = 'es'; +config.output.format = 'es'; +config.output.file = 'dist/preact.esm.js'; // remove memory() plugin config.plugins.splice(0, 1); diff --git a/config/rollup.config.js b/config/rollup.config.js index fe0581139c..3e1c904925 100644 --- a/config/rollup.config.js +++ b/config/rollup.config.js @@ -3,9 +3,14 @@ import babel from 'rollup-plugin-babel'; import memory from 'rollup-plugin-memory'; export default { - useStrict: true, - format: 'iife', - entry: 'src/preact.js', + strict: true, + input: 'src/preact.js', + output: { + format: 'iife', + file: 'dist/preact.dev.js', + name: 'preact', + sourcemap: true + }, plugins: [ memory({ path: 'src/preact.js', diff --git a/debug/index.js b/debug/index.js index fa02855308..a71b897861 100644 --- a/debug/index.js +++ b/debug/index.js @@ -1,3 +1,5 @@ +/* eslint-disable no-console */ + if (process.env.NODE_ENV === 'development') { const { options } = require('preact'); const oldVnodeOption = options.vnode; @@ -6,16 +8,17 @@ if (process.env.NODE_ENV === 'development') { const { nodeName, attributes, children } = vnode; if (nodeName === void 0) { - throw new Error('Undefined component passed to preact.h()'); + console.error('Undefined component passed to preact.h()\n'+serializeVNode(vnode)); } if ( attributes && attributes.ref !== void 0 && - typeof attributes.ref !== 'function' + typeof attributes.ref !== 'function' && + !('$$typeof' in vnode) // allow string refs when preact-compat is installed ) { throw new Error( `Component's "ref" property should be a function,` + - ` but [${typeof attributes.ref}] passed` + ` but [${typeof attributes.ref}] passed\n` + serializeVNode(vnode) ); } @@ -23,18 +26,17 @@ if (process.env.NODE_ENV === 'development') { const keys = {}; inspectChildren(children, (deepChild) => { - if (!deepChild) return; + if (!deepChild || deepChild.key==null) return; // In Preact, all keys are stored as object values, i.e. being strings const key = deepChild.key + ''; if (keys.hasOwnProperty(key)) { - /* eslint-disable no-console */ console.error( 'Following component has two or more children with the ' + 'same "key" attribute. This may cause glitches and misbehavior ' + 'in rendering process. Component: \n\n' + - serializeVNode(vnode) + '\n\n' + serializeVNode(vnode) ); // Return early to not spam the console @@ -45,10 +47,13 @@ if (process.env.NODE_ENV === 'development') { }); } - return oldVnodeOption.call(this, vnode); + if (oldVnodeOption) oldVnodeOption.call(this, vnode); }; const inspectChildren = (children, inspect) => { + if (!Array.isArray(children)) { + children = [children]; + } return children.some((child, i) => { if (Array.isArray(child)) { return inspectChildren(child, inspect); @@ -58,37 +63,34 @@ if (process.env.NODE_ENV === 'development') { }); }; - const serializeVNode = ({ nodeName, attributes }) => { - let name; - let props; - - if (typeof nodeName === 'function') { - name = nodeName.name || nodeName.displayName; - } else { - name = nodeName; + const serializeVNode = ({ nodeName, attributes, children }) => { + if (typeof nodeName==='function') { + nodeName = nodeName.name || nodeName.displayName; } + let props = ''; if (attributes) { - props = Object.keys(attributes).map(attr => { - const attrValue = attributes[attr]; - let attrValueString; - - // If it is an object but doesn't have toString(), use Object.toString - if (Object(attrValue) === attrValue && !attrValue.toString) { - attrValueString = Object.prototype.toString.call(attrValue); - } else { - attrValueString = attrValue + ''; + for (let attr in attributes) { + if (attributes.hasOwnProperty(attr) && attr!=='children') { + let value = attributes[attr]; + + // If it is an object but doesn't have toString(), use Object.toString + if (typeof value==='function') { + value = `function ${value.displayName || value.name}() {}`; + } + if (Object(value) === value && !value.toString) { + value = Object.prototype.toString.call(value); + } + else { + value = value + ''; + } + + props += ` ${attr}=${JSON.stringify(value)}`; } - - return `${attr}=${JSON.stringify(attrValueString)}`; - }); - } - - if (!props) { - return `<${name} />`; + } } - return `<${name} ${props.join(' ')} />`; + return `<${nodeName}${props}${children && children.length ? ('>..') : ' />'}`; }; require('preact/devtools'); diff --git a/package.json b/package.json index 362e87bf29..09069db756 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "preact", - "version": "8.2.1", + "version": "8.2.4", "description": "Fast 3kb React alternative with the same ES6 API. Components & Virtual DOM.", "main": "dist/preact.js", "jsnext:main": "dist/preact.esm.js", @@ -12,9 +12,9 @@ "copy-flow-definition": "copyfiles -f src/preact.js.flow dist", "copy-typescript-definition": "copyfiles -f src/preact.d.ts dist", "build": "npm-run-all --silent clean transpile copy-flow-definition copy-typescript-definition strip optimize minify size", - "transpile:main": "rollup -c config/rollup.config.js -m dist/preact.dev.js.map -n preact -o dist/preact.dev.js", - "transpile:devtools": "rollup -c config/rollup.config.devtools.js -o devtools.js -m devtools.js.map", - "transpile:esm": "rollup -c config/rollup.config.esm.js -m dist/preact.esm.js.map -o dist/preact.esm.js", + "transpile:main": "rollup -c config/rollup.config.js", + "transpile:devtools": "rollup -c config/rollup.config.devtools.js", + "transpile:esm": "rollup -c config/rollup.config.esm.js", "transpile:debug": "babel debug/ -o debug.js -s", "transpile": "npm-run-all transpile:main transpile:esm transpile:devtools transpile:debug", "optimize": "uglifyjs dist/preact.dev.js -c conditionals=false,sequences=false,loops=false,join_vars=false,collapse_vars=false --pure-funcs=Object.defineProperty --mangle-props --mangle-regex=\"/^(_|normalizedNodeName|nextBase|prev[CPS]|_parentC)/\" --name-cache config/properties.json -b width=120,quote_style=3 -o dist/preact.js -p relative --in-source-map dist/preact.dev.js.map --source-map dist/preact.js.map", @@ -22,7 +22,7 @@ "strip:main": "jscodeshift --run-in-band -s -t config/codemod-strip-tdz.js dist/preact.dev.js && jscodeshift --run-in-band -s -t config/codemod-const.js dist/preact.dev.js && jscodeshift --run-in-band -s -t config/codemod-let-name.js dist/preact.dev.js", "strip:esm": "jscodeshift --run-in-band -s -t config/codemod-strip-tdz.js dist/preact.esm.js && jscodeshift --run-in-band -s -t config/codemod-const.js dist/preact.esm.js && jscodeshift --run-in-band -s -t config/codemod-let-name.js dist/preact.esm.js", "strip": "npm-run-all strip:main strip:esm", - "size": "node -e \"process.stdout.write('gzip size: ')\" && gzip-size dist/preact.min.js", + "size": "node -e \"process.stdout.write('gzip size: ')\" && gzip-size --raw dist/preact.min.js", "test": "npm-run-all lint --parallel test:mocha test:karma test:ts test:size", "test:ts": "tsc -p test/ts/", "test:mocha": "mocha --recursive --require babel-register test/shared test/node", @@ -32,10 +32,9 @@ "test:size": "bundlesize", "lint": "eslint debug devtools src test", "prepublish": "npm run build", - "prepublishOnly": "cp package.json .package.json; node config/prepublish.js", "smart-release": "npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish", "release": "cross-env npm run smart-release", - "postinstall": "node ./config/donation-message.js" + "postinstall": "node -e \"console.log('\\u001b[35m\\u001b[1mLove Preact? You can now donate to our open collective:\\u001b[22m\\u001b[39m\\n > \\u001b[34mhttps://opencollective.com/preact/donate\\u001b[0m')\"" }, "eslintConfig": { "extends": "./config/eslint-config.js" @@ -79,7 +78,7 @@ "babel-plugin-transform-object-rest-spread": "^6.23.0", "babel-plugin-transform-react-jsx": "^6.24.1", "babel-preset-env": "^1.5.1", - "bundlesize": "^0.6.1", + "bundlesize": "^0.13.2", "chai": "^3.4.1", "copyfiles": "^1.0.0", "core-js": "^2.4.1", @@ -88,7 +87,7 @@ "diff": "^3.0.0", "eslint": "^3.0.0", "eslint-plugin-react": "^6.0.0", - "gzip-size-cli": "^1.0.0", + "gzip-size-cli": "^2.0.0", "isparta-loader": "^2.0.0", "jscodeshift": "^0.3.25", "karma": "^1.1.0", @@ -108,31 +107,16 @@ "npm-run-all": "^4.0.0", "phantomjs-prebuilt": "^2.1.7", "rimraf": "^2.5.3", - "rollup": "^0.40.0", - "rollup-plugin-babel": "^2.7.1", + "rollup": "^0.48.2", + "rollup-plugin-babel": "^3.0.2", "rollup-plugin-memory": "^2.0.0", - "rollup-plugin-node-resolve": "^2.0.0", + "rollup-plugin-node-resolve": "^3.0.0", "sinon": "^2.2.0", "sinon-chai": "^2.8.0", "typescript": "^2.2.2", "uglify-js": "^2.7.5", "webpack": "^2.4.1" }, - "babel": { - "presets": [ - ["env", { - "loose": true, - "exclude": ["transform-es2015-typeof-symbol"], - "targets": { - "browsers": ["last 2 versions", "IE >= 9"] - } - }] - ], - "plugins": [ - "transform-object-rest-spread", - "transform-react-jsx" - ] - }, "greenkeeper": { "ignore": [ "babel-cli",