From e7b7c5a7ddc439b27c76193251579672e8650d9e Mon Sep 17 00:00:00 2001 From: Joost De Cock Date: Sat, 27 Apr 2019 12:21:14 +0200 Subject: [PATCH] :sparkles: Added @freesewing/utils --- packages/utils/README.md | 98 ++++++++++++++++++++++ packages/utils/package.json | 46 ++++++++++ packages/utils/rollup.config.js | 29 +++++++ packages/utils/src/cloneObject.js | 3 + packages/utils/src/defaultGist.js | 15 ++++ packages/utils/src/defaultSa.js | 6 ++ packages/utils/src/formatImperial.js | 17 ++++ packages/utils/src/formatMm.js | 43 ++++++++++ packages/utils/src/gistDefaults.js | 29 +++++++ packages/utils/src/index.js | 14 ++++ packages/utils/src/optionDefault.js | 17 ++++ packages/utils/src/optionType.js | 15 ++++ packages/utils/src/roundMm.js | 8 ++ packages/utils/src/roundMmDown.js | 10 +++ packages/utils/src/roundMmUp.js | 10 +++ packages/utils/src/sliderStep.js | 6 ++ packages/utils/src/smallestImperialStep.js | 3 + packages/utils/src/storage.js | 24 ++++++ 18 files changed, 393 insertions(+) create mode 100644 packages/utils/README.md create mode 100644 packages/utils/package.json create mode 100644 packages/utils/rollup.config.js create mode 100644 packages/utils/src/cloneObject.js create mode 100644 packages/utils/src/defaultGist.js create mode 100644 packages/utils/src/defaultSa.js create mode 100644 packages/utils/src/formatImperial.js create mode 100644 packages/utils/src/formatMm.js create mode 100644 packages/utils/src/gistDefaults.js create mode 100644 packages/utils/src/index.js create mode 100644 packages/utils/src/optionDefault.js create mode 100644 packages/utils/src/optionType.js create mode 100644 packages/utils/src/roundMm.js create mode 100644 packages/utils/src/roundMmDown.js create mode 100644 packages/utils/src/roundMmUp.js create mode 100644 packages/utils/src/sliderStep.js create mode 100644 packages/utils/src/smallestImperialStep.js create mode 100644 packages/utils/src/storage.js diff --git a/packages/utils/README.md b/packages/utils/README.md new file mode 100644 index 00000000000..f24a521f3bd --- /dev/null +++ b/packages/utils/README.md @@ -0,0 +1,98 @@ +> **Note**: This is part of version 2 of FreeSewing. +> It is a work in progress, and not ready for prime-time yet +> +> For all questions, please come say hello in [our chatroom on Gitter](https://gitter.im/). + +

Freesewing logo

+

FreeSewing is a free and open source library for made-to-measure sewing patterns

+

@freesewing/utils on NPM + License: MIT + Open issues tagged pkg:utils +

Follow @freesewing_org on Twitter + Chat with us on Gitter + Become a FreeSewing Patron + Follow @freesewing_org on Twitter +

+ +# @freesewing/utils + +A collection of utilities shared across freesewing frontend projects + + + +## About FreeSewing 🤔 + +Where the world of makers and developers collide, that's where you'll find FreeSewing. + +Our [core library](https://freesewing.dev/en/freesewing) is a *batteries-included* toolbox +for parametric design of sewing patterns. It's a modular system (check our list +of [plugins](https://freesewing.dev/en/plugins) and getting started is as simple as: + +```bash +npm init freesewing-pattern +``` + +The [getting started] section on [freesewing.dev](https://freesewing.dev/) is a good +entrypoint to our documentation, but you'll find a lot more there, including +our [API documentation](https://freesewing.dev/en/freesewing/api), +as well as [examples](https://freesewing.dev/en/freesewing/examples), +and [best practices](https://freesewing.dev/en/do). + +If you're a maker, checkout [freesewing.org](https://freesewing/) where you can generate +our sewing patterns adapted to your measurements. + +## Support FreeSewing: Become a patron 🥰 + +FreeSewing is an open source project run by a community, +and financially supported by our patrons. + +If you feel what we do is worthwhile, you too +should [become a patron](https://freesewing.org/patrons/join). + +## Links 👩‍💻 + + - 💻 Makers website: [freesewing.org](https://freesewing.org) + - 💻 Developers website: [freesewing.dev](https://freesewing.org) + - 💬 Chat: [gitter.im/freesewing](https://gitter.im/freesewing/freesewing) + - 🐦 Twitter: [@freesewing_org](https://twitter.com/freesewing_org) + - 📷 Instagram: [@freesewing_org](https://instagram.com/freesewing_org) + +## License: MIT 🤓 + +© [Joost De Cock](https://github.com/joostdecock). +See [the license file](https://github.com/freesewing/freesewing/blob/develop/LICENSE) for details. + +## Where to get help 🤯 + +Our [chatroom on Gitter](https://gitter.im) is the best place to ask questions, +share your feedback, or just hang out. + +If you want to report a problem, please [create an issue](https://github.com/freesewing/freesewing/issues/new). diff --git a/packages/utils/package.json b/packages/utils/package.json new file mode 100644 index 00000000000..aeb68f614d2 --- /dev/null +++ b/packages/utils/package.json @@ -0,0 +1,46 @@ +{ + "name": "@freesewing/utils", + "version": "0.33.0", + "description": "A collection of utilities shared across freesewing frontend projects", + "author": "Joost De Cock (https://github.com/joostdecock)", + "homepage": "https://freesewing.org/", + "repository": "github:freesewing/freesewing", + "license": "MIT", + "bugs": { + "url": "https://github.com/freesewing/freesewing/issues" + }, + "keywords": [ + "freesewing", + "design", + "diy", + "fashion", + "made to measure", + "parametric design", + "sewing" + ], + "main": "dist/index.js", + "module": "dist/index.mjs", + "scripts": { + "clean": "rimraf ../../dist/utils", + "nodebuild": "BABEL_ENV=production rollup -c -o ../../dist/utils/index.js -f cjs", + "modulebuild": "BABEL_ENV=production rollup -c -o ../../dist/utils/index.mjs -f es", + "build": "npm run clean && npm run nodebuild && npm run modulebuild", + "test": "echo \"utils: No tests configured. Perhaps you'd like to do this?\" && exit 0", + "pubtest": "npm publish --registry http://localhost:6662" + }, + "peerDependencies": {}, + "dependencies": {}, + "devDependencies": {}, + "files": [ + "../../dist/packages/utils/*", + "README.md", + "package.json" + ], + "publishConfig": { + "access": "public" + }, + "engines": { + "node": ">=8.0.0", + "npm": ">=5" + } +} diff --git a/packages/utils/rollup.config.js b/packages/utils/rollup.config.js new file mode 100644 index 00000000000..a7121f8dd15 --- /dev/null +++ b/packages/utils/rollup.config.js @@ -0,0 +1,29 @@ +import babel from "rollup-plugin-babel"; +import resolve from "rollup-plugin-node-resolve"; +import json from "rollup-plugin-json"; +import minify from "rollup-plugin-babel-minify"; +import yaml from "rollup-plugin-yaml"; +import peerDepsExternal from "rollup-plugin-peer-deps-external"; +import { name, version, description, author, license } from "./package.json"; + +export default { + input: "src/index.js", + output: { + sourcemap: true + }, + plugins: [ + peerDepsExternal(), + resolve({ modulesOnly: true }), + json(), + yaml(), + babel({ + exclude: "node_modules/**", + plugins: ["@babel/plugin-proposal-object-rest-spread"] + }), + minify({ + comments: false, + sourceMap: true, + banner: `/**\n * ${name} | v${version}\n * ${description}\n * (c) ${new Date().getFullYear()} ${author}\n * @license ${license}\n */` + }) + ] +}; diff --git a/packages/utils/src/cloneObject.js b/packages/utils/src/cloneObject.js new file mode 100644 index 00000000000..05c150d07a9 --- /dev/null +++ b/packages/utils/src/cloneObject.js @@ -0,0 +1,3 @@ +const cloneObject = src => Object.assign({}, src); + +export default cloneObject; diff --git a/packages/utils/src/defaultGist.js b/packages/utils/src/defaultGist.js new file mode 100644 index 00000000000..23e630ccfb0 --- /dev/null +++ b/packages/utils/src/defaultGist.js @@ -0,0 +1,15 @@ +const defaultGist = { + settings: { + embed: true, + sa: 0, + complete: true, + paperless: false, + locale: "en", + units: "metric", + margin: 2, + measurements: {}, + options: {} + } +}; + +export default defaultGist; diff --git a/packages/utils/src/defaultSa.js b/packages/utils/src/defaultSa.js new file mode 100644 index 00000000000..5d1186b605c --- /dev/null +++ b/packages/utils/src/defaultSa.js @@ -0,0 +1,6 @@ +const defaultSa = { + imperial: 15.875, + metric: 10 +}; + +export default defaultSa; diff --git a/packages/utils/src/formatImperial.js b/packages/utils/src/formatImperial.js new file mode 100644 index 00000000000..56bad1e543b --- /dev/null +++ b/packages/utils/src/formatImperial.js @@ -0,0 +1,17 @@ +const formatImperial = ( + neg, + inch, + numo = false, + deno = false, + format = "html" +) => { + if (format === "html") { + if (numo) return `${neg}${inch}${numo}/${deno}`; + else return `{neg}{inch}`; + } else { + if (numo) return `${neg}${inch}`; + else return `${neg}${inch} ${numo}/${deno}`; + } +}; + +export default formatImperial; diff --git a/packages/utils/src/formatMm.js b/packages/utils/src/formatMm.js new file mode 100644 index 00000000000..b0695b3e38b --- /dev/null +++ b/packages/utils/src/formatMm.js @@ -0,0 +1,43 @@ +import roundMm from "./roundMm"; +import formatImperial from "./formatImperial"; + +const formatMm = (val, units, format = "html") => { + val = roundMm(val); + let H = format === "html" ? true : false; + if (units === "imperial") { + if (val == 0) return formatImperial("", 0, false, false, format); + let negative = ""; + let inches = ""; + let rest = ""; + let fraction = val / 25.4; + if (fraction < 0) { + fraction = fraction * -1; + negative = "-"; + } + if (Math.abs(fraction) < 1) rest = fraction; + else { + inches = Math.floor(fraction); + rest = fraction - inches; + } + let fraction128 = Math.round(rest * 128); + if (fraction128 == 0) return formatImperial(negative, inches); + if (fraction128 % 64 == 0) + return formatImperial(negative, inches, fraction128 / 64, 2); + if (fraction128 % 32 == 0) + return formatImperial(negative, inches, fraction128 / 32, 4); + if (fraction128 % 16 == 0) + return formatImperial(negative, inches, fraction128 / 16, 8); + if (fraction128 % 8 == 0) + return formatImperial(negative, inches, fraction128 / 8, 16); + if (fraction128 % 4 == 0) + return formatImperial(negative, inches, fraction128 / 4, 32); + if (fraction128 % 2 == 0) + return formatImperial(negative, inches, fraction128 / 2, 64); + return negative + fraction; + } else { + if (format === "html") return roundMm(val / 10) + "cm"; + else return roundMm(val / 10); + } +}; + +export default formatMm; diff --git a/packages/utils/src/gistDefaults.js b/packages/utils/src/gistDefaults.js new file mode 100644 index 00000000000..8fcdf2cabaa --- /dev/null +++ b/packages/utils/src/gistDefaults.js @@ -0,0 +1,29 @@ +import defaultGist from "./defaultGist"; +import optionDefault from "./optionDefault"; + +const gistDefaults = (config, gist = false) => { + if (!gist) gist = defaultGist; + let options = {}; + for (let option of Object.keys(config.options)) { + if ( + typeof gist.options !== "undefined" && + typeof gist.options[option] !== undefined + ) + options[option] = gist.options[option]; + else options[option] = optionDefault(config.options[option]); + } + delete gist.options; + let settings = JSON.parse(JSON.stringify(defaultGist.settings)); + delete settings.locale; + delete settings.units; + for (let setting of Object.keys(settings)) { + if (typeof gist.settings[setting] !== "undefined") { + settings[setting] = gist.settings[setting]; + } + } + settings.options = options; + + return settings; +}; + +export default gistDefaults; diff --git a/packages/utils/src/index.js b/packages/utils/src/index.js new file mode 100644 index 00000000000..f6e40167ec2 --- /dev/null +++ b/packages/utils/src/index.js @@ -0,0 +1,14 @@ +export { default as smallestImperialStep } from "./smallestImperialStep"; +export { default as roundMm } from "./roundMm"; +export { default as roundMmDown } from "./roundMmDown"; +export { default as roundMmUp } from "./roundMmUp"; +export { default as formatImperial } from "./formatImperial"; +export { default as formatMm } from "./formatMm"; +export { default as defaultSa } from "./defaultSa"; +export { default as sliderStep } from "./sliderStep"; +export { default as optionType } from "./optionType"; +export { default as defaultGist } from "./defaultGist"; +export { default as gistDefaults } from "./gistDefaults"; +export { default as optionDefault } from "./optionDefault"; +export { default as storage } from "./storage"; +export { default as cloneObject } from "./cloneObject"; diff --git a/packages/utils/src/optionDefault.js b/packages/utils/src/optionDefault.js new file mode 100644 index 00000000000..1da71374444 --- /dev/null +++ b/packages/utils/src/optionDefault.js @@ -0,0 +1,17 @@ +import optionType from "./optionType"; + +const optionDefault = option => { + let type = optionType(option); + switch (optionType(option)) { + case "constant": + return option; + break; + case "list": + return option.dflt; + break; + default: + return option[type]; + } +}; + +export default optionDefault; diff --git a/packages/utils/src/optionType.js b/packages/utils/src/optionType.js new file mode 100644 index 00000000000..226b598e2af --- /dev/null +++ b/packages/utils/src/optionType.js @@ -0,0 +1,15 @@ +const optionType = option => { + if (typeof option === "object") { + if (typeof option.pct !== "undefined") return "pct"; + if (typeof option.mm !== "undefined") return "mm"; + if (typeof option.deg !== "undefined") return "deg"; + if (typeof option.count !== "undefined") return "count"; + if (typeof option.bool !== "undefined") return "bool"; + if (typeof option.list !== "undefined") return "list"; + return "unknown"; + } + + return "constant"; +}; + +export default optionType; diff --git a/packages/utils/src/roundMm.js b/packages/utils/src/roundMm.js new file mode 100644 index 00000000000..ac52ffb2b33 --- /dev/null +++ b/packages/utils/src/roundMm.js @@ -0,0 +1,8 @@ +const roundMm = (val, units) => { + if (units === "imperial") + return Math.round(val * 1000000) / 1000000; + else + return Math.round(val * 10) / 10; +}; + +export default roundMm; diff --git a/packages/utils/src/roundMmDown.js b/packages/utils/src/roundMmDown.js new file mode 100644 index 00000000000..08888d0e978 --- /dev/null +++ b/packages/utils/src/roundMmDown.js @@ -0,0 +1,10 @@ +import smallestImperialStep from "./smallestImperialStep"; + +const roundMmDown = (val, units) => { + if (units === "imperial") + return val - (val % smallestImperialStep); + else + return Math.floor(val * 10) / 10; +}; + +export default roundMmDown; diff --git a/packages/utils/src/roundMmUp.js b/packages/utils/src/roundMmUp.js new file mode 100644 index 00000000000..6ec19fd3d1d --- /dev/null +++ b/packages/utils/src/roundMmUp.js @@ -0,0 +1,10 @@ +import smallestImperialStep from "./smallestImperialStep"; + +const roundMmUp = (val, units) => { + if (units === "imperial") + return val - (val % smallestImperialStep); + else + return Math.ceil(val * 10) / 10; +}; + +export default roundMmUp; diff --git a/packages/utils/src/sliderStep.js b/packages/utils/src/sliderStep.js new file mode 100644 index 00000000000..dd6b3a3772e --- /dev/null +++ b/packages/utils/src/sliderStep.js @@ -0,0 +1,6 @@ +const sliderStep = { + metric: 0.1, + imperial: 0.396875 +}; + +export default sliderStep; diff --git a/packages/utils/src/smallestImperialStep.js b/packages/utils/src/smallestImperialStep.js new file mode 100644 index 00000000000..eb5e20460b6 --- /dev/null +++ b/packages/utils/src/smallestImperialStep.js @@ -0,0 +1,3 @@ +const smallestImperialStep = 0.396875; + +export default smallestImperialStep; diff --git a/packages/utils/src/storage.js b/packages/utils/src/storage.js new file mode 100644 index 00000000000..a13aedc0ff0 --- /dev/null +++ b/packages/utils/src/storage.js @@ -0,0 +1,24 @@ +const storage = { + set: (key, value, raw) => { + if (typeof localStorage === "undefined") + throw(new Error("No localStorage support. And we need it. Bailing out.")); + + const _key = "fs_" + key; + + if (typeof value === "undefined" || value === null) + localStorage.removeItem(_key); + else localStorage.setItem(_key, raw ? value : JSON.stringify(value)); + + return value; + }, + get: (key, raw) => { + if (typeof localStorage === "undefined") + throw(new Error("No localStorage support. And we need it. Bailing out.")); + + const value = localStorage.getItem("fs_"+key); + + return raw ? value : JSON.parse(value); + } +} + +export default storage;