diff --git a/packages/plugin-bartack/.babelrc b/packages/plugin-bartack/.babelrc new file mode 100644 index 00000000000..957cae3e64d --- /dev/null +++ b/packages/plugin-bartack/.babelrc @@ -0,0 +1,10 @@ +{ + "presets": [ + [ + "@babel/preset-env", + { + "useBuiltIns": "entry" + } + ] + ] +} diff --git a/packages/plugin-bartack/CHANGELOG.md b/packages/plugin-bartack/CHANGELOG.md new file mode 100644 index 00000000000..bde96d7c315 --- /dev/null +++ b/packages/plugin-bartack/CHANGELOG.md @@ -0,0 +1,9 @@ +# Change log for: @freesewing/plugin-bartack + + + +This is the **initial release**, and the start of this change log. + +> Prior to version 2, FreeSewing was not a JavaScript project. +> As such, that history is out of scope for this change log. + diff --git a/packages/plugin-bartack/README.md b/packages/plugin-bartack/README.md new file mode 100644 index 00000000000..94da525cfe8 --- /dev/null +++ b/packages/plugin-bartack/README.md @@ -0,0 +1,118 @@ +![FreeSewing](https://static.freesewing.org/banner.png) +

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

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

+ +# @freesewing/plugin-bartack + +A FreeSewing plugin to add bartacks to your pattern + + + +## What am I looking at? 🤔 + +This repository is our *monorepo* +holding [all our NPM packages](https://freesewing.dev/reference/packages/). + +This folder holds: @freesewing/plugin-bartack + +## About FreeSewing 💀 + +Where the world of makers and developers collide, that's where you'll find FreeSewing. + +If you're a maker, checkout [freesewing.org](https://freesewing.org/) where you can generate +our sewing patterns adapted to your measurements. + +If you're a developer, our documentation is on [freesewing.dev](https://freesewing.dev/). +Our [core library](https://freesewing.dev/reference/api/) is a *batteries-included* toolbox +for parametric design of sewing patterns. But we also provide a range +of [plugins](https://freesewing.dev/reference/plugins/) that further extend the +functionality of the platform. + +If you have NodeJS installed, you can try it right now by running: + +```bash +npx create-freesewing-pattern +``` + +Or, consult our getting started guides +for [Linux](https://freesewing.dev/tutorials/getting-started-linux/), +[MacOS](https://freesewing.dev/tutorials/getting-started-mac/), +or [Windows](https://freesewing.dev/tutorials/getting-started-windows/). + +We also have a [pattern design tutorial](https://freesewing.dev/tutorials/pattern-design/) that +walks you through your first parametric design, +and [a friendly community](https://freesewing.org/community/where/) with +people who can help you when you get stuck. + +## 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, and you can spend a few coind without +hardship, then you should [join us and become a patron](https://freesewing.org/community/join). + +## Links 👩‍💻 + + - 💻 Makers website: [freesewing.org](https://freesewing.org) + - 💻 Developers website: [freesewing.dev](https://freesewing.dev) + - 💬 Chat: On Discord via [chat.freesewing.org](https://chat.freesewing.org/) + - ✅ Todo list/Kanban board: On Github via [todo.freesewing.org](https://todo.freesewing.org/) + - 🐦 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 [chatrooms on Discord](https://chat.freesewing.org/) are 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-bartack/img/example.png b/packages/plugin-bartack/img/example.png new file mode 100644 index 00000000000..70ea646c479 Binary files /dev/null and b/packages/plugin-bartack/img/example.png differ diff --git a/packages/plugin-bartack/package.json b/packages/plugin-bartack/package.json new file mode 100644 index 00000000000..382bb294c7f --- /dev/null +++ b/packages/plugin-bartack/package.json @@ -0,0 +1,55 @@ +{ + "name": "@freesewing/plugin-bartack", + "version": "2.14.0", + "description": "A FreeSewing plugin to add bartacks to your pattern", + "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": "rollup -c", + "test": "echo \"plugin-bartack: 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.14.0" + }, + "dependencies": {}, + "devDependencies": {}, + "files": [ + "dist/*", + "README.md", + "package.json" + ], + "publishConfig": { + "access": "public", + "tag": "latest" + }, + "engines": { + "node": ">=12.0.0", + "npm": ">=6" + }, + "rollup": { + "exports": "default" + } +} diff --git a/packages/plugin-bartack/rollup.config.js b/packages/plugin-bartack/rollup.config.js new file mode 100644 index 00000000000..a885f4cb4ec --- /dev/null +++ b/packages/plugin-bartack/rollup.config.js @@ -0,0 +1,37 @@ +import resolve from '@rollup/plugin-node-resolve' +import commonjs from '@rollup/plugin-commonjs' +import json from '@rollup/plugin-json' +import { terser } from 'rollup-plugin-terser' +import peerDepsExternal from 'rollup-plugin-peer-deps-external' +import { name, version, description, author, license, main, module, rollup } from './package.json' + +const output = [ + { + file: main, + format: 'cjs', + sourcemap: true, + exports: rollup.exports + } +] +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(), + terser({ + output: { + preamble: `/**\n * ${name} | v${version}\n * ${description}\n * (c) ${new Date().getFullYear()} ${author}\n * @license ${license}\n */` + } + }) + ] +} diff --git a/packages/plugin-bartack/src/bartack.js b/packages/plugin-bartack/src/bartack.js new file mode 100644 index 00000000000..7b491a54cfb --- /dev/null +++ b/packages/plugin-bartack/src/bartack.js @@ -0,0 +1,92 @@ +const name = (n, so) => `${so.prefix}${n}${so.suffix}` + +const drawBartack = (points, so, self) => { + let path = new self.Path().move(points.path1[0]) + for (let i in points.path1) { + if (points.path1[i]) path = path.line(points.path1[i]) + if (points.path2[i]) path = path.line(points.path2[i]) + } + + return path +} + +const getPoints = (path, so, self) => { + let path1 = path.offset(so.width / 2) + let path2 = path.offset(so.width / -2) + let len1 = path1.length() + let len2 = path2.length() + + // Make sure path1 is always the longest one + if (len2 > len1) { + let tmp = path2 + path2 = path1 + path1 = tmp + tmp = len2 + len2 = len1 + len1 = tmp + } + + let points = { + path1: [path1.start()], + path2: [path2.start()] + } + let steps = Math.ceil((len1 / so.width) * so.density) + for (let i = 1; i < steps; i++) { + points.path1.push(path1.shiftFractionAlong((1 / steps) * i)) + points.path2.push(path2.shiftFractionAlong((1 / steps) * i)) + } + + return points +} + +const bartackPath = (path, so, self) => + path ? drawBartack(getPoints(path, so, self), so, self) : null + +export default function bartack(so, self) { + const defaults = { + width: 3, + length: 15, + density: 3, + angle: 0, + prefix: '', + suffix: '', + anchor: false, + path: false, + from: false, + to: false, + start: 0, + end: 1, + bartackAlong: false, + bartackFractionAlong: false + } + so = { ...defaults, ...so } + + let guide = false + + if (so.anchor) + // Anchor + angle + length + guide = new self.Path().move(so.anchor).line(so.anchor.shift(so.angle, so.length)) + else if (so.from && so.to) + // From to + guide = new self.Path().move(so.from).line(so.to) + else if (so.path) { + // Along path + let start = false + let end = false + if (so.bartackAlong) { + if (so.start > 0) start = so.path.shiftAlong(so.start) + if (end < so.path.length) end = so.path.shiftAlong(so.end) + } else if (so.bartackFractionAlong) { + if (so.start > 0) start = so.path.shiftFractionAlong(so.start) + if (so.end < 1) end = so.path.shiftFractionAlong(so.end) + } + if (start && end) guide = so.path.split(start).pop().split(end).shift() + else if (start) guide = so.path.split(start).pop() + else if (end) guide = so.path.split(end).shift() + else guide = so.path.clone() + } + + self.paths[name('bartack', so)] = bartackPath(guide, so, self).attr('class', 'stroke-sm bartack') + + return true +} diff --git a/packages/plugin-bartack/src/index.js b/packages/plugin-bartack/src/index.js new file mode 100644 index 00000000000..a70bed9fb28 --- /dev/null +++ b/packages/plugin-bartack/src/index.js @@ -0,0 +1,30 @@ +import { name, version } from '../package.json' +import bartack from './bartack' + +export default { + name: name, + version: version, + hooks: { + preRender: function (svg) { + if (svg.attributes.get('freesewing:plugin-bartack') === false) { + svg.attributes.set('freesewing:plugin-bartack', version) + } + } + }, + macros: { + bartack: function (so) { + let self = this + return bartack(so, self) + }, + bartackAlong: function (so) { + let self = this + so.bartackAlong = true + return bartack(so, self) + }, + bartackFractionAlong: function (so) { + let self = this + so.bartackFractionAlong = true + return bartack(so, self) + } + } +} diff --git a/packages/plugin-bartack/tests/buttons.test.js b/packages/plugin-bartack/tests/buttons.test.js new file mode 100644 index 00000000000..4141ee3457f --- /dev/null +++ b/packages/plugin-bartack/tests/buttons.test.js @@ -0,0 +1,14 @@ +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(); + pattern.use(plugin).draft().render(); + expect(pattern.svg.attributes.get("freesewing:plugin-buttons")).to.equal( + version + ); +});