diff --git a/packages/plugin-mirror/.babelrc b/packages/plugin-mirror/.babelrc new file mode 100644 index 00000000000..957cae3e64d --- /dev/null +++ b/packages/plugin-mirror/.babelrc @@ -0,0 +1,10 @@ +{ + "presets": [ + [ + "@babel/preset-env", + { + "useBuiltIns": "entry" + } + ] + ] +} diff --git a/packages/plugin-mirror/CHANGELOG.md b/packages/plugin-mirror/CHANGELOG.md new file mode 100644 index 00000000000..1986927eac8 --- /dev/null +++ b/packages/plugin-mirror/CHANGELOG.md @@ -0,0 +1,3 @@ +# Change log for: @freesewing/plugin-mirror + +## Unreleased diff --git a/packages/plugin-mirror/README.md b/packages/plugin-mirror/README.md new file mode 100644 index 00000000000..60776eb9acb --- /dev/null +++ b/packages/plugin-mirror/README.md @@ -0,0 +1,99 @@ +![FreeSewing](https://freesewing.org/banner.jpg) + +

@freesewing/plugin-mirror on NPM + License: MIT + Code quality on DeepScan + Open issues tagged pkg:plugin-mirror +

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

+ +## What am I looking at? 🤔 + +This repository is our _monorepo_ holding [all our NPM packages](https://www.npmjs.com/search?q=keywords:freesewing). +This folder holds **@freesewing/plugin-mirror** + +A FreeSewing plugin to mirror parts and points accross a line + +## About FreeSewing 💀 + +Where the world of makers and developers collide, that's where you'll find FreeSewing. + +Our [core library](https://freesewing.dev/reference/api/) is a _batteries-included_ toolbox +for parametric design of sewing patterns. It's a modular system (check our list +of [plugins](https://freesewing.dev/reference/plugins/) and getting started is as simple as: + +```bash +npm init freesewing-pattern +``` + +The [getting started](https://freesewing.dev/guides/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 reference](https://freesewing.dev/reference/api/), +as well as [our turorial](https://freesewing.dev/tutorials/pattern-design/), +and [howtos](https://freesewing.dev/howtos/). + +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.dev) +- 💬 Chat: [gitter.im/freesewing](https://gitter.im/freesewing/chat) +- 🐦 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/freesewing/chat) 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/plugin-mirror/package.json b/packages/plugin-mirror/package.json new file mode 100644 index 00000000000..e9904495657 --- /dev/null +++ b/packages/plugin-mirror/package.json @@ -0,0 +1,52 @@ +{ + "name": "@freesewing/plugin-mirror", + "version": "2.6.0", + "description": "A FreeSewing plugin to mirror paths and points accross a line", + "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", + "plugin", + "sewing pattern", + "sewing", + "design", + "parametric design", + "made to measure", + "diy", + "fashion" + ], + "main": "dist/index.js", + "module": "dist/index.mjs", + "scripts": { + "clean": "rimraf dist", + "build": "npm run clean && rollup -c", + "test": "echo \"plugin-mirrors: No tests configured. Perhaps you'd like to do this?\" && exit 0", + "pubtest": "npm publish --registry http://localhost:6662", + "pubforce": "npm publish", + "symlink": "mkdir -p ./node_modules/@freesewing && cd ./node_modules/@freesewing && ln -s -f ../../../* . && cd -", + "start": "rollup -c -w" + }, + "peerDependencies": { + "@freesewing/core": "^2.6.0" + }, + "dependencies": {}, + "devDependencies": {}, + "files": [ + "dist/*", + "README.md", + "package.json" + ], + "publishConfig": { + "access": "public", + "tag": "latest" + }, + "engines": { + "node": ">=8.0.0", + "npm": ">=5" + } +} diff --git a/packages/plugin-mirror/rollup.config.js b/packages/plugin-mirror/rollup.config.js new file mode 100644 index 00000000000..142439a7f29 --- /dev/null +++ b/packages/plugin-mirror/rollup.config.js @@ -0,0 +1,41 @@ +import babel from 'rollup-plugin-babel' +import resolve from 'rollup-plugin-node-resolve' +import commonjs from 'rollup-plugin-commonjs' +import json from 'rollup-plugin-json' +import minify from 'rollup-plugin-babel-minify' +import peerDepsExternal from 'rollup-plugin-peer-deps-external' +import { name, version, description, author, license, main, module } from './package.json' + +const output = [ + { + file: main, + format: 'cjs', + sourcemap: true + } +] +if (typeof module !== 'undefined') + output.push({ + file: module, + format: 'es', + sourcemap: true + }) + +export default { + input: 'src/index.js', + output, + plugins: [ + peerDepsExternal(), + resolve({ modulesOnly: true }), + commonjs(), + json(), + 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/plugin-mirror/src/index.js b/packages/plugin-mirror/src/index.js new file mode 100644 index 00000000000..4453ef405f8 --- /dev/null +++ b/packages/plugin-mirror/src/index.js @@ -0,0 +1,83 @@ +import { name, version } from '../package.json' + +export const lineValues = (start, end) => { + const { x: x1, y: y1 } = end + const { x: x2, y: y2 } = start + const c = x1 * y2 - x2 * y1 + return [-(x1 - x2), y1 - y2, c] +} + +export const mirrorGen = (start, end) => { + const [A, B, C] = lineValues(start, end) + return (point) => { + const { x, y } = point + const uNom = (B ** 2 - A ** 2) * x - 2 * A * B * y - 2 * A * C + const vNom = (A ** 2 - B ** 2) * y - 2 * A * B * x - 2 * B * C + const denom = A ** 2 + B ** 2 + return [uNom / denom, vNom / denom] + } +} + +export default { + name: name, + version: version, + hooks: { + preRender: function (svg) { + if (svg.attributes.get('freesewing:plugin-mirror') === false) + svg.attributes.set('freesewing:plugin-mirror', version) + } + }, + macros: { + macros: { + mirror: function ({ + mirror, + clone = true, + points = null, + paths = null, + prefix = 'mirrored', + nameFormat // unimplemented + }) { + const [start, end] = mirror + const mirrorPoint = mirrorGen(start, end) + const ops = ['from', 'to', 'cp1', 'cp2'] + + if (paths !== null) { + paths.forEach((path) => { + // find existing path id + // Find point name from path by looking in the list of all points? + let foundId = null + for (let id of Object.keys(this.paths)) { + if (this.paths[id] === path) { + foundId = id + break + } + } + if (clone && foundId !== null) { + path = clone ? path.clone() : path + this.paths[`${prefix}${foundId}`] = path + } + for (let op in path.ops) { + for (let type of ops) { + // Iterate over all possible path op points and clone/move point + const pathOp = path.ops[op][type] + if (typeof pathOp !== 'undefined') { + ;[pathOp.x, pathOp.y] = mirrorPoint(pathOp) + pathOp.attributes.set('mirrored', true) + } + } + } + }) + } + if (points !== null) { + points.forEach((point) => { + if (clone) { + point = point.clone() + } + ;[point.x, point.y] = mirrorPoint(point) + point.attributes.set('mirrored', true) + }) + } + } + } + } +} diff --git a/packages/plugin-mirror/tests/mirror.test.js b/packages/plugin-mirror/tests/mirror.test.js new file mode 100644 index 00000000000..383d1589f1d --- /dev/null +++ b/packages/plugin-mirror/tests/mirror.test.js @@ -0,0 +1,12 @@ +import freesewing from 'freesewing' +import { version } from '../package.json' +let chai = require('chai') +let expect = chai.expect +chai.use(require('chai-string')) +let plugin = require('../dist/index.js') + +it('Should set the plugin name:version attribute', () => { + let pattern = new freesewing.Pattern().with(plugin) + pattern.render() + expect(pattern.svg.attributes.get('freesewing:plugin-mirror')).to.equal(version) +})