Skip to content

Commit

Permalink
Merge branch 'master' into 666-support-css-variables
Browse files Browse the repository at this point in the history
  • Loading branch information
developit committed Aug 16, 2018
2 parents d9bca90 + 73866a4 commit b2c742e
Show file tree
Hide file tree
Showing 26 changed files with 897 additions and 170 deletions.
2 changes: 1 addition & 1 deletion .editorconfig
Expand Up @@ -7,7 +7,7 @@ charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[{package.json,.*rc,*.yml}]
[{*.json,.*rc,*.yml}]
indent_style = space
indent_size = 2

Expand Down
12 changes: 9 additions & 3 deletions .travis.yml
Expand Up @@ -4,6 +4,7 @@ language: node_js

node_js:
- "8"
- "10"

cache:
directories:
Expand All @@ -18,8 +19,13 @@ before_install:
install:
- npm install

addons:
sauce_connect: true

script:
- npm run build
- COVERAGE=true npm run test
- COVERAGE=false FLAKEY=false PERFORMANCE=false npm run test:karma
- ./node_modules/coveralls/bin/coveralls.js < ./coverage/lcov.info
- COVERAGE=true ALLOW_SAUCELABS=false npm run test
- if [ "$TRAVIS_NODE_VERSION" = "8" ]; then
COVERAGE=false FLAKEY=false PERFORMANCE=false ALLOW_SAUCELABS=true npm run test:karma;
./node_modules/coveralls/bin/coveralls.js < ./coverage/lcov.info;
fi
10 changes: 6 additions & 4 deletions README.md
Expand Up @@ -64,7 +64,8 @@ Preact supports modern browsers and IE9+:
#### Real-World Apps

