From 2db8d556f2fffdbdc6153bd8320ccd7d5ee82639 Mon Sep 17 00:00:00 2001 From: Andrea Giammarchi Date: Thu, 26 Mar 2020 21:15:59 +0100 Subject: [PATCH] first commit --- .gitignore | 3 ++ .npmignore | 6 ++++ .travis.yml | 10 ++++++ LICENSE | 15 ++++++++ README.md | 5 +++ cjs/index.js | 67 ++++++++++++++++++++++++++++++++++++ cjs/package.json | 1 + es.js | 1 + esm/index.js | 60 ++++++++++++++++++++++++++++++++ index.js | 78 ++++++++++++++++++++++++++++++++++++++++++ min.js | 1 + package.json | 41 ++++++++++++++++++++++ rollup/babel.config.js | 18 ++++++++++ rollup/es.config.js | 18 ++++++++++ test/index.js | 45 ++++++++++++++++++++++++ test/package.json | 1 + 16 files changed, 370 insertions(+) create mode 100644 .gitignore create mode 100644 .npmignore create mode 100644 .travis.yml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 cjs/index.js create mode 100644 cjs/package.json create mode 100644 es.js create mode 100644 esm/index.js create mode 100644 index.js create mode 100644 min.js create mode 100644 package.json create mode 100644 rollup/babel.config.js create mode 100644 rollup/es.config.js create mode 100644 test/index.js create mode 100644 test/package.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9375f8e --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.nyc_output/ +node_modules/ +package-lock.json diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..8179ff3 --- /dev/null +++ b/.npmignore @@ -0,0 +1,6 @@ +.nyc_output/ +node_modules/ +rollup/ +test/ +package-lock.json +.travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..55ff2f7 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,10 @@ +language: node_js +node_js: + - stable +git: + depth: 1 +branches: + only: + - master +after_success: + - "npm run coveralls" diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..fbb4931 --- /dev/null +++ b/LICENSE @@ -0,0 +1,15 @@ +ISC License + +Copyright (c) 2020, Andrea Giammarchi, @WebReflection + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..2e2fb71 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# µhandlers + +[![Build Status](https://travis-ci.com/WebReflection/uhandlers.svg?branch=master)](https://travis-ci.com/WebReflection/uhandlers) [![Coverage Status](https://coveralls.io/repos/github/WebReflection/uhandlers/badge.svg?branch=master)](https://coveralls.io/github/WebReflection/uhandlers?branch=master) + +All [µhtml](https://github.com/WebReflection/uhtml#readme) attributes handlers. diff --git a/cjs/index.js b/cjs/index.js new file mode 100644 index 0000000..8b23a20 --- /dev/null +++ b/cjs/index.js @@ -0,0 +1,67 @@ +'use strict'; +const {isArray} = require('uarray'); + +const aria = node => value => { + for (const key in value) + node.setAttribute(key === 'role' ? key : `aria-${key}`, value[key]); +}; +exports.aria = aria; + +const attribute = (node, name) => { + let oldValue, noOwner = true; + const attribute = document.createAttribute(name); + return newValue => { + if (oldValue !== newValue) { + oldValue = newValue; + if (oldValue == null) { + if (!noOwner) { + node.removeAttributeNode(attribute); + noOwner = true; + } + } + else { + attribute.value = newValue; + if (noOwner) { + node.setAttributeNode(attribute); + noOwner = false; + } + } + } + }; +}; +exports.attribute = attribute; + +const data = ({dataset}) => value => { + for (const key in value) + dataset[key] = value[key]; +}; +exports.data = data; + +const event = (node, name) => { + let oldValue, type = name.slice(2); + if (!(name in node) && name.toLowerCase() in node) + type = type.toLowerCase(); + return newValue => { + const info = isArray(newValue) ? newValue : [newValue, false]; + if (oldValue !== info[0]) { + if (oldValue) + node.removeEventListener(type, oldValue, info[1]); + if (oldValue = info[0]) + node.addEventListener(type, oldValue, info[1]); + } + }; +}; +exports.event = event; + +const ref = node => value => { + if (typeof value === 'function') + value(node); + else + value.current = node; +}; +exports.ref = ref; + +const setter = (node, key) => value => { + node[key] = value; +}; +exports.setter = setter; diff --git a/cjs/package.json b/cjs/package.json new file mode 100644 index 0000000..0292b99 --- /dev/null +++ b/cjs/package.json @@ -0,0 +1 @@ +{"type":"commonjs"} \ No newline at end of file diff --git a/es.js b/es.js new file mode 100644 index 0000000..cb651a0 --- /dev/null +++ b/es.js @@ -0,0 +1 @@ +var uhtmlHandlers=function(t){"use strict";const{isArray:e}=Array;return t.aria=t=>e=>{for(const r in e)t.setAttribute("role"===r?r:`aria-${r}`,e[r])},t.attribute=(t,e)=>{let r,n=!0;const o=document.createAttribute(e);return e=>{r!==e&&(r=e,null==r?n||(t.removeAttributeNode(o),n=!0):(o.value=e,n&&(t.setAttributeNode(o),n=!1)))}},t.data=({dataset:t})=>e=>{for(const r in e)t[r]=e[r]},t.event=(t,r)=>{let n,o=r.slice(2);return!(r in t)&&r.toLowerCase()in t&&(o=o.toLowerCase()),r=>{const a=e(r)?r:[r,!1];n!==a[0]&&(n&&t.removeEventListener(o,n,a[1]),(n=a[0])&&t.addEventListener(o,n,a[1]))}},t.ref=t=>e=>{"function"==typeof e?e(t):e.current=t},t.setter=(t,e)=>r=>{t[e]=r},t}({}); diff --git a/esm/index.js b/esm/index.js new file mode 100644 index 0000000..be8acfe --- /dev/null +++ b/esm/index.js @@ -0,0 +1,60 @@ +import {isArray} from 'uarray'; + +export const aria = node => value => { + for (const key in value) + node.setAttribute(key === 'role' ? key : `aria-${key}`, value[key]); +}; + +export const attribute = (node, name) => { + let oldValue, noOwner = true; + const attribute = document.createAttribute(name); + return newValue => { + if (oldValue !== newValue) { + oldValue = newValue; + if (oldValue == null) { + if (!noOwner) { + node.removeAttributeNode(attribute); + noOwner = true; + } + } + else { + attribute.value = newValue; + if (noOwner) { + node.setAttributeNode(attribute); + noOwner = false; + } + } + } + }; +}; + +export const data = ({dataset}) => value => { + for (const key in value) + dataset[key] = value[key]; +}; + +export const event = (node, name) => { + let oldValue, type = name.slice(2); + if (!(name in node) && name.toLowerCase() in node) + type = type.toLowerCase(); + return newValue => { + const info = isArray(newValue) ? newValue : [newValue, false]; + if (oldValue !== info[0]) { + if (oldValue) + node.removeEventListener(type, oldValue, info[1]); + if (oldValue = info[0]) + node.addEventListener(type, oldValue, info[1]); + } + }; +}; + +export const ref = node => value => { + if (typeof value === 'function') + value(node); + else + value.current = node; +}; + +export const setter = (node, key) => value => { + node[key] = value; +}; diff --git a/index.js b/index.js new file mode 100644 index 0000000..2569034 --- /dev/null +++ b/index.js @@ -0,0 +1,78 @@ +var uhtmlHandlers = (function (exports) { + 'use strict'; + + var isArray = Array.isArray; + + var aria = function aria(node) { + return function (value) { + for (var key in value) { + node.setAttribute(key === 'role' ? key : "aria-".concat(key), value[key]); + } + }; + }; + var attribute = function attribute(node, name) { + var oldValue, + noOwner = true; + var attribute = document.createAttribute(name); + return function (newValue) { + if (oldValue !== newValue) { + oldValue = newValue; + + if (oldValue == null) { + if (!noOwner) { + node.removeAttributeNode(attribute); + noOwner = true; + } + } else { + attribute.value = newValue; + + if (noOwner) { + node.setAttributeNode(attribute); + noOwner = false; + } + } + } + }; + }; + var data = function data(_ref) { + var dataset = _ref.dataset; + return function (value) { + for (var key in value) { + dataset[key] = value[key]; + } + }; + }; + var event = function event(node, name) { + var oldValue, + type = name.slice(2); + if (!(name in node) && name.toLowerCase() in node) type = type.toLowerCase(); + return function (newValue) { + var info = isArray(newValue) ? newValue : [newValue, false]; + + if (oldValue !== info[0]) { + if (oldValue) node.removeEventListener(type, oldValue, info[1]); + if (oldValue = info[0]) node.addEventListener(type, oldValue, info[1]); + } + }; + }; + var ref = function ref(node) { + return function (value) { + if (typeof value === 'function') value(node);else value.current = node; + }; + }; + var setter = function setter(node, key) { + return function (value) { + node[key] = value; + }; + }; + + exports.aria = aria; + exports.attribute = attribute; + exports.data = data; + exports.event = event; + exports.ref = ref; + exports.setter = setter; + + return exports; + +}({})); diff --git a/min.js b/min.js new file mode 100644 index 0000000..9ad2be5 --- /dev/null +++ b/min.js @@ -0,0 +1 @@ +var uhtmlHandlers=function(t){"use strict";var i=Array.isArray;return t.aria=function(r){return function(t){for(var n in t)r.setAttribute("role"===n?n:"aria-".concat(n),t[n])}},t.attribute=function(n,t){var r,e=!0,u=document.createAttribute(t);return function(t){r!==t&&(null==(r=t)?e||(n.removeAttributeNode(u),e=!0):(u.value=t,e&&(n.setAttributeNode(u),e=!1)))}},t.data=function(t){var r=t.dataset;return function(t){for(var n in t)r[n]=t[n]}},t.event=function(r,t){var e,u=t.slice(2);return!(t in r)&&t.toLowerCase()in r&&(u=u.toLowerCase()),function(t){var n=i(t)?t:[t,!1];e!==n[0]&&(e&&r.removeEventListener(u,e,n[1]),(e=n[0])&&r.addEventListener(u,e,n[1]))}},t.ref=function(n){return function(t){"function"==typeof t?t(n):t.current=n}},t.setter=function(n,r){return function(t){n[r]=t}},t}({}); \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..a860786 --- /dev/null +++ b/package.json @@ -0,0 +1,41 @@ +{ + "name": "uhandler", + "version": "0.0.0", + "description": "", + "main": "./cjs/index.js", + "scripts": { + "build": "npm run cjs && npm run rollup:es && npm run rollup:babel && npm run min && npm run test", + "cjs": "ascjs esm cjs", + "rollup:es": "rollup --config rollup/es.config.js", + "rollup:babel": "rollup --config rollup/babel.config.js", + "min": "uglifyjs index.js --support-ie8 --comments=/^!/ -c -m -o min.js", + "coveralls": "nyc report --reporter=text-lcov | coveralls", + "test": "nyc node test/index.js" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "@babel/core": "^7.9.0", + "@babel/preset-env": "^7.9.0", + "ascjs": "^3.1.2", + "basichtml": "^2.2.1", + "coveralls": "^3.0.11", + "nyc": "^15.0.0", + "rollup": "^2.2.0", + "rollup-plugin-babel": "^4.4.0", + "rollup-plugin-node-resolve": "^5.2.0", + "rollup-plugin-terser": "^5.3.0", + "uglify-js": "^3.8.0" + }, + "module": "./esm/index.js", + "type": "module", + "exports": { + "import": "./esm/index.js", + "default": "./cjs/index.js" + }, + "unpkg": "min.js", + "dependencies": { + "uarray": "^1.0.0" + } +} diff --git a/rollup/babel.config.js b/rollup/babel.config.js new file mode 100644 index 0000000..6067339 --- /dev/null +++ b/rollup/babel.config.js @@ -0,0 +1,18 @@ +import resolve from 'rollup-plugin-node-resolve'; +import babel from 'rollup-plugin-babel'; + +export default { + input: './esm/index.js', + plugins: [ + + resolve({module: true}), + babel({presets: ['@babel/preset-env']}) + ], + + output: { + exports: 'named', + file: './index.js', + format: 'iife', + name: 'uhtmlHandlers' + } +}; diff --git a/rollup/es.config.js b/rollup/es.config.js new file mode 100644 index 0000000..d1012dd --- /dev/null +++ b/rollup/es.config.js @@ -0,0 +1,18 @@ +import resolve from 'rollup-plugin-node-resolve'; +import {terser} from 'rollup-plugin-terser'; + +export default { + input: './esm/index.js', + plugins: [ + + resolve({module: true}), + terser() + ], + + output: { + exports: 'named', + file: './es.js', + format: 'iife', + name: 'uhtmlHandlers' + } +}; diff --git a/test/index.js b/test/index.js new file mode 100644 index 0000000..48269a5 --- /dev/null +++ b/test/index.js @@ -0,0 +1,45 @@ +const {document} = require('basichtml').init(); + +const {aria, attribute, data, event, ref, setter} = require('../cjs'); + +const div = document.createElement('div'); + +const ariafy = aria(div); +ariafy({role: 'button', labelledBy: 'id'}); +console.assert(div.getAttribute('role') === 'button', 'role'); +console.assert(div.getAttribute('aria-labelledBy') === 'id', 'aria-labelled'); + +const attributefy = attribute(div, 'test'); +attributefy(null); +attributefy('value'); +attributefy('value'); +console.assert(div.getAttribute('test') === 'value', 'attribute'); +attributefy(null); +console.assert(!div.hasAttribute('test'), 'attribute null'); +attributefy('value'); +console.assert(div.hasAttribute('test'), 'attribute exists'); +attributefy('test'); +console.assert(div.getAttribute('test') === 'test', 'attribute test'); + + +const datafy = data(div); +datafy({labelledBy: 'id'}); +console.assert(div.dataset.labelledBy === 'id', 'data'); + +const eventfy = event(div, 'onClick'); +eventfy(Object); +eventfy([String, false]); +eventfy([String, false]); +eventfy(null); +event(div, 'dataset'); + +const reffy = ref(div); +const object = {}; +reffy(object); +console.assert(object.current === div, 'ref=${object}'); +reffy(node => { object.node = node; }); +console.assert(object.node === div, 'ref=${callback}'); + +const setterfy = setter(div, 'setter'); +setterfy('value'); +console.assert(div.setter === 'value', 'setter'); diff --git a/test/package.json b/test/package.json new file mode 100644 index 0000000..0292b99 --- /dev/null +++ b/test/package.json @@ -0,0 +1 @@ +{"type":"commonjs"} \ No newline at end of file