- [**Preact Hacker News**](https://hn.kristoferbaxter.com) _([GitHub Project](https://github.com/kristoferbaxter/preact-hn))_
- [**Play.cash**](https://play.cash) :notes:
- [**Play.cash**](https://play.cash) :notes: _([GitHub Project](https://github.com/feross/play.cash))_
- [**BitMidi**](https://bitmidi.com/) 🎹 Wayback machine for free MIDI files _([GitHub Project](https://github.com/feross/bitmidi.com))_
- [**ESBench**](http://esbench.com) is built using Preact.
- [**BigWebQuiz**](https://bigwebquiz.com) _([GitHub Project](https://github.com/jakearchibald/big-web-quiz))_
- [**Nectarine.rocks**](http://nectarine.rocks) _([GitHub Project](https://github.com/developit/nectarine))_ :peach:
Expand Down Expand Up @@ -96,7 +97,7 @@ Preact supports modern browsers and IE9+:

- [**Preact Boilerplate**](https://preact-boilerplate.surge.sh) _([GitHub Project](https://github.com/developit/preact-boilerplate))_ :zap:
- [**Preact Offline Starter**](https://preact-starter.now.sh) _([GitHub Project](https://github.com/lukeed/preact-starter))_ :100:
- [**Preact PWA**](https://preact-pwa.appspot.com/) _([GitHub Project](https://github.com/ezekielchentnik/preact-pwa))_ :hamburger:
- [**Preact PWA**](https://preact-pwa-yfxiijbzit.now.sh/) _([GitHub Project](https://github.com/ezekielchentnik/preact-pwa))_ :hamburger:
- [**Parcel + Preact + Unistore Starter**](https://github.com/hwclass/parcel-preact-unistore-starter)
- [**Preact Mobx Starter**](https://awaw00.github.io/preact-mobx-starter/) _([GitHub Project](https://github.com/awaw00/preact-mobx-starter))_ :sunny:
- [**Preact Redux Example**](https://github.com/developit/preact-redux-example) :star:
Expand Down Expand Up @@ -138,6 +139,7 @@ Preact supports modern browsers and IE9+:
- :electric_plug: [**preact-routlet**](https://github.com/k1r0s/preact-routlet): Simple `Component Driven` Routing for Preact using ES7 Decorators
- :fax: [**preact-bind-group**](https://github.com/k1r0s/preact-bind-group): Preact Forms made easy, Group Events into a Single Callback
- :hatching_chick: [**preact-habitat**](https://github.com/zouhir/preact-habitat): Declarative Preact widgets renderer in any CMS or DOM host ([demo](https://codepen.io/zouhir/pen/brrOPB)).
- :tada: [**proppy-preact**](https://github.com/fahad19/proppy): Functional props composition for Preact components

#### UI Component Libraries

Expand Down Expand Up @@ -250,8 +252,8 @@ import { h, render, Component } from 'preact';

class Clock extends Component {
render() {
let time = new Date().toLocaleTimeString();
return <span>{ time }</span>;
let time = new Date();
return <time datetime={time.toISOString()}>{ time.toLocaleTimeString() }</time>;
}
}

Expand Down
1 change: 1 addition & 0 deletions config/rollup.config.js
Expand Up @@ -27,6 +27,7 @@ export default {
sourceMap: true,
exclude: 'node_modules/**',
babelrc: false,
comments: false,
presets: [
['env', {
modules: false,
Expand Down
Expand Up @@ -2,7 +2,7 @@ import config from './rollup.config';

// ES output
config.output.format = 'es';
config.output.file = 'dist/preact.esm.js';
config.output.file = 'dist/preact.mjs';

// remove memory() plugin
config.plugins.splice(0, 1);
Expand Down
13 changes: 7 additions & 6 deletions package.json
@@ -1,10 +1,10 @@
{
"name": "preact",
"version": "8.2.9",
"version": "8.3.0",
"description": "Fast 3kb React alternative with the same modern API. Components & Virtual DOM.",
"main": "dist/preact.js",
"jsnext:main": "dist/preact.esm.js",
"module": "dist/preact.esm.js",
"jsnext:main": "dist/preact.mjs",
"module": "dist/preact.mjs",
"dev:main": "dist/preact.dev.js",
"minified:main": "dist/preact.min.js",
"types": "dist/preact.d.ts",
Expand All @@ -16,13 +16,13 @@
"flow": "flow",
"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:esm": "rollup -c config/rollup.config.module.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",
"minify": "uglifyjs dist/preact.js -c collapse_vars,evaluate,screw_ie8,unsafe,loops=false,keep_fargs=false,pure_getters,unused,dead_code -m -o dist/preact.min.js -p relative --in-source-map dist/preact.js.map --source-map dist/preact.min.js.map",
"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:esm": "jscodeshift --run-in-band -s -t config/codemod-strip-tdz.js dist/preact.mjs && jscodeshift --run-in-band -s -t config/codemod-const.js dist/preact.mjs && jscodeshift --run-in-band -s -t config/codemod-let-name.js dist/preact.mjs",
"strip": "npm-run-all strip:main strip:esm",
"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:flow test:size",
Expand Down Expand Up @@ -111,14 +111,15 @@
"karma-webpack": "^3.0.0",
"mocha": "^5.0.4",
"npm-run-all": "^4.0.0",
"puppeteer": "^1.5.0",
"rimraf": "^2.5.3",
"rollup": "^0.57.1",
"rollup-plugin-babel": "^3.0.2",
"rollup-plugin-memory": "^3.0.0",
"rollup-plugin-node-resolve": "^3.0.0",
"sinon": "^4.4.2",
"sinon-chai": "^3.0.0",
"typescript": "^2.8.1",
"typescript": "^2.9.0-rc",
"uglify-js": "^2.7.5",
"webpack": "^4.3.0"
},
Expand Down
6 changes: 3 additions & 3 deletions src/clone-element.js
Expand Up @@ -4,9 +4,9 @@ import { h } from './h';
/**
* Clones the given VNode, optionally adding attributes/props and replacing its
* children.
* @param {VNode} vnode The virtual DOM element to clone
* @param {Object} props Attributes/props to add when cloning
* @param {VNode} rest Any additional arguments will be used as replacement
* @param {import('./vnode').VNode} vnode The virtual DOM element to clone
* @param {object} props Attributes/props to add when cloning
* @param {Array<import('./vnode').VNode>} [rest] Any additional arguments will be used as replacement
* children.
*/
export function cloneElement(vnode, props) {
Expand Down
39 changes: 17 additions & 22 deletions src/component.js
Expand Up @@ -5,6 +5,9 @@ import { enqueueRender } from './render-queue';
/**
* Base Component class.
* Provides `setState()` and `forceUpdate()`, which trigger rendering.
* @typedef {object} Component
* @param {object} props The initial component props
* @param {object} context The initial context from parent components' getChildContext
* @public
*
* @example
Expand Down Expand Up @@ -42,35 +45,27 @@ export function Component(props, context) {
extend(Component.prototype, {

/**
* Returns a `boolean` indicating if the component should re-render when
* receiving the given `props` and `state`.
* @param {object} nextProps
* @param {object} nextState
* @param {object} nextContext
* @returns {boolean} should the component re-render
* @name shouldComponentUpdate
* @function
*/


/**
* Update component state by copying properties from `state` to `this.state`.
* @param {object} state A hash of state properties to update with new values
* @param {function} callback A function to be called once component state is
* Update component state and schedule a re-render.
* @param {object} state A dict of state properties to be shallowly merged
* into the current state, or a function that will produce such a dict. The
* function is called with the current state and props.
* @param {() => void} callback A function to be called once component state is
* updated
*/
setState(state, callback) {
let s = this.state;
if (!this.prevState) this.prevState = extend({}, s);
extend(s, typeof state==='function' ? state(s, this.props) : state);
if (!this.prevState) this.prevState = this.state;
this.state = extend(
extend({}, this.state),
typeof state === 'function' ? state(this.state, this.props) : state
);
if (callback) this._renderCallbacks.push(callback);
enqueueRender(this);
},


/**
* Immediately perform a synchronous re-render of the component.
* @param {function} callback A function to be called after component is
* @param {() => void} callback A function to be called after component is
* re-rendered.
* @private
*/
Expand All @@ -86,9 +81,9 @@ extend(Component.prototype, {
* @param {object} props Props (eg: JSX attributes) received from parent
* element/component
* @param {object} state The component's current state
* @param {object} context Context object (if a parent component has provided
* context)
* @returns {VNode}
* @param {object} context Context object, as returned by the nearest
* ancestor's `getChildContext()`
* @returns {import('./vnode').VNode | void}
*/
render() {}

Expand Down
6 changes: 5 additions & 1 deletion src/constants.js
@@ -1,13 +1,17 @@
// render modes

/** Do not re-render a component */
export const NO_RENDER = 0;
/** Synchronously re-render a component and its children */
export const SYNC_RENDER = 1;
/** Synchronously re-render a component, even if its lifecycle methods attempt to prevent it. */
export const FORCE_RENDER = 2;
/** Queue asynchronous re-render of a component and it's children */
export const ASYNC_RENDER = 3;


export const ATTR_KEY = '__preactattr_';

// DOM properties that should NOT have "px" added when numeric
/** DOM properties that should NOT have "px" added when numeric */
export const IS_NON_DIMENSIONAL = /acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i;

44 changes: 35 additions & 9 deletions src/dom/index.js
@@ -1,15 +1,40 @@
import { IS_NON_DIMENSIONAL } from '../constants';
import { applyRef } from '../util';
import options from '../options';

/**
* A DOM event listener
* @typedef {(e: Event) => void} EventListner
*/

/**
* A mapping of event types to event listeners
* @typedef {Object.<string, EventListener>} EventListenerMap
*/

/**
* Properties Preact adds to elements it creates
* @typedef PreactElementExtensions
* @property {string} [normalizedNodeName] A normalized node name to use in diffing
* @property {EventListenerMap} [_listeners] A map of event listeners added by components to this DOM node
* @property {import('../component').Component} [_component] The component that rendered this DOM node
* @property {function} [_componentConstructor] The constructor of the component that rendered this DOM node
*/

/**
* A DOM element that has been extended with Preact properties
* @typedef {Element & ElementCSSInlineStyle & PreactElementExtensions} PreactElement
*/

/**
* Create an element with the given nodeName.
* @param {string} nodeName
* @param {boolean} [isSvg=false] If `true`, creates an element within the SVG
* @param {string} nodeName The DOM node to create
* @param {boolean} [isSvg=false] If `true`, creates an element within the SVG
* namespace.
* @returns {Element} node
* @returns {PreactElement} The created DOM node
*/
export function createNode(nodeName, isSvg) {
/** @type {PreactElement} */
let node = isSvg ? document.createElementNS('http://www.w3.org/2000/svg', nodeName) : document.createElement(nodeName);
node.normalizedNodeName = nodeName;
return node;
Expand All @@ -18,7 +43,7 @@ export function createNode(nodeName, isSvg) {

/**
* Remove a child node from its parent if attached.
* @param {Element} node The node to remove
* @param {Node} node The node to remove
*/
export function removeNode(node) {
let parentNode = node.parentNode;
Expand All @@ -30,10 +55,10 @@ export function removeNode(node) {
* Set a named attribute on the given Node, with special behavior for some names
* and event handlers. If `value` is `null`, the attribute/handler will be
* removed.
* @param {Element} node An element to mutate
* @param {PreactElement} node An element to mutate
* @param {string} name The name/key to set, such as an event or attribute name
* @param {any} old The last value that was set for this name/node pair
* @param {any} value An attribute value, such as a function to be used as an
* @param {*} old The last value that was set for this name/node pair
* @param {*} value An attribute value, such as a function to be used as an
* event handler
* @param {boolean} isSvg Are we currently diffing inside an svg?
* @private
Expand All @@ -46,8 +71,8 @@ export function setAccessor(node, name, old, value, isSvg) {
// ignore
}
else if (name==='ref') {
if (old) old(null);
if (value) value(node);
applyRef(old, null);
applyRef(value, node);
}
else if (name==='class' && !isSvg) {
node.className = value || '';
Expand Down Expand Up @@ -117,6 +142,7 @@ export function setAccessor(node, name, old, value, isSvg) {

/**
* Proxy an event to hooked event handlers
* @param {Event} e The event object from the browser
* @private
*/
function eventProxy(e) {
Expand Down
6 changes: 3 additions & 3 deletions src/h.js
Expand Up @@ -30,9 +30,9 @@ const EMPTY_CHILDREN = [];
*
* `h('div', { id: 'foo', name : 'bar' }, 'Hello!');`
*
* @param {string} nodeName An element name. Ex: `div`, `a`, `span`, etc.
* @param {Object} attributes Any attributes/props to set on the created element.
* @param {...object} rest Additional arguments are taken to be children to
* @param {string | function} nodeName An element name. Ex: `div`, `a`, `span`, etc.
* @param {object | null} attributes Any attributes/props to set on the created element.
* @param {VNode[]} [rest] Additional arguments are taken to be children to
* append. Can be infinitely nested Arrays.
*
* @public
Expand Down
43 changes: 18 additions & 25 deletions src/options.js
@@ -1,29 +1,22 @@
/** Global options
* @public
* @namespace options {Object}
/**
* @typedef {import('./component').Component} Component
* @typedef {import('./vnode').VNode} VNode
*/
export default {

/**
* If `true`, `prop` changes trigger synchronous component updates.
* @name syncComponentUpdates
* @type {boolean}
* @default true
*/
//syncComponentUpdates: true,

/**
* Processes all created VNodes.
* @param {VNode} vnode A newly-created VNode to normalize/process
*/
//vnode(vnode) { }

/** Hook invoked after a component is mounted. */
// afterMount(component) { }
/**
* Global options
* @public
* @typedef Options
* @property {boolean} [syncComponentUpdates] If `true`, `prop` changes trigger synchronous component updates. Defaults to true.
* @property {(vnode: VNode) => void} [vnode] Processes all created VNodes.
* @property {(component: Component) => void} [afterMount] Hook invoked after a component is mounted.
* @property {(component: Component) => void} [afterUpdate] Hook invoked after the DOM is updated with a component's latest render.
* @property {(component: Component) => void} [beforeUnmount] Hook invoked immediately before a component is unmounted.
* @property {(rerender: function) => void} [debounceRendering] Hook invoked whenever a rerender is requested. Can be used to debounce rerenders.
* @property {(event: Event) => Event | void} [event] Hook invoked before any Preact event listeners. The return value (if any) replaces the native browser event given to event listeners
*/

/** Hook invoked after the DOM is updated with a component's latest render. */
// afterUpdate(component) { }
/** @type {Options} */
const options = {};

/** Hook invoked immediately before a component is unmounted. */
// beforeUnmount(component) { }
};
export default options;

0 comments on commit b2c742e

Please sign in to comment.