diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8c5c9a62129..d8ce771d605 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -649,6 +649,12 @@
- Migrated from Rollup to Esbuild for all builds
+### unice
+
+#### Added
+
+ - Unice is an underwear pattern
+
### ursula
#### Changed
@@ -679,12 +685,6 @@
### yuri
-#### Changed
-
- - Migrated from Rollup to Esbuild for all builds
-
-### examples
-
#### Changed
- Migrated from Rollup to Esbuild for all builds
@@ -1272,16 +1272,6 @@
### yuri
-#### Changed
-
- - Switched to default import for version from package.json
-
-### examples
-
-#### Added
-
- - Added plugin_gore example
-
#### Changed
- Switched to default import for version from package.json
@@ -2537,13 +2527,6 @@
- Added the (disabled) waistbandHeight option from Titan
- Changed to Titan's waistbandWidth option
-### examples
-
-#### Added
-
- - Added examples for bartack plugin
- - Added examples for new buttonhole-start/end snippets
-
### plugin-buttons
#### Added
@@ -4029,12 +4012,6 @@
### wahid
-#### Added
-
- - Initial release
-
-### examples
-
#### Added
- Initial release
diff --git a/config/dependencies.yaml b/config/dependencies.yaml
index e85429c6203..cdd3832178f 100644
--- a/config/dependencies.yaml
+++ b/config/dependencies.yaml
@@ -65,10 +65,6 @@ diana:
peer:
'@freesewing/brian': *freesewing
'@freesewing/plugin-bust': *freesewing
-examples:
- peer:
- '@freesewing/plugin-mirror': *freesewing
- '@freesewing/plugin-gore': *freesewing
holmes:
_:
'@freesewing/plugin-gore': *freesewing
diff --git a/config/keywords.yaml b/config/keywords.yaml
index f6b93f28536..7b04674c8cf 100644
--- a/config/keywords.yaml
+++ b/config/keywords.yaml
@@ -24,10 +24,6 @@ design:
- pattern
- sewing
- sewing pattern
-examples:
- - documentation
- - example
- - parametric design
i18n:
- i18n
- internationalisation
diff --git a/config/software/designs.json b/config/software/designs.json
index 75abc902887..d235ed76bb6 100644
--- a/config/software/designs.json
+++ b/config/software/designs.json
@@ -284,6 +284,13 @@
"difficulty": 1,
"tags": [ "tops", "historic" ]
},
+ "unice": {
+ "description": "A FreeSewing pattern for a basic, highly-customizable underwear pattern",
+ "code": [ "Anna Puk", "Natalia Sayang" ],
+ "design": [ "Anna Puk", "Natalia Sayang" ],
+ "difficulty": 1,
+ "tags": [ "bottoms", "underwear" ]
+ },
"ursula": {
"description": "A FreeSewing pattern for a basic, highly-customizable underwear pattern",
"code": "Natalia Sayang",
@@ -321,10 +328,6 @@
}
},
"utilities": {
- "examples": {
- "description": "A FreeSewing pattern holding examples for our documentation",
- "code": "Joost De Cock"
- },
"legend": {
"description": "A FreeSewing pattern to document pattern notation",
"code": "Joost De Cock"
diff --git a/designs/albert/src/front.mjs b/designs/albert/src/front.mjs
index 060bfff42c0..c35c2af6e1a 100644
--- a/designs/albert/src/front.mjs
+++ b/designs/albert/src/front.mjs
@@ -6,52 +6,52 @@ const crossBox = {
name: 'crossbox',
version,
macros: {
- crossBox: function (so) {
- let id = this.getId()
+ crossBox: function (so, { points, Point, paths, Path, getId }) {
+ let id = getId()
let shiftFraction = 0.1
- this.points[id + '_boxTopLeft'] = so.from.copy()
- this.points[id + '_boxBottomRight'] = so.to.copy()
- this.points[id + '_boxTopRight'] = new this.Point(so.to.x, so.from.y)
- this.points[id + '_boxBottomLeft'] = new this.Point(so.from.x, so.to.y)
+ points[id + '_boxTopLeft'] = so.from.copy()
+ points[id + '_boxBottomRight'] = so.to.copy()
+ points[id + '_boxTopRight'] = new Point(so.to.x, so.from.y)
+ points[id + '_boxBottomLeft'] = new Point(so.from.x, so.to.y)
- this.points[id + '_topCrossTL'] = this.points[id + '_boxTopLeft'].shiftFractionTowards(
- this.points[id + '_boxBottomRight'],
+ points[id + '_topCrossTL'] = points[id + '_boxTopLeft'].shiftFractionTowards(
+ points[id + '_boxBottomRight'],
shiftFraction
)
- this.points[id + '_topCrossTR'] = this.points[id + '_boxTopRight'].shiftFractionTowards(
- this.points[id + '_boxBottomLeft'],
+ points[id + '_topCrossTR'] = points[id + '_boxTopRight'].shiftFractionTowards(
+ points[id + '_boxBottomLeft'],
shiftFraction
)
- this.points[id + '_topCrossBL'] = this.points[id + '_boxBottomLeft'].shiftFractionTowards(
- this.points[id + '_boxTopRight'],
+ points[id + '_topCrossBL'] = points[id + '_boxBottomLeft'].shiftFractionTowards(
+ points[id + '_boxTopRight'],
shiftFraction
)
- this.points[id + '_topCrossBR'] = this.points[id + '_boxBottomRight'].shiftFractionTowards(
- this.points[id + '_boxTopLeft'],
+ points[id + '_topCrossBR'] = points[id + '_boxBottomRight'].shiftFractionTowards(
+ points[id + '_boxTopLeft'],
shiftFraction
)
- this.paths[id + 'crossBox'] = new this.Path()
- .move(this.points[id + '_boxTopLeft'])
- .line(this.points[id + '_boxTopRight'])
- .line(this.points[id + '_boxBottomRight'])
- .line(this.points[id + '_boxBottomLeft'])
- .line(this.points[id + '_boxTopLeft'])
+ paths[id + 'crossBox'] = new Path()
+ .move(points[id + '_boxTopLeft'])
+ .line(points[id + '_boxTopRight'])
+ .line(points[id + '_boxBottomRight'])
+ .line(points[id + '_boxBottomLeft'])
+ .line(points[id + '_boxTopLeft'])
.close()
.attr('class', 'lining dotted stroke-sm')
- this.paths[id + '_topCross'] = new this.Path()
- .move(this.points[id + '_topCrossTL'])
- .line(this.points[id + '_topCrossBR'])
- .line(this.points[id + '_topCrossTR'])
- .line(this.points[id + '_topCrossBL'])
- .line(this.points[id + '_topCrossTL'])
- .line(this.points[id + '_topCrossTR'])
- .move(this.points[id + '_topCrossBR'])
- .line(this.points[id + '_topCrossBL'])
+ paths[id + '_topCross'] = new Path()
+ .move(points[id + '_topCrossTL'])
+ .line(points[id + '_topCrossBR'])
+ .line(points[id + '_topCrossTR'])
+ .line(points[id + '_topCrossBL'])
+ .line(points[id + '_topCrossTL'])
+ .line(points[id + '_topCrossTR'])
+ .move(points[id + '_topCrossBR'])
+ .line(points[id + '_topCrossBL'])
.attr('class', 'lining dotted stroke-sm')
if (typeof so.text === 'string') {
- this.points.textAnchor = this.points[id + '_boxTopLeft']
- .shiftFractionTowards(this.points[id + '_boxBottomRight'], 0.5)
+ points.textAnchor = points[id + '_boxTopLeft']
+ .shiftFractionTowards(points[id + '_boxBottomRight'], 0.5)
.attr('data-text', so.text)
.attr('data-text-class', 'center')
}
diff --git a/designs/charlie/src/fly-extension.mjs b/designs/charlie/src/fly-extension.mjs
index b45f7ea5005..cb3a19bebb4 100644
--- a/designs/charlie/src/fly-extension.mjs
+++ b/designs/charlie/src/fly-extension.mjs
@@ -27,7 +27,7 @@ function draftCharlieFlyExtension({ points, paths, Path, complete, macro, sa, pa
.line(points.styleWaistIn)
.line(points.flyTop)
.hide()
- paths.seam = paths.saBase.clone().line(points.flyCorner).close().hide().attr('class', 'fabric')
+ paths.seam = paths.saBase.clone().line(points.flyCorner).close().unhide().attr('class', 'fabric')
if (complete) {
macro('cutonfold', {
diff --git a/designs/examples/CHANGELOG.md b/designs/examples/CHANGELOG.md
deleted file mode 100644
index 0173d7207ac..00000000000
--- a/designs/examples/CHANGELOG.md
+++ /dev/null
@@ -1,38 +0,0 @@
-# Change log for: @freesewing/examples
-
-
-## 2.21.0 (2022-06-27)
-
-### Changed
-
- - Migrated from Rollup to Esbuild for all builds
-
-## 2.20.0 (2022-01-24)
-
-### Added
-
- - Added plugin_gore example
-
-### Changed
-
- - Switched to default import for version from package.json
-
-## 2.15.0 (2021-04-15)
-
-### Added
-
- - Added examples for bartack plugin
- - Added examples for new buttonhole-start/end snippets
-
-## 2.0.0 (2019-08-25)
-
-### Added
-
- - Initial release
-
-
-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/designs/examples/config/index.js b/designs/examples/config/index.js
deleted file mode 100644
index c7219e59e22..00000000000
--- a/designs/examples/config/index.js
+++ /dev/null
@@ -1,122 +0,0 @@
-import pkg from '../package.json' assert { type: 'json' }
-
-const { version } = pkg
-
-export default {
- version,
- name: 'examples',
- design: 'Joost De Cock',
- code: 'Joost De Cock',
- department: 'womenswear',
- type: 'pattern',
- difficulty: 1,
- tags: ['example'],
- optionGroups: {
- fit: ['fixme'],
- },
- measurements: [],
- dependencies: {
- //point_attr: 'path_attr'
- },
- parts: [
- 'point_attr',
- 'path_move',
- 'path_line',
- 'path_curve',
- 'path__curve',
- 'path_curve_',
- 'path_close',
- 'path_ops',
- 'path_attr',
- 'path_clone',
- 'path_divide',
- 'path_edge',
- 'path_end',
- 'path_intersects',
- 'path_intersectsx',
- 'path_intersectsy',
- 'path_join',
- 'path_length',
- 'path_noop',
- 'path_offset',
- 'path_reverse',
- 'path_shiftalong',
- 'path_shiftfractionalong',
- 'path_split',
- 'path_start',
- 'path_translate',
- 'path_trim',
- 'plugin_banner',
- 'plugin_bartack',
- 'plugin_bartackalong',
- 'plugin_bartackfractionalong',
- 'plugin_buttons',
- 'plugin_cutonfold',
- 'plugin_dimension',
- 'plugin_gore',
- 'plugin_grainline',
- 'plugin_logo',
- 'plugin_mirror',
- 'plugin_notches',
- 'plugin_round',
- 'plugin_scalebox',
- 'plugin_sprinkle',
- 'plugin_title',
- 'point_angle',
- 'point_attr',
- 'point_clone',
- 'point_copy',
- 'point_dist',
- 'point_dx',
- 'point_dy',
- 'point_flipx',
- 'point_flipy',
- 'point_shift',
- 'point_shiftfractiontowards',
- 'point_shifttowards',
- 'point_shiftoutwards',
- 'point_sitson',
- 'point_sitsroughlyon',
- 'point_rotate',
- 'point_translate',
- 'settings_sa',
- 'snippet',
- 'snippet_attr',
- 'snippet_clone',
- 'snippets_bnotch',
- 'snippets_notch',
- 'snippets_button',
- 'snippets_buttonhole',
- 'snippets_buttonhole_start',
- 'snippets_buttonhole_end',
- 'snippets_snapsocket',
- 'snippets_snapstud',
- 'snippets_logo',
- 'utils_linesintersect',
- 'utils_beamsintersect',
- 'utils_beamintersectsx',
- 'utils_beamintersectsy',
- 'utils_lineintersectscurve',
- 'utils_curvesintersect',
- 'utils_pointonbeam',
- 'utils_pointonline',
- 'utils_pointoncurve',
- 'utils_circlesintersect',
- 'utils_beamintersectscircle',
- 'utils_lineintersectscircle',
- 'utils_curveintersectsy',
- 'utils_curveintersectsx',
- 'utils_splitcurve',
- 'docs_overview',
- 'docs_coords',
- ],
- options: {
- focus: '',
- // Optiongroups are needed for now, because workbench
- fixme: {
- pct: 50,
- min: 0,
- max: 100,
- },
- },
-}
diff --git a/designs/examples/src/docs.mjs b/designs/examples/src/docs.mjs
deleted file mode 100644
index e00000a3d42..00000000000
--- a/designs/examples/src/docs.mjs
+++ /dev/null
@@ -1,321 +0,0 @@
-import { box } from './shared.mjs'
-
-export const docs_coords = {
- name: 'examples.box_coords',
- draft: ({ Point, points, paths, Path, part }) => {
- points.origin = new Point(10, 10)
- points.x = new Point(100, 10)
- points.y = new Point(10, 50)
- points.textX = points.x.shift(135, 2).attr('data-text', 'X')
- points.textY = points.y.shift(180, 5).attr('data-text', 'Y')
- paths.coords = new Path()
- .move(points.y)
- .line(points.origin)
- .line(points.x)
- .attr('class', 'mark')
- .attr('marker-start', 'url(#dimensionFrom)')
- .attr('marker-end', 'url(#dimensionTo)')
-
- return box(part, 100, 50)
- },
-}
-
-export const docs_overview = {
- name: 'examples.docs_overview',
- draft: ({ Point, points, Path, paths, options, part }) => {
- /**
- * Returs the value passed to it randomized with a given tolerance
- */
- const about = (value, tolerance = 5) => {
- let randomized = (tolerance / 100) * Math.random() * value
- let fixed = (1 - tolerance / 100) * value
-
- return fixed + randomized
- }
-
- /**
- * like about, but also randomly makes value negative
- * This is for degrees
- */
- const nabout = (value, tolerance = 5) => {
- if (Math.random() > 0.5) return about(value, tolerance)
- else return -1 * about(value, tolerance)
- }
-
- /**
- * Draws a w*h box that's randomized by tolerance to give it
- * that hand-drawn look.
- *
- * Returns a Path object
- */
- const box = (name, origin, width, height, tolerance = 10) => {
- let base = height
- if (width < height) base = width
- let t = base * (tolerance / 100)
- points[name + 'TopLeft'] = new Point(about(origin.x, t), about(origin.y, t))
- points[name + 'BottomLeft'] = new Point(about(origin.x, t), about(origin.y + height, t))
- points[name + 'BottomRight'] = new Point(
- about(origin.x + width, t),
- about(origin.y + height, t)
- )
- points[name + 'TopRight'] = new Point(about(origin.x + width, t), about(origin.y, t))
- points[name + 'Mid'] = points[name + 'TopLeft'].shiftFractionTowards(
- points[name + 'BottomRight'],
- 0.5
- )
- points[name + 'Mid'].y += 3
-
- let f = 0.3
- let r = tolerance / 2
- points[name + 'TopLeftCp1'] = points[name + 'TopLeft']
- .shiftFractionTowards(points[name + 'BottomLeft'], about(f))
- .rotate(nabout(r), points[name + 'TopLeft'])
- points[name + 'TopLeftCp2'] = points[name + 'TopLeft']
- .shiftFractionTowards(points[name + 'TopRight'], about(f))
- .rotate(nabout(r), points[name + 'TopLeft'])
- points[name + 'BottomLeftCp1'] = points[name + 'BottomLeft']
- .shiftFractionTowards(points[name + 'TopLeft'], about(f))
- .rotate(nabout(r), points[name + 'BottomLeft'])
- points[name + 'BottomLeftCp2'] = points[name + 'BottomLeft']
- .shiftFractionTowards(points[name + 'BottomRight'], about(f))
- .rotate(nabout(r), points[name + 'BottomLeft'])
- points[name + 'BottomRightCp1'] = points[name + 'BottomRight']
- .shiftFractionTowards(points[name + 'BottomLeft'], about(f))
- .rotate(nabout(r), points[name + 'BottomRight'])
- points[name + 'BottomRightCp2'] = points[name + 'BottomRight']
- .shiftFractionTowards(points[name + 'TopRight'], about(f))
- .rotate(nabout(r), points[name + 'BottomRight'])
- points[name + 'TopRightCp1'] = points[name + 'TopRight']
- .shiftFractionTowards(points[name + 'BottomRight'], about(f))
- .rotate(nabout(r), points[name + 'TopRight'])
- points[name + 'TopRightCp2'] = points[name + 'TopRight']
- .shiftFractionTowards(points[name + 'TopLeft'], about(f))
- .rotate(nabout(r), points[name + 'TopRight'])
-
- return new Path()
- .move(points[name + 'TopLeft'])
- .curve(
- points[name + 'TopLeftCp1'],
- points[name + 'BottomLeftCp1'],
- points[name + 'BottomLeft']
- )
- .curve(
- points[name + 'BottomLeftCp2'],
- points[name + 'BottomRightCp1'],
- points[name + 'BottomRight']
- )
- .curve(
- points[name + 'BottomRightCp2'],
- points[name + 'TopRightCp1'],
- points[name + 'TopRight']
- )
- .curve(points[name + 'TopRightCp2'], points[name + 'TopLeftCp2'], points[name + 'TopLeft'])
- .close()
- .attr('class', options.focus === name ? 'note' : 'fabric')
- }
-
- /**
- * Draws an arrow from to
- * Returns a Path object
- */
- const arrow = (name, text = '', tolerance = 10) => {
- let from = points[name + 'From']
- let to = points[name + 'To']
- from = from.shiftTowards(to, 3)
- to = to.shiftTowards(from, 3)
- let base = from.dist(to)
- let t = base * (tolerance / 100)
- from.x = about(from.x, t)
- from.x = about(from.x, t)
- to.x = about(to.x, t)
- to.x = about(to.x, t)
- let f = 0.3
- let r = tolerance / 2
- points[name + 'FromCp'] = from.shiftFractionTowards(to, about(f)).rotate(nabout(r), from)
- points[name + 'ToCp'] = to.shiftFractionTowards(from, about(f)).rotate(nabout(r), to)
- points[name + 'Tip1'] = to.shiftTowards(from, about(3.8)).rotate(about(15), to)
- points[name + 'Tip2'] = to.shiftTowards(from, about(3.5)).rotate(about(-15), to)
- let path = new Path()
- .move(from)
- .curve(points[name + 'FromCp'], points[name + 'ToCp'], to)
- .move(points[name + 'Tip1'])
- .line(to)
- .line(points[name + 'Tip2'])
- .attr('class', 'fabric')
- if (options.focus === name) path = path.attr('class', 'note')
- if (text)
- return path
- .attr('data-text', ' ' + text)
- .attr('data-text-class', 'scribble')
- .attr('data-text-class', options.focus === name ? 'fill-note' : '')
- else return path
- }
-
- const drawBox = (name, x, y, width, height, tolerance = 5, text = true) => {
- points[name + 'Origin'] = new Point(x, y)
- paths[name] = box(name, points[name + 'Origin'], width, height, tolerance)
- if (text) {
- points[name + 'Mid'].attr('data-text', name).attr('data-text-class', 'center scribble')
- if (options.focus === name) points[name + 'Mid'].attr('data-text-class', 'fill-note')
- }
- }
-
- const svgLogo = (anchor, size = 1) => {
- points.svg15 = anchor
- .shift(45, 4 * size)
- .attr('data-circle', 1.2 * size)
- .attr('data-circle-class', 'fill-fabric')
- points.svg3 = anchor
- .shift(0, 4 * size)
- .attr('data-circle', 1.2 * size)
- .attr('data-circle-class', 'fill-fabric')
- points.svg45 = anchor
- .shift(-45, 4 * size)
- .attr('data-circle', 1.2 * size)
- .attr('data-circle-class', 'fill-fabric')
- points.svg6 = anchor
- .shift(-90, 4 * size)
- .attr('data-circle', 1.2 * size)
- .attr('data-circle-class', 'fill-fabric')
- points.svg75 = anchor
- .shift(-135, 4 * size)
- .attr('data-circle', 1.2 * size)
- .attr('data-circle-class', 'fill-fabric')
- points.svg9 = anchor
- .shift(180, 4 * size)
- .attr('data-circle', 1.2 * size)
- .attr('data-circle-class', 'fill-fabric')
- points.svg105 = anchor
- .shift(135, 4 * size)
- .attr('data-circle', 1.2 * size)
- .attr('data-circle-class', 'fill-fabric')
- points.svg12 = anchor
- .shift(90, 4 * size)
- .attr('data-circle', 1.2 * size)
- .attr('data-circle-class', 'fill-fabric')
- points.svgText = anchor
- .clone()
- .attr('data-text', 'SVG')
- .attr('data-text-class', 'text-xl scribble')
- points.svgText.x += size * 7
- points.svgText.y += 6
- paths.svgLogo = new Path()
- .move(points.svg15)
- .line(points.svg75)
- .move(points.svg3)
- .line(points.svg9)
- .move(points.svg45)
- .line(points.svg105)
- .move(points.svg6)
- .line(points.svg12)
- .attr('class', 'stroke-l')
- }
- const reactLogo = (anchor, size = 1) => {
- h = 3 * size
- w = 6 * size
- points.reactTop1 = anchor.shift(45, w)
- points.reactBottom1 = anchor.shift(-135, w)
- points.reactTop1Cp1 = points.reactTop1.shift(135, h)
- points.reactTop1Cp2 = points.reactTop1.shift(-45, h)
- points.reactBottom1Cp1 = points.reactBottom1.shift(135, h)
- points.reactBottom1Cp2 = points.reactBottom1.shift(-45, h)
- points.reactTop2 = points.reactTop1.rotate(60, anchor)
- points.reactBottom2 = points.reactBottom1.rotate(60, anchor)
- points.reactTop2Cp1 = points.reactTop1Cp1.rotate(60, anchor)
- points.reactTop2Cp2 = points.reactTop1Cp2.rotate(60, anchor)
- points.reactBottom2Cp1 = points.reactBottom1Cp1.rotate(60, anchor)
- points.reactBottom2Cp2 = points.reactBottom1Cp2.rotate(60, anchor)
- points.reactTop3 = points.reactTop1.rotate(-60, anchor)
- points.reactBottom3 = points.reactBottom1.rotate(-60, anchor)
- points.reactTop3Cp1 = points.reactTop1Cp1.rotate(-60, anchor)
- points.reactTop3Cp2 = points.reactTop1Cp2.rotate(-60, anchor)
- points.reactBottom3Cp1 = points.reactBottom1Cp1.rotate(-60, anchor)
- points.reactBottom3Cp2 = points.reactBottom1Cp2.rotate(-60, anchor)
- points.svgLogo = anchor
- .clone()
- .attr('data-circle', 1 * size)
- .attr('data-circle-class', 'fill-fabric')
- points.reactText = anchor
- .clone()
- .attr('data-text', 'React')
- .attr('data-text-class', 'text-xl scribble')
- points.reactText.x += size * 7
- points.reactText.y += 6
-
- paths.reactLogo = new Path()
- .move(points.reactTop1)
- .curve(points.reactTop1Cp1, points.reactBottom1Cp1, points.reactBottom1)
- .curve(points.reactBottom1Cp2, points.reactTop1Cp2, points.reactTop1)
- .close()
- .move(points.reactTop2)
- .curve(points.reactTop2Cp1, points.reactBottom2Cp1, points.reactBottom2)
- .curve(points.reactBottom2Cp2, points.reactTop2Cp2, points.reactTop2)
- .close()
- .move(points.reactTop3)
- .curve(points.reactTop3Cp1, points.reactBottom3Cp1, points.reactBottom3)
- .curve(points.reactBottom3Cp2, points.reactTop3Cp2, points.reactTop3)
- .close()
- }
-
- // Other parts first so they're behind
- drawBox('Part4', 4, -19, 40, 65, 5, false)
- drawBox('Part3', 1, -16, 40, 65, 5, false)
- drawBox('Part2', -2, -13, 40, 65, 5, false)
- drawBox('Part', -5, -10, 40, 65, 5)
- paths.Part4.attr('class', 'fill-bg')
- paths.Part3.attr('class', 'fill-bg')
- paths.Part2.attr('class', 'fill-bg')
- paths.Part.attr('class', 'fill-bg')
- points.PartMid.y = points.PartTopLeft.y + 9
- let x = 0
- let y = 0
- let w = 30
- let h = 15
- drawBox('Points', x, y, w, h)
- y += 18
- drawBox('Paths', x, y, w, h)
- y += 18
- drawBox('Snippets', x, y, w, h)
- x = -35
- y = -3
- w = 25
- h = 20
- drawBox('config', x, y, w, h)
- y += 23
- drawBox('Store', x, y, w, h)
- x = -40
- y = -30
- drawBox('Pattern', x, y, 90, 90)
- points.PatternMid.y = points.PatternTopLeft.y + 9
-
- drawBox('settings', -100, 6, 40, 20)
- drawBox('draft', 80, 3, 20, 25)
-
- points.arrow1From = points.settingsTopRight.shiftFractionTowards(
- points.settingsBottomRight,
- 0.5
- )
- points.arrow1To = points.PatternTopLeft.shiftFractionTowards(points.PatternBottomLeft, 0.5)
- paths.arrow1 = arrow('arrow1')
- points.arrow2From = points.PatternTopRight.shiftFractionTowards(points.PatternBottomRight, 0.5)
- points.arrow2To = points.draftTopLeft.shiftFractionTowards(points.draftBottomLeft, 0.5)
- paths.arrow2 = arrow('arrow2', 'draft()')
-
- svgLogo(points.draftMid.shift(70, 50))
- reactLogo(points.draftMid.shift(-80, 36))
-
- points.arrow3From = points.draftTopLeft.shiftFractionTowards(points.draftTopRight, 0.5)
- points.arrow3To = points.svgText.clone()
- paths.arrow3 = arrow('arrow3', 'render()')
- points.arrow4From = points.draftBottomLeft.shiftFractionTowards(points.draftBottomRight, 0.5)
- points.arrow4To = points.reactText.clone().shift(40, 15)
- paths.arrow4 = arrow('arrow4')
-
- paths.extend = new Path()
- .move(points.draftTopRight)
- .line(points.draftTopRight.shift(0, 40))
- .attr('class', 'hidden')
-
- return part
- },
-}
diff --git a/designs/examples/src/index.mjs b/designs/examples/src/index.mjs
deleted file mode 100644
index 487893757d1..00000000000
--- a/designs/examples/src/index.mjs
+++ /dev/null
@@ -1,384 +0,0 @@
-import { Design } from '@freesewing/core'
-import { pluginBundle } from '@freesewing/plugin-bundle'
-import { gorePlugin } from '@freesewing/plugin-gore'
-import { data } from '../data.mjs'
-
-// Path API
-import {
- path__curve,
- path_addclass,
- path_attr,
- path_move,
- path_line,
- path_curve,
- path_curve_,
- path_close,
- path_ops,
- path_clone,
- path_divide,
- path_edge,
- path_end,
- path_intersects,
- path_intersectsx,
- path_intersectsy,
- path_join,
- path_length,
- path_noop,
- path_offset,
- path_reverse,
- path_shiftalong,
- path_shiftfractionalong,
- path_smurve,
- path_smurve_,
- path_split,
- path_start,
- path_translate,
- path_trim,
-} from './path.mjs'
-
-// Point API
-import {
- point_addcircle,
- point_addtext,
- point_angle,
- point_attr,
- point_clone,
- point_copy,
- point_dist,
- point_dx,
- point_dy,
- point_flipx,
- point_flipy,
- point_setcircle,
- point_settext,
- point_shift,
- point_shiftfractiontowards,
- point_shifttowards,
- point_shiftoutwards,
- point_sitson,
- point_sitsroughlyon,
- point_rotate,
- point_translate,
-} from './point.mjs'
-
-// Snippet API
-import { snippet, snippet_attr, snippet_clone } from './snippet.mjs'
-
-// Utils API
-import {
- utils_linesintersect,
- utils_beamsintersect,
- utils_beamintersectsx,
- utils_beamintersectsy,
- utils_lineintersectscurve,
- utils_curvesintersect,
- utils_pointonbeam,
- utils_pointonline,
- utils_pointoncurve,
- utils_circlesintersect,
- utils_beamintersectscircle,
- utils_lineintersectscircle,
- utils_curveintersectsx,
- utils_curveintersectsy,
- utils_splitcurve,
-} from './utils.mjs'
-
-// Plugins
-import {
- plugin_banner,
- plugin_bartack,
- plugin_bartackalong,
- plugin_bartackfractionalong,
- plugin_buttons,
- plugin_cutonfold,
- plugin_dimension,
- plugin_gore,
- plugin_grainline,
- plugin_logo,
- plugin_mirror,
- plugin_notches,
- plugin_round,
- plugin_sprinkle,
- plugin_scalebox,
- plugin_title,
-} from './plugins.mjs'
-
-// Snippets
-import {
- snippet_bnotch,
- snippet_notch,
- snippet_button,
- snippet_buttonhole,
- snippet_buttonholestart,
- snippet_buttonholeend,
- snippet_snapsocket,
- snippet_snapstud,
- snippet_logo,
-} from './snippets.mjs'
-
-// Stacks
-import {
- stacks_top,
- stacks_left,
- stacks_right,
- stacks_bottom,
- stacks_leftEye,
- stacks_rightEye,
- stacks_mouth,
-} from './stacks.mjs'
-
-// Settings
-import { settings_sa } from './settings.mjs'
-
-// Docs illustrations
-import { docs_coords, docs_overview } from './docs.mjs'
-
-// Setup our new design
-const Examples = new Design({
- data,
- parts: [
- // Path API
- path__curve,
- path_addclass,
- path_attr,
- path_move,
- path_line,
- path_curve,
- path_curve_,
- path_close,
- path_ops,
- path_clone,
- path_divide,
- path_edge,
- path_end,
- path_intersects,
- path_intersectsx,
- path_intersectsy,
- path_join,
- path_length,
- path_noop,
- path_offset,
- path_reverse,
- path_shiftalong,
- path_shiftfractionalong,
- path_smurve,
- path_smurve_,
- path_split,
- path_start,
- path_translate,
- path_trim,
-
- // Point API
- point_addcircle,
- point_addtext,
- point_angle,
- point_attr,
- point_clone,
- point_copy,
- point_dist,
- point_dx,
- point_dy,
- point_flipx,
- point_flipy,
- point_setcircle,
- point_settext,
- point_shift,
- point_shiftfractiontowards,
- point_shifttowards,
- point_shiftoutwards,
- point_sitson,
- point_sitsroughlyon,
- point_rotate,
- point_translate,
-
- // Snippet API
- snippet,
- snippet_attr,
- snippet_clone,
-
- // Utils API
- utils_linesintersect,
- utils_beamsintersect,
- utils_beamintersectsx,
- utils_beamintersectsy,
- utils_lineintersectscurve,
- utils_curvesintersect,
- utils_pointonbeam,
- utils_pointonline,
- utils_pointoncurve,
- utils_circlesintersect,
- utils_beamintersectscircle,
- utils_lineintersectscircle,
- utils_curveintersectsx,
- utils_curveintersectsy,
- utils_splitcurve,
-
- // Plugins
- plugin_banner,
- plugin_bartack,
- plugin_bartackalong,
- plugin_bartackfractionalong,
- plugin_buttons,
- plugin_cutonfold,
- plugin_dimension,
- plugin_gore,
- plugin_grainline,
- plugin_logo,
- plugin_mirror,
- plugin_notches,
- plugin_round,
- plugin_sprinkle,
- plugin_scalebox,
- plugin_title,
-
- // Snippets
- snippet_bnotch,
- snippet_notch,
- snippet_button,
- snippet_buttonhole,
- snippet_buttonholestart,
- snippet_buttonholeend,
- snippet_snapsocket,
- snippet_snapstud,
- snippet_logo,
-
- // Stacks
- stacks_top,
- stacks_left,
- stacks_right,
- stacks_bottom,
- stacks_leftEye,
- stacks_rightEye,
- stacks_mouth,
-
- // Settings
- settings_sa,
-
- // Docs
- docs_coords,
- docs_overview,
- ],
- plugins: [pluginBundle, gorePlugin],
-})
-
-// Named exports
-export {
- // Path API
- path__curve,
- path_addclass,
- path_attr,
- path_move,
- path_line,
- path_curve,
- path_curve_,
- path_close,
- path_ops,
- path_clone,
- path_divide,
- path_edge,
- path_end,
- path_intersects,
- path_intersectsx,
- path_intersectsy,
- path_join,
- path_length,
- path_noop,
- path_offset,
- path_reverse,
- path_shiftalong,
- path_shiftfractionalong,
- path_smurve,
- path_smurve_,
- path_split,
- path_start,
- path_translate,
- path_trim,
-
- // Point API
- point_addcircle,
- point_addtext,
- point_angle,
- point_attr,
- point_clone,
- point_copy,
- point_dist,
- point_dx,
- point_dy,
- point_flipx,
- point_flipy,
- point_setcircle,
- point_settext,
- point_shift,
- point_shiftfractiontowards,
- point_shifttowards,
- point_shiftoutwards,
- point_sitson,
- point_sitsroughlyon,
- point_rotate,
- point_translate,
-
- // Snippet API
- snippet,
- snippet_attr,
- snippet_clone,
-
- // Utils API
- utils_linesintersect,
- utils_beamsintersect,
- utils_beamintersectsx,
- utils_beamintersectsy,
- utils_lineintersectscurve,
- utils_curvesintersect,
- utils_pointonbeam,
- utils_pointonline,
- utils_pointoncurve,
- utils_circlesintersect,
- utils_beamintersectscircle,
- utils_lineintersectscircle,
- utils_curveintersectsx,
- utils_curveintersectsy,
- utils_splitcurve,
-
- // Plugins
- plugin_banner,
- plugin_bartack,
- plugin_bartackalong,
- plugin_bartackfractionalong,
- plugin_buttons,
- plugin_cutonfold,
- plugin_dimension,
- plugin_gore,
- plugin_grainline,
- plugin_logo,
- plugin_mirror,
- plugin_notches,
- plugin_round,
- plugin_sprinkle,
- plugin_scalebox,
- plugin_title,
-
- // Snippets
- snippet_bnotch,
- snippet_notch,
- snippet_button,
- snippet_buttonhole,
- snippet_buttonholestart,
- snippet_buttonholeend,
- snippet_snapsocket,
- snippet_snapstud,
- snippet_logo,
-
- // Stacks
- stacks_top,
- stacks_left,
- stacks_right,
- stacks_bottom,
- stacks_leftEye,
- stacks_rightEye,
- stacks_mouth,
-
- // Docs
- docs_coords,
- docs_overview,
- Examples,
-}
diff --git a/designs/examples/src/path.mjs b/designs/examples/src/path.mjs
deleted file mode 100644
index ad951583e72..00000000000
--- a/designs/examples/src/path.mjs
+++ /dev/null
@@ -1,745 +0,0 @@
-import { box } from './shared.mjs'
-
-export const path__curve = {
- name: 'examples.path__curve',
- draft: ({ Point, points, Path, paths, part }) => {
- points.from = new Point(5, 20)
- points.cp2 = new Point(60, 30)
- points.to = new Point(90, 20)
-
- paths.line = new Path()
- .move(points.from)
- ._curve(points.cp2, points.to)
- .attr('data-text', 'Path._curve()')
- .attr('data-text-class', 'text-sm center fill-note')
-
- return box(part, 100, 25)
- },
-}
-
-export const path_addclass = {
- name: 'examples.path_addclass',
- draft: ({ Point, points, Path, paths, part }) => {
- points.from = new Point(5, 10)
- points.to = new Point(95, 10)
-
- paths.line = new Path()
- .move(points.from)
- .line(points.to)
- .addClass('note dashed')
-
- return box(part, 100, 20)
- },
-}
-
-export const path_attr = {
- name: 'examples.path_attr',
- draft: ({ Point, points, Path, paths, part }) => {
- points.B = new Point(10, 50)
- points.BCp2 = new Point(40, 10)
- points.C = new Point(90, 30)
- points.CCp1 = new Point(50, 90)
-
- paths.example = new Path()
- .move(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
- .attr('class', 'canvas')
- .attr('data-text', 'supportFreesewingBecomeAPatron')
- .attr('data-text-class', 'text-xs center')
-
- return part
- },
-}
-
-export const path_clone = {
- name: 'examples.path_clone',
- draft: ({ Point, points, Path, paths, part }) => {
- points.A = new Point(45, 60)
- points.B = new Point(10, 30)
- points.BCp2 = new Point(40, 20)
- points.C = new Point(90, 30)
- points.CCp1 = new Point(50, -30)
-
- paths.example = new Path()
- .move(points.A)
- .line(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
-
- paths.clone = paths.example
- .clone()
- .attr('class', 'note lashed stroke-l')
- .attr('style', 'stroke-opacity: 0.5')
-
- return part
- },
-}
-
-export const path_close = {
- name: 'examples.path_close',
- draft: ({ Point, points, Path, paths, part }) => {
- points.from = new Point(10, 20)
- points.cp2 = new Point(60, 30)
- points.to = new Point(90, 20)
-
- paths.line = new Path()
- .move(points.from)
- ._curve(points.cp2, points.to)
- .close()
- .reverse() // To keep text from being upside-down
- .attr('data-text', 'Path._close()')
- .attr('data-text-class', 'text-sm right fill-note')
-
- return box(part, 100, 25)
- },
-}
-
-export const path_curve = {
- name: 'examples.path_curve',
- draft: ({ Point, points, Path, paths, part }) => {
- points.from = new Point(10, 20)
- points.cp1 = new Point(40, 0)
- points.cp2 = new Point(60, 30)
- points.to = new Point(90, 20)
-
- paths.line = new Path()
- .move(points.from)
- .curve(points.cp1, points.cp2, points.to)
- .attr('data-text', 'Path.curve()')
- .attr('data-text-class', 'text-sm center fill-note')
-
- return box(part, 100, 25)
- },
-}
-
-export const path_curve_ = {
- name: 'examples.path_curve_',
- draft: ({ Point, points, Path, paths, part }) => {
- points.from = new Point(10, 20)
- points.cp1 = new Point(40, 0)
- points.to = new Point(90, 20)
-
- paths.line = new Path()
- .move(points.from)
- .curve_(points.cp1, points.to)
- .attr('data-text', 'Path.curve_()')
- .attr('data-text-class', 'text-sm center fill-note')
-
- return box(part, 100, 25)
- },
-}
-
-export const path_divide = {
- name: 'examples.path_divide',
- draft: ({ Point, points, Path, paths, part }) => {
- points.A = new Point(55, 40)
- points.B = new Point(10, 70)
- points.BCp2 = new Point(40, 20)
- points.C = new Point(90, 60)
- points.CCp1 = new Point(50, -30)
- points.D = new Point(50, 80)
- points.DCp1 = new Point(140, 50)
-
- paths.example = new Path()
- .move(points.A)
- .line(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
- .curve(points.DCp1, points.DCp1, points.D)
- .close()
-
- let style = 'stroke-width: 4; stroke-opacity: 0.5;'
- let i = 0
- for (let p of paths.example.divide()) {
- i++
- paths[i] = p.attr('style', style).attr('style', `stroke: hsl(${i * 70}, 100%, 50%)`)
- }
-
- return part
- },
-}
-
-export const path_edge = {
- name: 'examples.path_edge',
- draft: ({ Point, points, Path, paths, Snippet, snippets, part }) => {
- points.A = new Point(45, 60)
- points.B = new Point(10, 30)
- points.BCp2 = new Point(40, 20)
- points.C = new Point(90, 30)
- points.CCp1 = new Point(50, -30)
- points.D = new Point(-60, 90)
- points.E = new Point(90, 190)
-
- paths.demo = new Path()
- .move(points.A)
- .line(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
- .curve(points.E, points.D, points.A)
- .close()
-
- for (let i of [
- 'topLeft',
- 'topRight',
- 'bottomLeft',
- 'bottomRight',
- 'top',
- 'left',
- 'bottom',
- 'right',
- ])
- snippets[i] = new Snippet('notch', paths.demo.edge(i))
-
- return part
- },
-}
-
-export const path_end = {
- name: 'examples.path_end',
- draft: ({ Point, points, Path, paths, Snippet, snippets, part }) => {
- points.A = new Point(45, 60)
- points.B = new Point(10, 30)
- points.BCp2 = new Point(40, 20)
- points.C = new Point(90, 30)
- points.CCp1 = new Point(50, -30)
-
- paths.demo = new Path().move(points.A).line(points.B).curve(points.BCp2, points.CCp1, points.C)
-
- snippets.end = new Snippet('notch', paths.demo.end())
-
- return part
- },
-}
-
-export const path_intersects = {
- name: 'examples.path_intersects',
- draft: ({ Point, points, Path, paths, Snippet, snippets, part }) => {
- points.A = new Point(45, 60)
- points.B = new Point(10, 30)
- points.BCp2 = new Point(40, 20)
- points.C = new Point(90, 30)
- points.CCp1 = new Point(50, -30)
- points.D = new Point(50, 130)
- points.DCp1 = new Point(150, 30)
-
- points._A = new Point(55, 40)
- points._B = new Point(0, 55)
- points._BCp2 = new Point(40, -20)
- points._C = new Point(90, 40)
- points._CCp1 = new Point(50, -30)
- points._D = new Point(40, 120)
- points._DCp1 = new Point(180, 40)
-
- paths.demo1 = new Path()
- .move(points.A)
- .line(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
- .curve(points.DCp1, points.DCp1, points.D)
- paths.demo2 = new Path()
- .move(points._A)
- .line(points._B)
- .curve(points._BCp2, points._CCp1, points._C)
- .curve(points._DCp1, points._DCp1, points._D)
-
- for (let p of paths.demo1.intersects(paths.demo2)) {
- snippets[part.getId()] = new Snippet('notch', p)
- }
-
- return part
- },
-}
-
-export const path_intersectsx = {
- name: 'examples.path_intersectsx',
- draft: ({ Point, points, Path, paths, Snippet, snippets, part }) => {
- points.A = new Point(95, 50)
- points.B = new Point(10, 30)
- points.BCp2 = new Point(40, 20)
- points.C = new Point(90, 30)
- points.CCp1 = new Point(50, -30)
- points.D = new Point(50, 130)
- points.DCp1 = new Point(150, 30)
-
- points.top = new Point(60, -10)
- points.bot = new Point(60, 140)
-
- paths.line = new Path().move(points.top).line(points.bot).attr('class', 'lining dashed')
-
- paths.demo = new Path()
- .move(points.A)
- .line(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
- .curve(points.DCp1, points.DCp1, points.D)
-
- for (let p of paths.demo.intersectsX(60)) {
- snippets[part.getId()] = new Snippet('notch', p)
- }
-
- return part
- },
-}
-
-export const path_intersectsy = {
- name: 'examples.path_intersectsy',
- draft: ({ Point, points, Path, paths, Snippet, snippets, part }) => {
- points.A = new Point(55, 40)
- points.B = new Point(10, 70)
- points.BCp2 = new Point(40, 20)
- points.C = new Point(90, 60)
- points.CCp1 = new Point(50, -30)
- points.D = new Point(50, 80)
- points.DCp1 = new Point(140, 50)
-
- points.top = new Point(10, 58)
- points.bot = new Point(130, 58)
-
- paths.line = new Path().move(points.top).line(points.bot).attr('class', 'lining dashed')
-
- paths.demo = new Path()
- .move(points.A)
- .line(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
- .curve(points.DCp1, points.DCp1, points.D)
- for (let p of paths.demo.intersectsY(58)) {
- snippets[part.getId()] = new Snippet('notch', p)
- }
-
- return part
- },
-}
-
-export const path_join = {
- name: 'examples.path_join',
- draft: ({ Point, points, Path, paths, part }) => {
- points.A = new Point(45, 60)
- points.B = new Point(10, 30)
- points.BCp2 = new Point(40, 20)
- points.C = new Point(90, 30)
- points.CCp1 = new Point(50, -30)
-
- paths.path1 = new Path().move(points.A).line(points.B).attr('class', 'various')
-
- paths.path2 = new Path()
- .move(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
- .attr('class', 'canvas')
-
- paths.joint = paths.path1
- .join(paths.path2)
- .attr('class', 'note lashed stroke-l')
- .attr('style', 'stroke-opacity: 0.5')
-
- return part
- },
-}
-
-export const path_length = {
- name: 'examples.path_length',
- draft: ({ Point, points, Path, paths, macro, part }) => {
- points.A = new Point(45, 60)
- points.B = new Point(10, 30)
- points.BCp2 = new Point(40, 20)
- points.C = new Point(90, 30)
- points.CCp1 = new Point(50, -30)
-
- paths.example = new Path()
- .move(points.A)
- .line(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
-
- macro('pd', {
- path: paths.example,
- d: -20,
- })
-
- macro('pd', {
- path: new Path().move(points.B).line(points.A),
- d: 10,
- })
-
- macro('pd', {
- path: new Path().move(points.B).curve(points.BCp2, points.CCp1, points.C),
- d: -10,
- })
-
- return part
- },
-}
-
-export const path_line = {
- name: 'examples.path_line',
- draft: ({ Point, points, Path, paths, part }) => {
- points.from = new Point(10, 10)
- points.to = new Point(90, 10)
-
- paths.line = new Path()
- .move(points.from)
- .line(points.to)
- .attr('data-text', 'Path.line()')
- .attr('data-text-class', 'text-sm center fill-note')
-
- return box(part, 100, 15)
- },
-}
-
-export const path_move = {
- name: 'examples.path_move',
- draft: ({ Point, points, Path, paths, part }) => {
- points.to = new Point(50, 10)
- .attr('data-text', 'Path.move()')
- .attr('data-text-class', 'fill-note center')
-
- paths.noline = new Path().move(points.to)
-
- return box(part, 100, 15)
- },
-}
-
-export const path_noop = {
- name: 'examples.path_noop',
- draft: ({ Point, points, Path, paths, part }) => {
- points.left = new Point(10, 10)
- points.dartLeft = new Point(40, 10)
- points.dartTip = new Point(50, 50)
- points.dartRight = new Point(60, 10)
- points.right = new Point(90, 10)
-
- paths.without = new Path()
- .move(points.left)
- .line(points.dartLeft)
- .noop('dart')
- .line(points.right)
-
- paths.withDart = paths.without
- .insop('dart', new Path().line(points.dartTip).line(points.dartRight))
- .attr('style', 'stroke-width: 2px; stroke-opacity: 0.5; stroke: orange;')
-
- return part
- },
-}
-
-export const path_offset = {
- name: 'examples.path_offset',
- draft: ({ Point, points, Path, paths, part }) => {
- points.A = new Point(45, 60)
- points.B = new Point(10, 30)
- points.BCp2 = new Point(40, 20)
- points.C = new Point(90, 30)
- points.CCp1 = new Point(50, -30)
-
- paths.example = new Path()
- .move(points.A)
- .line(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
- .line(points.A)
- .close()
-
- paths.offset = paths.example.offset(-10).attr('class', 'interfacing')
-
- paths.lineOffset = new Path().move(points.A).line(points.B).offset(-5).attr('class', 'various')
-
- paths.curveOffset = new Path()
- .move(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
- .offset(-5)
- .attr('class', 'canvas')
-
- return part
- },
-}
-
-export const path_ops = {
- name: 'examples.path_ops',
- draft: ({ Point, points, Path, paths, options, part }) => {
- const textClasses = (label) =>
- options.focus === label ? 'center text-xs fill-note' : 'center text-xs'
-
- points.A = new Point(10, 10)
- .attr('data-text', 'Path.move()')
- .attr('data-text-class', textClasses('move'))
- points.B = new Point(70, 30)
- points.BCp2 = new Point(40, 10)
- points.C = new Point(90, -50)
- points.CCp1 = new Point(125, -30)
- points.D = new Point(20, -50)
- points.DCp = new Point(40, 0)
- points.E = new Point(-20, -20)
- points.ECp = new Point(-20, -50)
-
- paths.line = new Path()
- .move(points.A)
- .line(points.B)
- .attr('data-text', 'Path.line()')
- .attr('data-text-class', textClasses('line'))
-
- paths.curve = new Path()
- .move(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
- .attr('data-text', 'Path.curve()')
- .attr('data-text-class', textClasses('curve'))
-
- paths._curve = new Path()
- .move(points.C)
- ._curve(points.DCp, points.D)
- .attr('data-text', 'Path._curve()')
- .attr('data-text-class', textClasses('_curve'))
-
- paths.curve_ = new Path()
- .move(points.D)
- .curve_(points.ECp, points.E)
- .attr('data-text', 'Path.curve_()')
- .attr('data-text-class', textClasses('curve_'))
-
- paths.close = new Path()
- .move(points.E)
- .line(points.A)
- .attr('data-text', 'Path.close()')
- .attr('data-text-class', textClasses('close'))
-
- paths.example = paths.line.join(paths.curve).join(paths._curve).join(paths.curve_).close()
-
- return part
- },
-}
-
-export const path_reverse = {
- name: 'examples.path_reverse',
- draft: ({ Point, points, Path, paths, part }) => {
- points.B = new Point(10, 30)
- points.BCp2 = new Point(40, 20)
- points.C = new Point(90, 30)
- points.CCp1 = new Point(50, -30)
-
- paths.example = new Path()
- .move(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
- .attr('data-text', 'freesewingIsMadeByJoostDeCockAndContributors')
- .attr('data-text-class', 'text-xs fill-note')
-
- paths.reverse = paths.example
- .reverse()
- .attr('data-text', 'freesewingIsMadeByJoostDeCockAndContributors')
- .attr('data-text-class', 'text-xs fill-lining')
-
- return part
- },
-}
-
-export const path_shiftalong = {
- name: 'examples.path_shiftalong',
- draft: ({ Point, points, Path, paths, Snippet, snippets, part }) => {
- points.A = new Point(45, 60)
- points.B = new Point(10, 30)
- points.BCp2 = new Point(40, 20)
- points.C = new Point(90, 30)
- points.CCp1 = new Point(50, -30)
-
- paths.example = new Path()
- .move(points.A)
- .line(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
-
- points.x1 = paths.example
- .shiftAlong(20)
- .attr('data-text', '2cm')
- .attr('data-text-class', 'center fill-note')
- .attr('data-text-lineheight', 6)
- points.x2 = paths.example
- .shiftAlong(90)
- .attr('data-text', '9cm')
- .attr('data-text-class', 'center fill-note')
- .attr('data-text-lineheight', 6)
-
- snippets.x1 = new Snippet('notch', points.x1)
- snippets.x2 = new Snippet('notch', points.x2)
-
- return part
- },
-}
-
-export const path_shiftfractionalong = {
- name: 'examples.path_shiftfractionalong',
- draft: ({ Point, points, Path, paths, Snippet, snippets, part }) => {
- points.A = new Point(45, 60)
- points.B = new Point(10, 30)
- points.BCp2 = new Point(40, 20)
- points.C = new Point(90, 30)
- points.CCp1 = new Point(50, -30)
-
- paths.example = new Path()
- .move(points.A)
- .line(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
-
- points.x1 = paths.example
- .shiftFractionAlong(0.2)
- .attr('data-text', '20%')
- .attr('data-text-class', 'center fill-note')
- .attr('data-text-lineheight', 6)
- points.x2 = paths.example
- .shiftFractionAlong(0.9)
- .attr('data-text', '90%')
- .attr('data-text-class', 'center fill-note')
- .attr('data-text-lineheight', 6)
-
- snippets.xl = new Snippet('notch', points.x1)
- snippets.x2 = new Snippet('notch', points.x2)
-
- return part
- },
-}
-
-export const path_smurve = {
- name: 'examples.path_smurve',
- draft: ({ Point, points, Path, paths, part }) => {
- points.from = new Point(10, 20)
- points.cp1 = new Point(40, 10)
- points.cp2 = new Point(60, 30)
- points.to = new Point(90, 20)
- points.scp2 = new Point(140, 30)
- points.sto = new Point(170, 20)
-
- paths.line = new Path()
- .move(points.from)
- .curve(points.cp1, points.cp2, points.to)
- .smurve(points.scp2, points.sto)
- .attr('data-text', 'Path.smurve()')
- .attr('data-text-class', 'text-sm center fill-note')
-
- return box(part, 180, 40)
- },
-}
-
-export const path_smurve_ = {
- name: 'examples.path_smurve_',
- draft: ({ Point, points, Path, paths, part }) => {
- points.from = new Point(10, 20)
- points.cp1 = new Point(40, 10)
- points.cp2 = new Point(60, 30)
- points.to = new Point(90, 20)
- points.sto = new Point(170, 20)
-
- paths.line = new Path()
- .move(points.from)
- .curve(points.cp1, points.cp2, points.to)
- .smurve_(points.sto)
- .attr('data-text', 'Path.smurve_()')
- .attr('data-text-class', 'text-sm center fill-note')
-
- return box(part, 180, 40)
- },
-}
-
-export const path_split = {
- name: 'examples.path_split',
- draft: ({ Point, points, Path, paths, Snippet, snippets, part }) => {
- points.A = new Point(45, 60)
- points.B = new Point(10, 30)
- points.BCp2 = new Point(40, 20)
- points.C = new Point(90, 30)
- points.CCp1 = new Point(50, -30)
- points.D = new Point(50, 130)
- points.DCp1 = new Point(150, 30)
-
- paths.demo = new Path()
- .move(points.D)
- .curve(points.DCp1, points.DCp1, points.C)
- .curve(points.CCp1, points.BCp2, points.B)
- .line(points.A)
-
- points.split = paths.demo.shiftFractionAlong(0.75)
- snippets.x = new Snippet('x', points.split)
-
- let style = 'stroke-width: 3; stroke-opacity: 0.5;'
- let halves = paths.demo.split(points.split)
- for (let i in halves) {
- paths[i] = halves[i].attr('style', style).attr('style', `stroke: hsl(${i * 70}, 100%, 50%)`)
- }
-
- return part
- },
-}
-
-export const path_start = {
- name: 'examples.path_start',
- draft: ({ Point, points, Path, paths, Snippet, snippets, part }) => {
- points.A = new Point(45, 60)
- points.B = new Point(10, 30)
- points.BCp2 = new Point(40, 20)
- points.C = new Point(90, 30)
- points.CCp1 = new Point(50, -30)
-
- paths.example = new Path()
- .move(points.A)
- .line(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
-
- snippets.start = new Snippet('notch', paths.example.start())
- return part
- },
-}
-
-export const path_translate = {
- name: 'examples.path_translate',
- draft: ({ Point, points, Path, paths, macro, part }) => {
- points.A = new Point(45, 60)
- points.B = new Point(10, 30)
- points.BCp2 = new Point(40, 20)
- points.C = new Point(90, 30)
- points.CCp1 = new Point(50, -30)
-
- paths.A = new Path().move(points.A).line(points.B).curve(points.BCp2, points.CCp1, points.C)
-
- paths.B = paths.A.translate(60, 30)
-
- points.step1 = points.B.shift(0, 60)
- points.step2 = points.step1.shift(-90, 30)
- macro('ld', {
- from: points.B,
- to: points.step1,
- noStartMarker: true,
- })
- macro('ld', {
- from: points.step1,
- to: points.step2,
- noStartMarker: true,
- })
-
- return part
- },
-}
-
-export const path_trim = {
- name: 'examples.path_trim',
- draft: ({ Point, points, Path, paths, part }) => {
- points.center = new Point(0, 0)
- points.base = new Point(0, 10)
- points.tip = new Point(0, 50)
- points.tipCpRight = new Point(30, 50)
- points.tipCpLeft = new Point(-30, 50)
- paths.example = new Path().move(points.base)
- for (let i = 0; i < 4; i++) {
- points['base' + i] = points.base.rotate(60 * i, points.center)
- points['tip' + i] = points.tip.rotate(60 * i, points.center)
- points['tipCpRight' + i] = points.tipCpRight.rotate(60 * i, points.center)
- points['tipCpLeft' + i] = points.tipCpLeft.rotate(60 * i, points.center)
- if (i < 2) {
- paths.example
- .line(points['base' + i])
- .curve(points['base' + i], points['tipCpLeft' + i], points['tip' + i])
- .curve(points['tipCpRight' + i], points['base' + i], points['base' + i])
- } else {
- paths.example
- .line(points['base' + i])
- .line(points['tip' + i])
- .line(points['tipCpRight' + i])
- .line(points['base' + i])
- }
- }
-
- paths.offset = paths.example.offset(10).attr('class', 'lining dotted stroke-sm')
-
- paths.trimmed = paths.offset
- .trim()
- .attr('class', 'various stroke-xl')
- .attr('style', 'stroke-opacity: 0.5;')
- return part
- },
-}
diff --git a/designs/examples/src/plugins.mjs b/designs/examples/src/plugins.mjs
deleted file mode 100644
index e8f436e8f94..00000000000
--- a/designs/examples/src/plugins.mjs
+++ /dev/null
@@ -1,342 +0,0 @@
-import { box } from './shared.mjs'
-
-export const plugin_banner = {
- name: 'examples.plugin_banner',
- draft: ({ points, Point, paths, Path, macro, part }) => {
- points.from = new Point(0, 0)
- points.to = new Point(320, 0)
-
- paths.banner = new Path().move(points.from).line(points.to)
-
- macro('banner', {
- path: paths.banner,
- text: 'banner plugin',
- })
-
- // Prevent clipping of text
- paths.box = new Path().move(new Point(0, -20)).line(new Point(0, 20)).attr('class', 'hidden')
-
- return part
- },
-}
-
-export const plugin_bartack = {
- name: 'examples.plugin_bartack',
- draft: ({ Point, points, macro, part }) => {
- points.a = new Point(15, 15)
-
- macro('bartack', {
- anchor: points.a,
- angle: 30,
- length: 15,
- })
-
- return box(part, 60, 30)
- },
-}
-
-export const plugin_bartackalong = {
- name: 'examples.plugin_bartackalong',
- draft: ({ Point, Path, points, paths, macro, part }) => {
- points.a = new Point(15, 15)
- points.b = new Point(20, 20)
- points.c = new Point(30, 20)
- points.d = new Point(35, 15)
- points.e = new Point(20, 10)
- points.f = new Point(30, 10)
-
- paths.a = new Path().move(points.a).curve(points.b, points.c, points.d).hide()
-
- macro('bartackAlong', {
- path: paths.a,
- })
-
- macro('sprinkle', {
- snippet: 'notch',
- on: ['e', 'f'],
- })
-
- return box(part, 60, 30)
- },
-}
-
-export const plugin_bartackfractionalong = {
- name: 'examples.plugin_bartackfractionalong',
- draft: ({ Point, Path, points, paths, macro, part }) => {
- points.a = new Point(15, 15)
- points.b = new Point(20, 20)
- points.c = new Point(30, 20)
- points.d = new Point(35, 15)
- points.e = new Point(20, 10)
- points.f = new Point(30, 10)
-
- paths.a = new Path().move(points.a).curve(points.b, points.c, points.d).hide()
-
- macro('bartackFractionAlong', {
- path: paths.a,
- start: 0.2,
- end: 0.8,
- })
-
- macro('sprinkle', {
- snippet: 'notch',
- on: ['e', 'f'],
- })
-
- return box(part, 60, 30)
- },
-}
-
-export const plugin_buttons = {
- name: 'examples.plugin_buttons',
- draft: ({ Point, snippets, Snippet, part }) => {
- snippets.button = new Snippet('button', new Point(20, 10))
- snippets.buttonhole = new Snippet('buttonhole', new Point(40, 10))
- snippets.buttonholeStart = new Snippet('buttonhole-start', new Point(60, 10))
- snippets.buttonholeEnd = new Snippet('buttonhole-end', new Point(80, 10))
- snippets.snapMale = new Snippet('snap-stud', new Point(100, 10))
- snippets.snapFemale = new Snippet('snap-socket', new Point(120, 10))
-
- return box(part, 140, 20)
- },
-}
-
-export const plugin_cutonfold = {
- name: 'examples.plugin_cutonfold',
- draft: ({ Point, points, Path, paths, macro, part }) => {
- points.topLeft = new Point(0, 0)
- points.topRight = new Point(150, 0)
- points.bottomRight = new Point(150, 30)
- points.bottomLeft = new Point(0, 30)
-
- paths.box = new Path()
- .move(points.topLeft)
- .line(points.topRight)
- .line(points.bottomRight)
- .line(points.bottomLeft)
- .close()
-
- macro('cutonfold', {
- from: points.bottomLeft,
- to: points.bottomRight,
- grainline: true,
- })
-
- return part
- },
-}
-
-export const plugin_dimension = {
- name: 'examples.plugin_dimension',
- draft: ({ Point, points, Path, paths, macro, part }) => {
- points.A = new Point(0, 0)
- points.B = new Point(0, 100)
- points.C = new Point(50, 100)
- points.D = new Point(100, 50)
- points.DCp1 = new Point(100, 0)
-
- paths.box = new Path()
- .move(points.A)
- .line(points.B)
- .line(points.C)
- .line(points.D)
- .curve(points.DCp1, points.A, points.A)
- .close()
-
- macro('vd', {
- from: points.A,
- to: points.B,
- x: points.A.x - 15,
- })
-
- macro('hd', {
- from: points.B,
- to: points.C,
- y: points.B.y + 15,
- })
-
- macro('ld', {
- from: points.C,
- to: points.D,
- d: -15,
- })
-
- macro('ld', {
- from: points.C,
- to: points.D,
- d: -30,
- text: 'Custom text',
- })
-
- macro('pd', {
- path: new Path().move(points.A).curve(points.A, points.DCp1, points.D),
- d: -15,
- })
-
- return part
- },
-}
-
-export const plugin_gore = {
- name: 'examples.plugin_gore',
- draft: ({ Point, points, macro, part }) => {
- points.anchor = new Point(0, 0)
-
- macro('gore', {
- from: points.anchor,
- radius: 60,
- gores: 5,
- extraLength: 20,
- })
-
- return part
- },
-}
-
-export const plugin_grainline = {
- name: 'examples.plugin_grainline',
- draft: ({ Point, points, macro, part }) => {
- points.grainlineFrom = new Point(10, 10)
- points.grainlineTo = new Point(100, 10)
-
- macro('grainline', {
- from: points.grainlineFrom,
- to: points.grainlineTo,
- })
-
- return box(part, 110, 15)
- },
-}
-
-export const plugin_logo = {
- name: 'examples.plugin_logo',
- draft: ({ points, Point, snippets, Snippet, part }) => {
- points.anchor = new Point(50, 25)
-
- snippets.logo = new Snippet('logo', points.anchor).attr('data-scale', 0.666)
-
- return box(part, 100, 35)
- },
-}
-
-export const plugin_mirror = {
- name: 'examples.plugin_mirror',
- draft: ({ Point, Path, points, paths, macro, part }) => {
- points.a = new Point(5, 5)
- points.b = new Point(45, 30)
- points.c = new Point(5, 30)
- points.d = new Point(45, 5)
- points.mid = new Point(25, 15)
-
- paths.a = new Path().move(points.a).curve(points.b, points.c, points.d)
-
- macro('mirror', {
- mirror: [points.b, points.d],
- points: [points.mid],
- paths: [paths.a],
- })
-
- macro('sprinkle', {
- snippet: 'notch',
- on: ['mid', 'mirroredMid'],
- })
-
- return box(part, 100, 40)
- },
-}
-
-export const plugin_notches = {
- name: 'examples.plugin_notches',
- draft: ({ Point, snippets, Snippet, part }) => {
- snippets.notch = new Snippet('notch', new Point(60, 10))
- snippets.bnotch = new Snippet('bnotch', new Point(80, 10))
-
- return box(part, 140, 20)
- },
-}
-
-export const plugin_round = {
- name: 'examples.plugin_round',
- draft: ({ Point, points, Path, paths, macro, part }) => {
- points.topLeft = new Point(0, 0)
- points.bottomLeft = new Point(0, 30)
- points.topRight = new Point(100, 0)
- points.bottomRight = new Point(100, 30)
-
- paths.demo = new Path()
- .move(points.topLeft)
- .line(points.bottomLeft)
- .line(points.bottomRight)
- .line(points.topRight)
- .close()
- .attr('class', 'note dashed')
-
- macro('round', {
- from: points.topLeft,
- to: points.bottomRight,
- via: points.bottomLeft,
- radius: 10,
- prefix: 'bl',
- })
- macro('round', {
- from: points.bottomRight,
- to: points.topLeft,
- via: points.topRight,
- radius: 20,
- prefix: 'tr',
- })
-
- return part
- },
-}
-
-export const plugin_scalebox = {
- name: 'examples.plugin_scalebox',
- draft: ({ Point, points, macro, part }) => {
- points.anchor1 = new Point(0, 0)
- points.anchor2 = new Point(70, 0)
-
- macro('scalebox', { at: points.anchor1 })
- macro('miniscale', { at: points.anchor2 })
-
- return part
- },
-}
-
-export const plugin_sprinkle = {
- name: 'examples.plugin_sprinkle',
- draft: ({ Point, points, macro, part }) => {
- points.a = new Point(10, 10)
- points.b = new Point(20, 15)
- points.c = new Point(30, 10)
- points.d = new Point(40, 15)
- points.e = new Point(50, 10)
- points.f = new Point(60, 15)
- points.g = new Point(70, 10)
- points.h = new Point(80, 15)
- points.i = new Point(90, 10)
-
- macro('sprinkle', {
- snippet: 'button',
- on: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'],
- })
-
- return box(part, 100, 25)
- },
-}
-
-export const plugin_title = {
- name: 'examples.plugin_title',
- draft: ({ Point, points, macro, part }) => {
- points.title = new Point(90, 45)
-
- macro('title', {
- at: points.title,
- nr: 4,
- title: 'sleeve',
- prefix: 'test',
- })
-
- return box(part, 200, 70)
- },
-}
diff --git a/designs/examples/src/point.mjs b/designs/examples/src/point.mjs
deleted file mode 100644
index ef299c4d345..00000000000
--- a/designs/examples/src/point.mjs
+++ /dev/null
@@ -1,457 +0,0 @@
-import { box } from './shared.mjs'
-
-export const point_addcircle = {
- name: 'examples.point_addcircle',
- draft: ({ Point, points, part }) => {
- points.a = new Point(30, 10).addCircle(3, 'lining dashed').addCircle(7, 'mark dashed')
-
- points.b = new Point(50, 10)
- .addCircle(1, 'interfacing')
- .addCircle(3, 'fabric')
- .addCircle(5, 'lining')
- .addCircle(7, 'mark')
- .addCircle(9, 'note')
-
- points.c = new Point(70, 10).addCircle(3, 'interfacing').addCircle(7, 'mark lashed')
- return box(part, 100, 20)
- },
-}
-
-export const point_addtext = {
- name: 'examples.point_addtext',
- draft: ({ Point, points, part }) => {
- points.anchor = new Point(100, 25)
- .addText('supportFreesewingBecomeAPatron', 'center')
- .addText('please?')
-
- return box(part, 200, 50)
- },
-}
-
-export const point_angle = {
- name: 'examples.point_angle',
- draft: ({ Point, points, Path, paths, part }) => {
- points.sun = new Point(10, 5)
- points.moon = points.sun.shift(-15, 70)
- points.text = points.sun
- .shiftFractionTowards(points.moon, 0.8)
- .attr('data-text', points.sun.angle(points.moon) + '°')
- .attr('data-text-class', 'text-sm fill-note center')
-
- paths.line = new Path().move(points.sun).line(points.moon).attr('class', 'dashed')
-
- return part
- },
-}
-
-export const point_attr = {
- name: 'examples.point_attr',
- draft: ({ Point, points, part }) => {
- points.anchor = new Point(100, 25)
- .attr('data-text', 'supportFreesewingBecomeAPatron')
- .attr('data-text-class', 'center')
-
- return box(part, 200, 50)
- },
-}
-
-export const point_clone = {
- name: 'examples.point_clone',
- draft: ({ Point, points, Snippet, snippets, part }) => {
- points.A = new Point(25, 25)
- .attr('data-text', 'Point A')
- .attr('data-text-class', 'text-xl')
- .attr('data-text-fill-opacity', '0.5')
- points.B = points.A.clone().attr('data-text', 'Point B')
-
- snippets.x = new Snippet('notch', points.A)
-
- return box(part)
- },
-}
-
-export const point_copy = {
- name: 'examples.point_copy',
- draft: ({ Point, points, Snippet, snippets, part }) => {
- points.A = new Point(50, 25).attr('data-text', 'Point A').attr('data-text-class', 'text-xl')
- points.B = points.A.copy().attr('data-text', 'Point B')
-
- snippets.x = new Snippet('notch', points.A)
-
- return box(part)
- },
-}
-
-export const point_dist = {
- name: 'examples.point_dist',
- draft: ({ Point, points, Path, paths, part }) => {
- points.from = new Point(10, 10)
- points.to = new Point(80, 70)
-
- points.text = points.from
- .shiftFractionTowards(points.to, 0.6)
- .attr('data-text', points.from.dist(points.to) + 'mm')
- .attr('data-text-class', 'text-sm fill-note center')
-
- paths.line = new Path().move(points.from).line(points.to).attr('class', 'dashed')
-
- return part
- },
-}
-
-export const point_dx = {
- name: 'examples.point_dx',
- draft: ({ Point, points, Path, paths, part }) => {
- points.from = new Point(10, 10)
- points.to = new Point(80, 70)
-
- paths.line = new Path().move(points.from).line(points.to).attr('class', 'dashed')
-
- points.totop = points.from.shift(0, points.from.dx(points.to))
-
- points.text_dx = points.from
- .shiftFractionTowards(points.totop, 0.6)
- .shiftFractionTowards(points.to, 0.1)
- .attr('data-text', points.from.dx(points.to) + 'mm')
- .attr('data-text-class', 'text-sm fill-note center')
-
- paths.line_dx = new Path().move(points.from).line(points.totop).attr('class', 'dashed')
-
- paths.line_dy = new Path().move(points.to).line(points.totop).attr('class', 'dashed')
-
- return part
- },
-}
-
-export const point_dy = {
- name: 'examples.point_dy',
- draft: ({ Point, points, Path, paths, part }) => {
- points.from = new Point(10, 10)
- points.to = new Point(80, 70)
-
- paths.line = new Path().move(points.from).line(points.to).attr('class', 'dashed')
-
- points.totop = points.from.shift(0, points.from.dx(points.to))
-
- paths.line_dx = new Path().move(points.from).line(points.totop).attr('class', 'dashed')
-
- points.text_dy = points.totop
- .shiftFractionTowards(points.to, 0.4)
- .attr('data-text', points.from.dy(points.to) + 'mm')
- .attr('data-text-class', 'text-sm fill-note right')
-
- paths.line_dy = new Path().move(points.to).line(points.totop).attr('class', 'dashed')
-
- return part
- },
-}
-
-export const point_flipx = {
- name: 'examples.point_flipy',
- draft: ({ Point, points, Path, paths, part }) => {
- points.top = new Point(50, 10)
- points.out1 = new Point(70, 30)
- points.in1 = new Point(55, 35)
- points.out2 = new Point(75, 50)
- points.in2 = new Point(60, 55)
- points.out3 = new Point(80, 70)
- points.in3 = new Point(55, 70)
- points.trunkOut = new Point(55, 80)
- points.trunkIn = new Point(50, 80)
-
- points._out1 = points.out1.flipX(points.top)
- points._in1 = points.in1.flipX(points.top)
- points._out2 = points.out2.flipX(points.top)
- points._in2 = points.in2.flipX(points.top)
- points._out3 = points.out3.flipX(points.top)
- points._in3 = points.in3.flipX(points.top)
- points._trunkOut = points.trunkOut.flipX(points.top)
-
- points.bottom = new Point(50, 80)
-
- paths.tree = new Path()
- .move(points.top)
- .line(points.out1)
- .line(points.in1)
- .line(points.out2)
- .line(points.in2)
- .line(points.out3)
- .line(points.in3)
- .line(points.trunkOut)
- .line(points._trunkOut)
- .line(points._in3)
- .line(points._out3)
- .line(points._in2)
- .line(points._out2)
- .line(points._in1)
- .line(points._out1)
- .close()
-
- paths.mirror = new Path().move(points.top).line(points.bottom).attr('class', 'note dashed')
-
- return part
- },
-}
-
-export const point_flipy = {
- name: 'examples.point_flipy',
- draft: ({ Point, points, Path, paths, part }) => {
- points.start = new Point(0, 50)
- points.churchTowerWallLeft = new Point(10, 50)
- points.churchTowerRoofLeft = new Point(10, 30)
- points.churchTowerTop = new Point(15, 10)
- points.churchTowerRoofRight = new Point(20, 30)
- points.churchRoofRight = new Point(50, 30)
- points.churchWallRight = new Point(50, 50)
- points.houseWallLeft = new Point(65, 50)
- points.houseRoofLeft = new Point(65, 35)
- points.houseRoofTop = new Point(75, 25)
- points.houseRoofRight = new Point(85, 35)
- points.houseWallRight = new Point(85, 50)
- points.end = new Point(95, 50)
-
- points.mirror = new Point(0, 60)
- points.mirrorLineEnd = new Point(95, 60)
-
- points._start = points.start.flipY(points.mirror)
- points._churchTowerWallLeft = points.churchTowerWallLeft.flipY(points.mirror)
- points._churchTowerRoofLeft = points.churchTowerRoofLeft.flipY(points.mirror)
- points._churchTowerTop = points.churchTowerTop.flipY(points.mirror)
- points._churchTowerRoofRight = points.churchTowerRoofRight.flipY(points.mirror)
- points._churchRoofRight = points.churchRoofRight.flipY(points.mirror)
- points._churchWallRight = points.churchWallRight.flipY(points.mirror)
- points._houseWallLeft = points.houseWallLeft.flipY(points.mirror)
- points._houseRoofLeft = points.houseRoofLeft.flipY(points.mirror)
- points._houseRoofTop = points.houseRoofTop.flipY(points.mirror)
- points._houseRoofRight = points.houseRoofRight.flipY(points.mirror)
- points._houseWallRight = points.houseWallRight.flipY(points.mirror)
- points._end = points.end.flipY(points.mirror)
-
- paths.skylineTop = new Path()
- .move(points.start)
- .line(points.churchTowerWallLeft)
- .line(points.churchTowerRoofLeft)
- .line(points.churchTowerTop)
- .line(points.churchTowerRoofRight)
- .line(points.churchRoofRight)
- .line(points.churchWallRight)
- .line(points.houseWallLeft)
- .line(points.houseRoofLeft)
- .line(points.houseRoofTop)
- .line(points.houseRoofRight)
- .line(points.houseWallRight)
- .line(points.end)
-
- paths.skylineBottom = new Path()
- .move(points._start)
- .line(points._churchTowerWallLeft)
- .line(points._churchTowerRoofLeft)
- .line(points._churchTowerTop)
- .line(points._churchTowerRoofRight)
- .line(points._churchRoofRight)
- .line(points._churchWallRight)
- .line(points._houseWallLeft)
- .line(points._houseRoofLeft)
- .line(points._houseRoofTop)
- .line(points._houseRoofRight)
- .line(points._houseWallRight)
- .line(points._end)
-
- paths.mirrorLine = new Path()
- .move(points.mirror)
- .line(points.mirrorLineEnd)
- .attr('class', 'note dashed')
-
- return part
- },
-}
-
-export const point_rotate = {
- name: 'examples.point_rotate',
- draft: ({ Point, points, Path, paths, part }) => {
- points.sun = new Point(40, 40)
- points.moon = new Point(70, 40)
- let step = 360 / 36
- for (let i = 1; i < 37; i++) {
- let angle = step * i
- points[`moon${i}`] = points.moon.rotate(angle, points.sun)
- paths[`moon${i}`] = new Path().move(points.sun).line(points[`moon${i}`])
- }
-
- return part
- },
-}
-
-export const point_setcircle = {
- name: 'examples.point_setcircle',
- draft: ({ Point, points, part }) => {
- points.a = new Point(30, 10).setCircle(3, 'lining dashed').setCircle(7, 'mark dashed')
-
- points.b = new Point(50, 10)
- .setCircle(1, 'interfacing')
- .setCircle(3, 'fabric')
- .setCircle(5, 'lining')
- .setCircle(7, 'mark')
- .setCircle(9, 'note')
-
- points.c = new Point(70, 10).setCircle(3, 'interfacing').setCircle(7, 'mark lashed')
- return box(part, 100, 20)
- },
-}
-
-export const point_settext = {
- name: 'examples.point_settext',
- draft: ({ Point, points, part }) => {
- points.anchor = new Point(100, 25)
- .setText('supportFreesewingBecomeAPatron', 'center')
- .setText('please?')
-
- return box(part, 200, 50)
- },
-}
-
-export const point_shift = {
- name: 'examples.point_shift',
- draft: ({ Point, points, macro, part }) => {
- points.A = new Point(90, 40).attr('data-text', 'Point A').attr('data-text-class', 'right')
- points.B = points.A.shift(155, 70)
- .attr('data-text', 'Point B is point A shifted 7cm\nat a 155 degree angle')
- .attr('data-text-lineheight', 6)
-
- macro('ld', {
- from: points.B,
- to: points.A,
- d: -10,
- })
-
- return box(part, 100, 45)
- },
-}
-
-export const point_shiftfractiontowards = {
- name: 'examples.point_shiftfractiontowards',
- draft: ({ Point, points, Path, paths, macro, part }) => {
- points.A = new Point(90, 70).attr('data-text', 'Point A')
- points.B = new Point(10, 10).attr('data-text', 'Point B')
- points.C = points.A.shiftFractionTowards(points.B, 0.5)
- .attr('data-text', 'Point C is point A shifted 50%\nin the direction of point B')
- .attr('data-text-class', 'center')
- .attr('data-text-lineheight', 6)
-
- paths.direction = new Path().move(points.A).line(points.B).attr('class', 'note dashed')
-
- macro('ld', {
- from: points.C,
- to: points.A,
- d: -10,
- })
-
- macro('ld', {
- from: points.B,
- to: points.A,
- d: 20,
- })
-
- return part
- },
-}
-
-export const point_shiftoutwards = {
- name: 'examples.point_shiftoutwards',
- draft: ({ Point, points, Path, paths, macro, part }) => {
- points.A = new Point(90, 70).attr('data-text', 'Point A')
- points.B = new Point(30, 30).attr('data-text', 'Point B')
- points.C = points.A.shiftOutwards(points.B, 30)
- .attr('data-text', 'Point C is point A shifted 3cm\nbeyond point B')
- .attr('data-text-lineheight', 6)
-
- paths.direction = new Path().move(points.A).line(points.C).attr('class', 'note dashed')
-
- macro('ld', {
- from: points.C,
- to: points.B,
- d: -10,
- })
-
- return box(part, 110, 75)
- },
-}
-
-export const point_shifttowards = {
- name: 'examples.point_shifttowards',
- draft: ({ Point, points, Path, paths, macro, part }) => {
- points.A = new Point(90, 70).attr('data-text', 'Point A')
- points.B = new Point(10, 10).attr('data-text', 'Point B')
- points.C = points.A.shiftTowards(points.B, 35)
- .attr('data-text', 'Point C is point A shifted 3.5cm\nin the direction of point B')
- .attr('data-text-class', 'center')
- .attr('data-text-lineheight', 6)
-
- paths.direction = new Path().move(points.A).line(points.B).attr('class', 'note dashed')
-
- macro('ld', {
- from: points.C,
- to: points.A,
- d: -10,
- })
-
- return box(part, 110, 80)
- },
-}
-
-export const point_sitson = {
- name: 'examples.point_sitson',
- draft: ({ Point, points, Snippet, snippets, part }) => {
- let s
- for (let i = 0; i < 10; i++) {
- points[`a${i}`] = new Point(i * 10, 40)
- points[`b${i}`] = new Point(i * 10, i * 8)
- if (points[`a${i}`].sitsOn(points[`b${i}`])) s = 'notch'
- else s = 'bnotch'
- snippets[`b${i}`] = new Snippet(s, points[`b${i}`])
- snippets[`a${i}`] = new Snippet(s, points[`a${i}`])
- }
-
- return box(part)
- },
-}
-
-export const point_sitsroughlyon = {
- name: 'examples.point_sitsroughlyon',
- draft: ({ Point, points, Snippet, snippets, part }) => {
- box(part)
-
- let s
- for (let i = 0; i < 10; i++) {
- points[`a${i}`] = new Point(i * 10, 40)
- points[`b${i}`] = new Point(i * 10, i * 8)
- if (points[`a${i}`].sitsRoughlyOn(points[`b${i}`])) s = 'notch'
- else s = 'bnotch'
- snippets[`b${i}`] = new Snippet(s, points[`b${i}`])
- snippets[`a${i}`] = new Snippet(s, points[`a${i}`])
- }
-
- return part
- },
-}
-
-export const point_translate = {
- name: 'examples.point_translate',
- draft: ({ Point, points, macro, part }) => {
- points.A = new Point(20, 20).attr('data-text', 'Point A')
- points.B = points.A.translate(120, 60)
- .attr('data-text', 'Point B is point A with a\ntranslate(120, 60)\ntransform applied')
- .attr('data-text-class', 'right')
- .attr('data-text-dy', -6)
- .attr('data-text-lineheight', 6)
-
- macro('ld', {
- from: points.A,
- to: points.B,
- text: 'translate(120,60)',
- noStartMarker: true,
- })
-
- return box(part, 150, 85)
- },
-}
diff --git a/designs/examples/src/settings.mjs b/designs/examples/src/settings.mjs
deleted file mode 100644
index a8ffe9ea574..00000000000
--- a/designs/examples/src/settings.mjs
+++ /dev/null
@@ -1,22 +0,0 @@
-export const settings_sa = {
- name: 'examples.settings_sa',
- draft: ({ Point, points, Path, paths, part }) => {
- points.A = new Point(45, 60)
- points.B = new Point(10, 30)
- points.BCp2 = new Point(40, 20)
- points.C = new Point(90, 30)
- points.CCp1 = new Point(50, -30)
-
- paths.example = new Path()
- .move(points.A)
- .line(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
- .line(points.A)
- .close()
- .attr('class', 'fabric')
-
- paths.offset = paths.example.offset(-10).attr('class', 'fabric sa')
-
- return part
- },
-}
diff --git a/designs/examples/src/shared.mjs b/designs/examples/src/shared.mjs
deleted file mode 100644
index e99bb3fbd3c..00000000000
--- a/designs/examples/src/shared.mjs
+++ /dev/null
@@ -1,13 +0,0 @@
-/**
- * This draws a (diagonal in a) box
- * with with w and height h with a non-visible line.
- * This is to force our examples parts to a certain size
- */
-export function box(part, w = 100, h = 50) {
- part.paths.box = new part.Path()
- .move(new part.Point(0, 0))
- .line(new part.Point(w, h))
- .setClass('hidden noxray')
-
- return part
-}
diff --git a/designs/examples/src/snippet.mjs b/designs/examples/src/snippet.mjs
deleted file mode 100644
index 152a6635f07..00000000000
--- a/designs/examples/src/snippet.mjs
+++ /dev/null
@@ -1,39 +0,0 @@
-import { box } from './shared.mjs'
-
-export const snippet = {
- name: 'examples.snippet',
- draft: ({ Point, points, Snippet, snippets, part }) => {
- points.anchor1 = new Point(20, 15)
- points.anchor2 = new Point(50, 15)
- points.anchor3 = new Point(80, 15)
- snippets.demo1 = new Snippet('button', points.anchor1)
- snippets.demo2 = new Snippet('buttonhole', points.anchor2)
- snippets.demo3 = new Snippet('logo', points.anchor3).attr('data-scale', 0.5)
-
- return box(part)
- },
-}
-
-export const snippet_attr = {
- name: 'examples.snippet_attr',
- draft: ({ Point, points, Snippet, snippets, part }) => {
- points.anchor = new Point(50, 15)
- snippets.demo = new Snippet('logo', points.anchor)
- .attr('data-scale', 0.8)
- .attr('data-rotate', 180)
-
- return box(part)
- },
-}
-
-export const snippet_clone = {
- name: 'examples.snippet_clone',
- draft: ({ Point, points, Snippet, snippets, part }) => {
- points.anchor = new Point(35, 35)
- snippets.demo = new Snippet('logo', points.anchor).attr('style', 'color: #f006')
-
- snippets.clone = snippets.demo.clone().attr('data-scale', 0.5)
-
- return box(part)
- },
-}
diff --git a/designs/examples/src/snippets.mjs b/designs/examples/src/snippets.mjs
deleted file mode 100644
index 95c2e3d3ea4..00000000000
--- a/designs/examples/src/snippets.mjs
+++ /dev/null
@@ -1,91 +0,0 @@
-import { box } from './shared.mjs'
-
-export const snippet_bnotch = {
- name: 'examples.snippet_bnotch',
- draft: ({ Point, points, Snippet, snippets, part }) => {
- points.anchor = new Point(50, 5)
- snippets.demo = new Snippet('bnotch', points.anchor)
-
- return box(part, 100, 10)
- },
-}
-
-export const snippet_button = {
- name: 'examples.snippet_button',
- draft: ({ Point, points, Snippet, snippets, part }) => {
- points.anchor = new Point(50, 5)
- snippets.demo = new Snippet('button', points.anchor)
-
- return box(part, 100, 10)
- },
-}
-
-export const snippet_buttonholeend = {
- name: 'examples.snippet_buttonholeend',
- draft: ({ Point, points, Snippet, snippets, part }) => {
- points.anchor = new Point(50, 0)
- snippets.demo = new Snippet('buttonhole-end', points.anchor)
-
- return box(part, 100, 10)
- },
-}
-
-export const snippet_buttonholestart = {
- name: 'examples.snippet_buttonholestart',
- draft: ({ Point, points, Snippet, snippets, part }) => {
- points.anchor = new Point(50, 10)
- snippets.demo = new Snippet('buttonhole-start', points.anchor)
-
- return box(part, 100, 10)
- },
-}
-
-export const snippet_buttonhole = {
- name: 'examples.snippet_buttonhole',
- draft: ({ Point, points, Snippet, snippets, part }) => {
- points.anchor = new Point(50, 5)
- snippets.demo = new Snippet('buttonhole', points.anchor)
-
- return box(part, 100, 10)
- },
-}
-
-export const snippet_logo = {
- name: 'examples.snippet_logo',
- draft: ({ Point, points, Snippet, snippets, part }) => {
- points.anchor = new Point(50, 35)
- snippets.demo = new Snippet('logo', points.anchor)
-
- return box(part, 100, 50)
- },
-}
-
-export const snippet_notch = {
- name: 'examples.snippet_notch',
- draft: ({ Point, points, Snippet, snippets, part }) => {
- points.anchor = new Point(50, 5)
- snippets.demo = new Snippet('notch', points.anchor)
-
- return box(part, 100, 10)
- },
-}
-
-export const snippet_snapsocket = {
- name: 'examples.snippet_snapsocket',
- draft: ({ Point, points, Snippet, snippets, part }) => {
- points.anchor = new Point(50, 5)
- snippets.demo = new Snippet('snap-socket', points.anchor)
-
- return box(part, 100, 10)
- },
-}
-
-export const snippet_snapstud = {
- name: 'examples.snippet_snapstud',
- draft: ({ Point, points, Snippet, snippets, part }) => {
- points.anchor = new Point(50, 5)
- snippets.demo = new Snippet('snap-stud', points.anchor)
-
- return box(part, 100, 10)
- },
-}
diff --git a/designs/examples/src/stacks.mjs b/designs/examples/src/stacks.mjs
deleted file mode 100644
index 8b0cd0255f6..00000000000
--- a/designs/examples/src/stacks.mjs
+++ /dev/null
@@ -1,128 +0,0 @@
-const stack = (settings, partName) => {
- if (settings?.options?.stackIt === 'Do stack') return 'example'
- else return partName
-}
-
-export const stacks_top = {
- name: 'examples.stacks_top',
- stack,
- measurements: ['head'],
- options: {
- size: { pct: 50, min: 5, max: 100, menu: 'stack' },
- x: { pct: 0, min: -100, max: 100, menu: 'stack' },
- y: { pct: 0, min: -100, max: 100, menu: 'stack' },
- stackIt: { dflt: 'Do stack', list: ['Do stack', 'Do not stack'], menu: 'stack' },
- },
- draft: ({ store, Point, points, Path, paths, options, measurements, part }) => {
- store.set('size', measurements.head * options.size)
- store.set('x', measurements.head * options.x)
- store.set('y', measurements.head * options.y)
- points.from = new Point(store.get('x'), store.get('y'))
- points.to = points.from.shift(0, store.get('size'))
- paths.line = new Path().move(points.from).line(points.to).attr('class', 'fabric stroke-4xl')
-
- return part
- },
-}
-
-export const stacks_right = {
- name: 'examples.stacks_right',
- stack,
- after: stacks_top,
- draft: ({ store, Point, points, Path, paths, part }) => {
- points.from = new Point(store.get('x') + store.get('size'), store.get('y'))
- points.to = points.from.shift(-90, store.get('size'))
- paths.line = new Path().move(points.from).line(points.to).attr('class', 'fabric stroke-4xl')
-
- return part
- },
-}
-
-export const stacks_bottom = {
- name: 'examples.stacks_bottom',
- stack,
- after: stacks_top,
- draft: ({ store, Point, points, Path, paths, part }) => {
- points.from = new Point(store.get('x') + store.get('size'), store.get('y') + store.get('size'))
- points.to = points.from.shift(180, store.get('size'))
- paths.line = new Path().move(points.from).line(points.to).attr('class', 'fabric stroke-4xl')
-
- return part
- },
-}
-
-export const stacks_left = {
- name: 'examples.stacks_left',
- stack,
- after: stacks_top,
- draft: ({ store, Point, points, Path, paths, part }) => {
- points.from = new Point(store.get('x'), store.get('y') + store.get('size'))
- points.to = points.from.shift(90, store.get('size'))
- paths.line = new Path().move(points.from).line(points.to).attr('class', 'fabric stroke-4xl')
-
- return part
- },
-}
-
-export const stacks_leftEye = {
- name: 'examples.stacks_leftEye',
- stack,
- after: stacks_top,
- draft: ({ store, Point, points, part }) => {
- points.leftEye = new Point(
- store.get('x') + store.get('size') * 0.35,
- store.get('y') + store.get('size') * 0.4
- )
- .attr('data-circle', store.get('size') * 0.1)
- .attr('data-circle-class', 'stroke-6xl')
-
- return part
- },
-}
-
-export const stacks_rightEye = {
- name: 'examples.stacks_rightEye',
- stack,
- after: stacks_top,
- draft: ({ store, Point, points, part }) => {
- points.rightEye = new Point(
- store.get('x') + store.get('size') * 0.65,
- store.get('y') + store.get('size') * 0.4
- )
- .attr('data-circle', store.get('size') * 0.08)
- .attr('data-circle-class', 'stroke-7xl')
-
- return part
- },
-}
-
-export const stacks_mouth = {
- name: 'examples.stacks_mouth',
- stack,
- after: stacks_top,
- draft: ({ store, Point, points, paths, Path, part }) => {
- points.left = new Point(
- store.get('x') + store.get('size') * 0.15,
- store.get('y') + store.get('size') * 0.5
- )
- points.right = new Point(
- store.get('x') + store.get('size') * 0.85,
- store.get('y') + store.get('size') * 0.5
- )
- points.leftCp = new Point(
- store.get('x') + store.get('size') * 0.35,
- store.get('y') + store.get('size') * 0.8
- )
- points.rightCp = new Point(
- store.get('x') + store.get('size') * 0.65,
- store.get('y') + store.get('size') * 0.8
- )
-
- paths.mouth = new Path()
- .move(points.left)
- .curve(points.leftCp, points.rightCp, points.right)
- .attr('class', 'fabric stroke-7xl')
-
- return part
- },
-}
diff --git a/designs/examples/src/utils.mjs b/designs/examples/src/utils.mjs
deleted file mode 100644
index 201fa7d40f0..00000000000
--- a/designs/examples/src/utils.mjs
+++ /dev/null
@@ -1,445 +0,0 @@
-import { box } from './shared.mjs'
-
-export const utils_beamintersectscircle = {
- name: 'examples.utils_beamintersectscircle',
- draft: ({ Point, points, Path, paths, Snippet, snippets, utils, part }) => {
- points.A = new Point(95, 45).attr('data-circle', 35).attr('data-circle-class', 'fabric')
- points.B = new Point(55, 50)
- points.C = new Point(75, 30)
- points.D = new Point(55, 65)
- points.E = new Point(115, 5)
- points.F = new Point(65, 75)
- points.G = new Point(125, 15)
-
- paths.line1 = new Path().move(points.B).line(points.C)
- paths.line2 = new Path().move(points.D).line(points.E)
- paths.line3 = new Path().move(points.F).line(points.G)
-
- let intersections1 = utils.beamIntersectsCircle(
- points.A,
- points.A.attributes.get('data-circle'),
- points.B,
- points.C
- )
- let intersections2 = utils.beamIntersectsCircle(
- points.A,
- points.A.attributes.get('data-circle'),
- points.D,
- points.E,
- 'y'
- )
- let intersections3 = utils.beamIntersectsCircle(
- points.A,
- points.A.attributes.get('data-circle'),
- points.F,
- points.G
- )
-
- snippets.first1 = new Snippet('bnotch', intersections1[0])
- snippets.second1 = new Snippet('notch', intersections1[1])
- snippets.first2 = new Snippet('bnotch', intersections2[0])
- snippets.second2 = new Snippet('notch', intersections2[1])
- snippets.first3 = new Snippet('bnotch', intersections3[0])
- snippets.second3 = new Snippet('notch', intersections3[1])
-
- return box(part, 200, 80)
- },
-}
-
-export const utils_beamintersectsx = {
- name: 'examples.utils_beamintersectsx',
- draft: ({ Point, points, Path, paths, Snippet, snippets, utils, part }) => {
- points.A = new Point(10, 10)
- points.B = new Point(90, 30)
-
- paths.AB = new Path().move(points.A).line(points.B)
-
- snippets.x = new Snippet('notch', utils.beamIntersectsX(points.A, points.B, 40))
-
- paths.help = new Path()
- .move(new Point(40, 5))
- .line(new Point(40, 35))
- .attr('class', 'note dashed')
-
- return part
- },
-}
-
-export const utils_beamintersectsy = {
- name: 'examples.utils_beamintersectsy',
- draft: ({ Point, points, Path, paths, Snippet, snippets, utils, part }) => {
- points.A = new Point(10, 10)
- points.B = new Point(50, 40)
-
- paths.AB = new Path().move(points.A).line(points.B)
-
- snippets.x = new Snippet('notch', utils.beamIntersectsY(points.A, points.B, 30))
-
- paths.help = new Path()
- .move(new Point(0, 30))
- .line(new Point(50, 30))
- .attr('class', 'note dashed')
-
- return part
- },
-}
-
-export const utils_beamsintersect = {
- name: 'examples.utils_beamsintersect',
- draft: ({ Point, points, Path, paths, Snippet, snippets, utils, part }) => {
- points.A = new Point(10, 10)
- points.B = new Point(50, 40)
- points.C = new Point(45, 20)
- points.D = new Point(60, 15)
-
- paths.AB = new Path().move(points.A).line(points.B)
- paths.CD = new Path().move(points.C).line(points.D)
-
- snippets.x = new Snippet('notch', utils.beamsIntersect(points.A, points.B, points.C, points.D))
-
- return part
- },
-}
-
-export const utils_circlesintersect = {
- name: 'examples.utils_circlesintersect',
- draft: ({ Point, points, Snippet, snippets, utils, part }) => {
- points.A = new Point(10, 10).attr('data-circle', 15).attr('data-circle-class', 'fabric')
- points.B = new Point(30, 30).attr('data-circle', 35).attr('data-circle-class', 'fabric')
- points.C = new Point(90, 10).attr('data-circle', 15).attr('data-circle-class', 'various')
- points.D = new Point(110, 30).attr('data-circle', 35).attr('data-circle-class', 'various')
-
- let intersections1 = utils.circlesIntersect(
- points.A,
- points.A.attributes.get('data-circle'),
- points.B,
- points.B.attributes.get('data-circle')
- )
- let intersections2 = utils.circlesIntersect(
- points.C,
- points.C.attributes.get('data-circle'),
- points.D,
- points.D.attributes.get('data-circle'),
- 'y'
- )
-
- snippets.first1 = new Snippet('bnotch', intersections1[0])
- snippets.second1 = new Snippet('notch', intersections1[1])
- snippets.first2 = new Snippet('bnotch', intersections2[0])
- snippets.second2 = new Snippet('notch', intersections2[1])
-
- return part
- },
-}
-
-export const utils_curveintersectsx = {
- name: 'examples.utils_curveintersectsx',
- draft: ({ Point, points, Path, paths, utils, snippets, Snippet, part }) => {
- points.start = new Point(10, 15)
- points.cp1 = new Point(80, 10)
- points.cp2 = new Point(-50, 80)
- points.end = new Point(110, 70)
-
- paths.curve = new Path().move(points.start).curve(points.cp1, points.cp2, points.end)
-
- for (let x of [30, 40]) {
- points['from' + x] = new Point(x, 10)
- points['to' + x] = new Point(x, 80)
- paths['line' + x] = new Path()
- .move(points['from' + x])
- .line(points['to' + x])
- .attr('class', 'lining dashed')
- }
-
- snippets.i40 = new Snippet(
- 'notch',
- utils.curveIntersectsX(points.start, points.cp1, points.cp2, points.end, 40)
- )
-
- for (let p of utils.curveIntersectsX(points.start, points.cp1, points.cp2, points.end, 30))
- snippets[p.y] = new Snippet('notch', p)
-
- return part
- },
-}
-
-export const utils_curveintersectsy = {
- name: 'examples.utils_curveintersectsy',
- draft: ({ Point, points, Path, paths, utils, snippets, Snippet, part }) => {
- points.start = new Point(10, 45)
- points.cp1 = new Point(50, 10)
- points.cp2 = new Point(0, 80)
- points.end = new Point(110, 70)
-
- paths.curve = new Path().move(points.start).curve(points.cp1, points.cp2, points.end)
-
- for (let y of [40, 50]) {
- points['from' + y] = new Point(10, y)
- points['to' + y] = new Point(110, y)
- paths['line' + y] = new Path()
- .move(points['from' + y])
- .line(points['to' + y])
- .attr('class', 'lining dashed')
- }
-
- snippets.i50 = new Snippet(
- 'notch',
- utils.curveIntersectsY(points.start, points.cp1, points.cp2, points.end, 50)
- )
-
- for (let p of utils.curveIntersectsY(points.start, points.cp1, points.cp2, points.end, 40))
- snippets[p.x] = new Snippet('notch', p)
-
- return part
- },
-}
-
-export const utils_curvesintersect = {
- name: 'examples.utils_curvesintersect',
- draft: ({ Point, points, Path, paths, Snippet, snippets, utils, part }) => {
- points.A = new Point(10, 10)
- points.Acp = new Point(310, 40)
- points.B = new Point(110, 70)
- points.Bcp = new Point(-210, 40)
-
- points.C = new Point(20, -5)
- points.Ccp = new Point(60, 300)
- points.D = new Point(100, 85)
- points.Dcp = new Point(70, -220)
- paths.curveA = new Path().move(points.A).curve(points.Acp, points.Bcp, points.B)
- paths.curveB = new Path().move(points.C).curve(points.Ccp, points.Dcp, points.D)
-
- for (let p of utils.curvesIntersect(
- points.A,
- points.Acp,
- points.Bcp,
- points.B,
- points.C,
- points.Ccp,
- points.Dcp,
- points.D
- )) {
- snippets[part.getId()] = new Snippet('notch', p)
- }
-
- return part
- },
-}
-
-export const utils_lineintersectscircle = {
- name: 'examples.utils_lineintersectscircle',
- draft: ({ Point, points, Path, paths, Snippet, snippets, utils, part }) => {
- points.A = new Point(95, 45).attr('data-circle', 35).attr('data-circle-class', 'fabric')
- points.B = new Point(55, 50)
- points.C = new Point(75, 30)
-
- points.D = new Point(55, 65)
- points.E = new Point(115, 5)
- points.F = new Point(65, 75)
- points.G = new Point(125, 15)
-
- paths.line1 = new Path().move(points.B).line(points.C)
- paths.line2 = new Path().move(points.D).line(points.E)
- paths.line3 = new Path().move(points.F).line(points.G)
-
- let intersections1 = utils.lineIntersectsCircle(
- points.A,
- points.A.attributes.get('data-circle'),
- points.B,
- points.C
- )
- let intersections2 = utils.lineIntersectsCircle(
- points.A,
- points.A.attributes.get('data-circle'),
- points.D,
- points.E,
- 'y'
- )
- let intersections3 = utils.lineIntersectsCircle(
- points.A,
- points.A.attributes.get('data-circle'),
- points.F,
- points.G
- )
- snippets.first1 = new Snippet('bnotch', intersections1[0])
- snippets.first2 = new Snippet('bnotch', intersections2[0])
- snippets.second2 = new Snippet('notch', intersections2[1])
- snippets.first3 = new Snippet('bnotch', intersections3[0])
- snippets.second3 = new Snippet('notch', intersections3[1])
-
- return box(part, 200, 80)
- },
-}
-
-export const utils_lineintersectscurve = {
- name: 'examples.utils_lineintersectscurve',
- draft: ({ Point, points, Path, paths, Snippet, snippets, utils, part }) => {
- points.A = new Point(10, 10)
- points.Acp = new Point(310, 40)
- points.B = new Point(110, 70)
- points.Bcp = new Point(-210, 40)
- points.E = new Point(20, -5)
- points.D = new Point(100, 85)
- paths.curve = new Path().move(points.A).curve(points.Acp, points.Bcp, points.B)
- paths.line = new Path().move(points.E).line(points.D)
-
- for (let p of utils.lineIntersectsCurve(
- points.D,
- points.E,
- points.A,
- points.Acp,
- points.Bcp,
- points.B
- )) {
- snippets[part.getId()] = new Snippet('notch', p)
- }
-
- return part
- },
-}
-
-export const utils_linesintersect = {
- name: 'examples.utils_linesintersect',
- draft: ({ Point, points, Path, paths, Snippet, snippets, utils, part }) => {
- points.A = new Point(10, 10)
- points.B = new Point(50, 40)
- points.C = new Point(15, 30)
- points.D = new Point(60, 15)
-
- paths.AB = new Path().move(points.A).line(points.B)
- paths.CD = new Path().move(points.C).line(points.D)
-
- snippets.X = new Snippet('notch', utils.linesIntersect(points.A, points.B, points.C, points.D))
-
- return part
- },
-}
-
-export const utils_pointonbeam = {
- name: 'examples.utils_pointonbeam',
- draft: ({ Point, points, Path, paths, Snippet, snippets, utils, part }) => {
- points.from1 = new Point(10, 10)
- points.to1 = new Point(90, 60)
- points.from2 = new Point(10, 30)
- points.to2 = new Point(90, 80)
- points.b1 = new Point(170, 110)
- points.b2 = new Point(170, 130)
-
- let scatter = []
- for (let i = 1; i < 36; i++) {
- for (let j = 1; j < 27; j++) {
- scatter.push(new Point(i * 10, j * 10))
- }
- }
- let snippet
- for (let point of scatter) {
- if (utils.pointOnBeam(points.from1, points.to1, point)) snippet = 'notch'
- else snippet = 'bnotch'
- snippets[part.getId()] = new Snippet(snippet, point)
- if (utils.pointOnBeam(points.from2, points.to2, point, 0.01)) {
- snippet = 'notch'
- } else snippet = 'bnotch'
- snippets[part.getId()] = new Snippet(snippet, point)
- }
- paths.line1 = new Path().move(points.from1).line(points.to1).attr('class', 'fabric stroke-lg')
- paths.lne1 = new Path().move(points.to1).line(points.b1).attr('class', 'fabric dashed')
- paths.line2 = new Path().move(points.from2).line(points.to2).attr('class', 'fabric stroke-lg')
- paths.lne2 = new Path().move(points.to2).line(points.b2).attr('class', 'fabric dashed')
-
- return part
- },
-}
-
-export const utils_pointoncurve = {
- name: 'examples.utils_pointoncurve',
- draft: ({ Point, points, Path, paths, Snippet, snippets, utils, part }) => {
- points.start = new Point(10, 10)
- points.cp1 = new Point(90, 10)
- points.cp2 = new Point(10, 60)
- points.end = new Point(90, 60)
-
- let scatter = []
- for (let i = 1; i < 19; i++) {
- for (let j = 1; j < 14; j++) {
- scatter.push(new Point(i * 10, j * 10))
- }
- }
- let snippet
- for (let point of scatter) {
- if (utils.pointOnCurve(points.start, points.cp1, points.cp2, points.end, point)) {
- snippet = 'notch'
- } else snippet = 'bnotch'
- snippets[part.getId()] = new Snippet(snippet, point)
- }
- paths.curve = new Path()
- .move(points.start)
- .curve(points.cp1, points.cp2, points.end)
- .attr('class', 'fabric stroke-lg')
-
- return part
- },
-}
-
-export const utils_pointonline = {
- name: 'examples.utils_pointonline',
- draft: ({ Point, points, Path, paths, Snippet, snippets, utils, part }) => {
- points.from1 = new Point(10, 10)
- points.to1 = new Point(90, 60)
- points.from2 = new Point(10, 30)
- points.to2 = new Point(90, 80)
- points.b1 = new Point(170, 110)
- points.b2 = new Point(170, 130)
-
- let scatter = []
- for (let i = 1; i < 36; i++) {
- for (let j = 1; j < 27; j++) {
- scatter.push(new Point(i * 10, j * 10))
- }
- }
- let snippet
- for (let point of scatter) {
- if (utils.pointOnLine(points.from1, points.to1, point)) snippet = 'notch'
- else snippet = 'bnotch'
- snippets[part.getId()] = new Snippet(snippet, point)
- if (utils.pointOnLine(points.from2, points.to2, point, 0.01)) {
- snippet = 'notch'
- } else snippet = 'bnotch'
- snippets[part.getId()] = new Snippet(snippet, point)
- }
- paths.line1 = new Path().move(points.from1).line(points.to1).attr('class', 'fabric stroke-lg')
- paths.lne1 = new Path().move(points.to1).line(points.b1).attr('class', 'fabric dashed')
- paths.line2 = new Path().move(points.from2).line(points.to2).attr('class', 'fabric stroke-lg')
- paths.lne2 = new Path().move(points.to2).line(points.b2).attr('class', 'fabric dashed')
-
- return part
- },
-}
-
-export const utils_splitcurve = {
- name: 'examples.utils_splitcurve',
- draft: ({ Point, points, Path, paths, utils, part }) => {
- points.from = new Point(40, 10)
- points.to = new Point(40, 80)
- paths.line = new Path().move(points.from).line(points.to).attr('class', 'lining dashed')
-
- points.start = new Point(10, 15)
- points.cp1 = new Point(80, 10)
- points.cp2 = new Point(-50, 80)
- points.end = new Point(110, 70)
-
- points.i40 = utils.curveIntersectsX(points.start, points.cp1, points.cp2, points.end, 40)
-
- let parts = utils.splitCurve(points.start, points.cp1, points.cp2, points.end, points.i40)
-
- let colors = ['lining', 'interfacing']
- for (let p of parts) {
- let color = colors.pop()
- paths[color] = new Path()
- .move(p.start)
- .curve(p.cp1, p.cp2, p.end)
- .attr('class', 'stroke-xl ' + color)
- }
-
- return part
- },
-}
diff --git a/designs/hi/src/body.mjs b/designs/hi/src/body.mjs
index da8b19b5be6..2143b29025c 100644
--- a/designs/hi/src/body.mjs
+++ b/designs/hi/src/body.mjs
@@ -409,7 +409,6 @@ function draftHiBody({
.curve(points.body02cp1, points.body03cp2, points.body03)
.join(paths.allButDart)
.close()
- .hide()
let gillPath = new Path()
.move(points.body17)
diff --git a/designs/hugo/src/front.mjs b/designs/hugo/src/front.mjs
index 3fcef579843..7ab6591ea44 100644
--- a/designs/hugo/src/front.mjs
+++ b/designs/hugo/src/front.mjs
@@ -89,9 +89,7 @@ function hugoFront({
.line(points.raglanTipFront)
.join(neckOpeningParts[0].reverse())
paths.saBase.hide()
- paths.seam = paths.saBase.clone().close().attr('class', 'fabric')
- // FIXME: This pocket path is not getting set on the paths object
- // It's something to do with the paths proxy which -- I assume -- is proxying the wrong object?
+ paths.seam = paths.saBase.clone().unhide().close().attr('class', 'fabric')
paths.pocket = new Path()
.move(points.pocketHem)
.line(points.pocketTip)
diff --git a/designs/hugo/src/pocket.mjs b/designs/hugo/src/pocket.mjs
index 8ef02ff8dc5..1aae397d7e6 100644
--- a/designs/hugo/src/pocket.mjs
+++ b/designs/hugo/src/pocket.mjs
@@ -101,6 +101,6 @@ function hugoPocket({
export const pocket = {
name: 'hugo.pocket',
from: front,
- hideDependencies: true,
+ // hideDependencies: true,
draft: hugoPocket,
}
diff --git a/designs/hugo/src/pocketfacing.mjs b/designs/hugo/src/pocketfacing.mjs
index e8f5388e608..c2ab9853e5a 100644
--- a/designs/hugo/src/pocketfacing.mjs
+++ b/designs/hugo/src/pocketfacing.mjs
@@ -47,6 +47,5 @@ function hugoPocketFacing({ sa, points, Path, paths, complete, paperless, macro,
export const pocketFacing = {
name: 'hugo.pocketFacing',
from: pocket,
- hideDependencies: true,
draft: hugoPocketFacing,
}
diff --git a/designs/lunetius/src/lacerna.mjs b/designs/lunetius/src/lacerna.mjs
index 499acf28a51..ee171f115d5 100644
--- a/designs/lunetius/src/lacerna.mjs
+++ b/designs/lunetius/src/lacerna.mjs
@@ -61,7 +61,7 @@ function lunetiusLacerna({
.line(points.bottom)
.hide()
paths.saBase = new Path().move(points.top).line(points.topLeft).hide()
- paths.seam = paths.saBase.join(paths.hem).join(paths.fold).attr('class', 'fabric').hide()
+ paths.seam = paths.saBase.join(paths.hem).join(paths.fold).attr('class', 'fabric')
// Complete?
if (complete) {
diff --git a/designs/plugintest/src/plugin-round.mjs b/designs/plugintest/src/plugin-round.mjs
index 82e33b18e9e..abb5046cce7 100644
--- a/designs/plugintest/src/plugin-round.mjs
+++ b/designs/plugintest/src/plugin-round.mjs
@@ -17,7 +17,7 @@ const pluginRound = ({ Point, points, Path, paths, macro, options, part }) => {
.attr('class', 'note dashed')
const opts = {
- radius: options.roundRadius,
+ radius: Number(options.roundRadius),
hide: options.roundHide,
}
diff --git a/designs/plugintest/src/plugin-scalebox.mjs b/designs/plugintest/src/plugin-scalebox.mjs
index 92750aeb2c1..df125f1ac63 100644
--- a/designs/plugintest/src/plugin-scalebox.mjs
+++ b/designs/plugintest/src/plugin-scalebox.mjs
@@ -7,6 +7,7 @@ const pluginScalebox = ({ Point, points, macro, options, part }) => {
macro(options.scaleboxType, {
at: points.a,
+ rotate: options.scaleboxRotation,
})
}
@@ -19,6 +20,7 @@ export const scalebox = {
after: base,
options: {
scaleboxType: { dflt: 'scalebox', list: ['scalebox', 'miniscale'], menu: 'scalebox' },
+ scaleboxRotation: { deg: 0, min: 0, max: 360, menu: 'scalebox' },
},
draft: pluginScalebox,
}
diff --git a/designs/teagan/src/back.mjs b/designs/teagan/src/back.mjs
index 4b2afa3fe2c..f87587160f0 100644
--- a/designs/teagan/src/back.mjs
+++ b/designs/teagan/src/back.mjs
@@ -39,8 +39,7 @@ function teaganBack({
.join(paths.saBase)
.line(points.cfHem)
.close()
- .hide()
- .attr('class', 'fabric')
+ .setClass('fabric')
// Set store values required to draft sleevecap
store.set('sleevecapEase', 0)
diff --git a/designs/unice/.eslintrc.yml b/designs/unice/.eslintrc.yml
new file mode 100644
index 00000000000..b39fd0463e8
--- /dev/null
+++ b/designs/unice/.eslintrc.yml
@@ -0,0 +1,18 @@
+env:
+ browser: true
+ es2021: true
+extends: eslint:recommended
+overrides:
+ - files: ["*.yaml", "*.yml"]
+ plugins: ["yaml"]
+ extends: ["plugin:yaml/recommended"]
+parserOptions:
+ ecmaVersion: latest
+ sourceType: module
+rules: {}
+globals:
+ it: readonly
+ describe: readonly
+ process: readonly
+ __dirname: readonly
+
diff --git a/designs/unice/CHANGELOG.md b/designs/unice/CHANGELOG.md
new file mode 100644
index 00000000000..6b458471bea
--- /dev/null
+++ b/designs/unice/CHANGELOG.md
@@ -0,0 +1,15 @@
+# Change log for: @freesewing/unice
+
+
+## 2.21.0 (2022-06-27)
+
+### Added
+
+ - Unice is an underwear pattern
+
+
+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/designs/examples/README.md b/designs/unice/README.md
similarity index 98%
rename from designs/examples/README.md
rename to designs/unice/README.md
index 31fba58bc1f..6375f82401a 100644
--- a/designs/examples/README.md
+++ b/designs/unice/README.md
@@ -1,13 +1,13 @@

+ href="https://www.npmjs.com/package/@freesewing/unice"
+ title="@freesewing/unice on NPM"
+ >

+ href="https://github.com/freesewing/freesewing/issues?q=is%3Aissue+is%3Aopen+label%3Apkg%3Aunice"
+ title="Open issues tagged pkg:unice"
+ >
-# @freesewing/examples
+# @freesewing/unice
-A FreeSewing pattern holding examples for our documentation
+A FreeSewing pattern for a basic, highly-customizable underwear pattern
@@ -63,7 +63,7 @@ A FreeSewing pattern holding examples for our documentation
This repository is our *monorepo* holding all our NPM designs, plugins, other NPM packages, and (web)sites.
-This folder holds: @freesewing/examples
+This folder holds: @freesewing/unice
If you're not entirely sure what to do or how to start, type this command:
diff --git a/designs/examples/build.mjs b/designs/unice/build.mjs
similarity index 100%
rename from designs/examples/build.mjs
rename to designs/unice/build.mjs
diff --git a/designs/examples/data.mjs b/designs/unice/data.mjs
similarity index 77%
rename from designs/examples/data.mjs
rename to designs/unice/data.mjs
index 0617f3ee8e5..510883477b0 100644
--- a/designs/examples/data.mjs
+++ b/designs/unice/data.mjs
@@ -1,4 +1,4 @@
// This file is auto-generated | All changes you make will be overwritten.
-export const name = "@freesewing/examples"
+export const name = "@freesewing/unice"
export const version = "3.0.0-alpha.0"
export const data = { name, version }
diff --git a/designs/examples/package.json b/designs/unice/package.json
similarity index 78%
rename from designs/examples/package.json
rename to designs/unice/package.json
index 63b468a69e4..b827b14a8a9 100644
--- a/designs/examples/package.json
+++ b/designs/unice/package.json
@@ -1,8 +1,8 @@
{
- "name": "@freesewing/examples",
+ "name": "@freesewing/unice",
"version": "3.0.0-alpha.0",
- "description": "A FreeSewing pattern holding examples for our documentation",
- "author": "Joost De Cock (https://github.com/joostdecock)",
+ "description": "A FreeSewing pattern for a basic, highly-customizable underwear pattern",
+ "author": "Anna Puk (https://github.com/anna-puk)",
"homepage": "https://freesewing.org/",
"repository": "github:freesewing/freesewing",
"license": "MIT",
@@ -15,9 +15,14 @@
},
"keywords": [
"freesewing",
- "documentation",
- "example",
- "parametric design"
+ "design",
+ "diy",
+ "fashion",
+ "made to measure",
+ "parametric design",
+ "pattern",
+ "sewing",
+ "sewing pattern"
],
"type": "module",
"module": "dist/index.mjs",
@@ -41,9 +46,7 @@
"peerDependencies": {
"@freesewing/core": "^3.0.0-alpha.0",
"@freesewing/plugin-bundle": "^3.0.0-alpha.0",
- "@freesewing/config-helpers": "^3.0.0-alpha.0",
- "@freesewing/plugin-mirror": "^3.0.0-alpha.0",
- "@freesewing/plugin-gore": "^3.0.0-alpha.0"
+ "@freesewing/config-helpers": "^3.0.0-alpha.0"
},
"dependencies": {},
"devDependencies": {
diff --git a/designs/unice/src/back.mjs b/designs/unice/src/back.mjs
new file mode 100644
index 00000000000..afefabe8fbf
--- /dev/null
+++ b/designs/unice/src/back.mjs
@@ -0,0 +1,308 @@
+import { front } from './front.mjs'
+
+export const back = {
+ name: 'unice.back',
+ measurements: ['waist', 'seat', 'waistToSeat', 'waistToUpperLeg', 'hips', 'waistToHips'],
+ optionalMeasurements: ['crossSeam', 'crossSeamFront'],
+ options: {
+ backToFrontLength: 1.15, // Maybe include this in advanced options?
+ backToFrontWidth: 1.1, // Maybe include this in advanced options?
+ gussetRatio: 0.7, // Relationship between front and back gusset widths
+ backDip: { pct: 2.5, min: -5, max: 15, menu: 'style' },
+ backExposure: { pct: 20, min: -30, max: 90, menu: 'style' },
+ },
+ after: front,
+ draft: ({
+ utils,
+ store,
+ sa,
+ Point,
+ points,
+ Path,
+ paths,
+ options,
+ measurements,
+ complete,
+ paperless,
+ macro,
+ part,
+ }) => {
+ // Design pattern here
+
+ // Create points
+ points.backWaistMid = new Point(measurements.seat / 4, 0)
+ points.backWaistBandLeft = new Point(
+ store.get('sideSeamWaist').x / options.backToFrontWidth,
+ store.get('sideSeamWaist').y
+ )
+ points.backLegOpeningLeft = new Point(
+ store.get('sideSeamHip').x / options.backToFrontWidth,
+ store.get('sideSeamHip').y
+ )
+
+ // back height is given by (estimated) cross seam, minus front and gusset lengths
+ // this does not account for vertical stretch yet
+ const backHeight =
+ store.get('crossSeam') - store.get('frontHeight') - options.gussetLength * measurements.seat
+
+ // calculate the actual back height, using yScale above and yScaleReduced below leg opening
+ const backHeightAbove = store.get('frontHeightAbove') // part above has same height front and back
+
+ let backHeightBelow
+ backHeightBelow =
+ store.get('yScale') * (backHeight - backHeightAbove / store.get('yScaleReduced'))
+
+ const backHeightReduced = backHeightBelow + backHeightAbove
+
+ points.backGussetLeft = new Point(
+ measurements.seat / 4 -
+ ((measurements.waist * options.gussetWidth * store.get('xScale')) / options.gussetRatio) *
+ options.backToFrontWidth,
+ backHeightReduced
+ )
+ points.backGussetMid = new Point(measurements.seat / 4, backHeightReduced)
+
+ points.backGussetRight = points.backGussetLeft.flipX(points.backWaistMid)
+ points.backLegOpeningRight = points.backLegOpeningLeft.flipX(points.backWaistMid)
+ points.backWaistBandRight = points.backWaistBandLeft.flipX(points.backWaistMid)
+
+ points.backWaistBandMid = points.backWaistBandLeft
+ .shiftFractionTowards(points.backWaistBandRight, 0.5)
+ .shift(270, measurements.waistToUpperLeg * options.backDip)
+
+ /* Middle point for label */
+ points.backMidMid = points.backLegOpeningLeft.shiftFractionTowards(
+ points.backLegOpeningRight,
+ 0.5
+ )
+
+ // Create control points
+
+ /* Control point for waistband dip */
+ points.backWaistBandLeftCp1 = points.backWaistBandMid.shift(
+ 0,
+ points.backWaistBandMid.dx(points.backWaistBandLeft) / 3
+ )
+
+ /* Flip points to right side */
+ points.backWaistBandRightCp1 = points.backWaistBandLeftCp1.flipX(points.backWaistMid)
+
+ // Shape back coverage
+
+ /* Only have to do this on one side */
+ points.backLegOpeningCorner = utils.beamsIntersect(
+ points.backLegOpeningLeft,
+ points.backLegOpeningLeft.shift(180, points.backGussetLeft.dy(points.backLegOpeningLeft)),
+ points.backGussetLeft,
+ points.backGussetLeft.shift(270, points.backGussetLeft.dy(points.backLegOpeningLeft))
+ )
+
+ if (options.backExposure >= 0) {
+ /* If back exposure is high, like a thong style */
+ /* This controls the hip bit */
+ points.backLegOpeningLeftCp1 = points.backLegOpeningLeft.shiftFractionTowards(
+ points.backLegOpeningCorner,
+ options.backExposure
+ )
+ /* This controls the center bit */
+ points.backGussetLeftCp1 = points.backGussetLeft.shiftFractionTowards(
+ points.backWaistBandMid,
+ options.backExposure
+ )
+ points.backGussetLeft = points.backGussetLeft.shiftFractionTowards(
+ points.backGussetMid,
+ options.backExposure
+ ) // This narrows the back of the gusset
+ points.backGussetRight = points.backGussetLeft.flipX(points.backWaistMid)
+ } else {
+ /* If back exposure is low and flares out to cover more */
+ store.set('adjustedBackExposure', options.backExposure * store.get('adjustedLegOpening')) // flare depends on leg opening
+ /* This controls the hip bit */
+ points.backLegOpeningLeftCp1 = points.backLegOpeningLeft.shift(
+ -45,
+ store.get('adjustedBackExposure') * points.backWaistBandMid.dx(points.backWaistBandLeft)
+ )
+ /* This controls the taper to gusset */
+ points.backGussetLeftCp1 = points.backGussetLeft.shift(
+ 115,
+ store.get('adjustedBackExposure') * points.backWaistBandMid.dx(points.backWaistBandLeft)
+ )
+
+ /* center of the flare and its control points are on a line parallel to the backGussetLeft to backLegOpeningLeft line
+ * first, define the points on that line */
+ points.backFlare = points.backGussetLeft.shiftFractionTowards(points.backLegOpeningLeft, 0.5)
+ // points.backFlareCp1 = points.backGussetLeft.shiftFractionTowards(points.backLegOpeningLeft, 0.5 - store.get('adjustedBackExposure'))
+ points.backFlareCp1 = points.backGussetLeft.shiftFractionTowards(
+ points.backLegOpeningLeft,
+ 0.7
+ )
+ points.backFlareCp2 = points.backGussetLeft.shiftFractionTowards(
+ points.backLegOpeningLeft,
+ 0.3
+ )
+ /* then shift all three points outward */
+ points.backFlareLeft = points.backFlare.shift(
+ 215,
+ points.backWaistBandMid.dx(points.backWaistBandLeft) * store.get('adjustedBackExposure') * 2
+ )
+ points.backFlareLeftCp1 = points.backFlareCp1.shift(
+ 215,
+ points.backWaistBandMid.dx(points.backWaistBandLeft) * store.get('adjustedBackExposure') * 2
+ )
+ points.backFlareLeftCp2 = points.backFlareCp2.shift(
+ 215,
+ points.backWaistBandMid.dx(points.backWaistBandLeft) * store.get('adjustedBackExposure') * 2
+ )
+
+ /* Flip points to the right */
+
+ points.backFlareRight = points.backFlareLeft.flipX(points.backWaistBandMid)
+ points.backFlareRightCp1 = points.backFlareLeftCp1.flipX(points.backWaistMid)
+ points.backFlareRightCp2 = points.backFlareLeftCp2.flipX(points.backWaistMid)
+ }
+
+ /* Flip points to the right */
+
+ points.backLegOpeningRightCp1 = points.backLegOpeningLeftCp1.flipX(points.backWaistMid)
+ points.backGussetRightCp1 = points.backGussetLeftCp1.flipX(points.backWaistMid)
+
+ // Draw paths
+
+ if (options.backExposure >= 0) {
+ paths.seam = new Path()
+ .move(points.backWaistBandMid)
+ .curve(points.backWaistBandLeftCp1, points.backWaistBandLeft, points.backWaistBandLeft) // Waist band dip
+ .line(points.backLegOpeningLeft)
+ .curve(points.backLegOpeningLeftCp1, points.backGussetLeftCp1, points.backGussetLeft)
+ .line(points.backGussetMid)
+ .line(points.backGussetRight)
+ .curve(points.backGussetRightCp1, points.backLegOpeningRightCp1, points.backLegOpeningRight)
+ .line(points.backWaistBandRight)
+ .curve(points.backWaistBandRight, points.backWaistBandRightCp1, points.backWaistBandMid) // Waist band dip
+ .close()
+ .attr('class', 'fabric')
+ } else {
+ paths.seam = new Path()
+ .move(points.backWaistBandMid)
+ .curve(points.backWaistBandLeftCp1, points.backWaistBandLeft, points.backWaistBandLeft) // Waist band dip
+ .line(points.backLegOpeningLeft)
+ .curve(points.backLegOpeningLeftCp1, points.backFlareLeftCp1, points.backFlareLeft)
+ .curve(points.backFlareLeftCp2, points.backGussetLeftCp1, points.backGussetLeft)
+ .line(points.backGussetMid)
+ .line(points.backGussetRight)
+ .curve(points.backGussetRightCp1, points.backFlareRightCp2, points.backFlareRight)
+ .curve(points.backFlareRightCp1, points.backLegOpeningRightCp1, points.backLegOpeningRight)
+ .line(points.backWaistBandRight)
+ .curve(points.backWaistBandRight, points.backWaistBandRightCp1, points.backWaistBandMid) // Waist band dip
+ .close()
+ .attr('class', 'fabric')
+ }
+
+ // Store points for use in other parts
+
+ /* Store gusset points for use in gusset */
+
+ store.set('backGussetLeft', points.backGussetLeft)
+ store.set('backGussetRight', points.backGussetRight)
+
+ /* Store lengths for use in elastic */
+
+ paths.backLegOpening =
+ options.backExposure >= 0
+ ? new Path()
+ .move(points.backGussetRight)
+ .curve(
+ points.backGussetRightCp1,
+ points.backLegOpeningRightCp1,
+ points.backLegOpeningRight
+ )
+ .setHidden(true)
+ : new Path()
+ .move(points.backGussetRight)
+ .curve(points.backGussetRightCp1, points.backFlareRightCp2, points.backFlareRight)
+ .curve(
+ points.backFlareRightCp1,
+ points.backLegOpeningRightCp1,
+ points.backLegOpeningRight
+ )
+ .setHidden(true)
+ store.set('backLegOpeningLength', paths.backLegOpening.length())
+
+ paths.backWaistBand = new Path()
+ .move(points.backWaistBandRight)
+ .curve(points.backWaistBandRightCp1, points.backWaistBandLeftCp1, points.backWaistBandLeft)
+ .setHidden(true)
+ store.set('backWaistBandLength', paths.backWaistBand.length())
+
+ // Complete?
+ if (complete) {
+ if (sa) {
+ paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa')
+ }
+ }
+
+ macro('title', {
+ at: points.backMidMid,
+ nr: 2,
+ title: 'back',
+ })
+
+ macro('grainline', {
+ from: points.backGussetMid,
+ to: points.backGussetMid.shiftFractionTowards(points.backWaistBandMid, 0.4),
+ })
+
+ points.scaleboxAnchor = points.scalebox = points.backMidMid.shift(90, -50)
+ macro('miniscale', { at: points.scalebox })
+
+ // Paperless?
+ if (paperless) {
+ macro('hd', {
+ from: points.backWaistBandRight,
+ to: points.backWaistBandLeft,
+ y: points.backWaistBandRight.y + sa - 15,
+ })
+ macro('hd', {
+ from: points.backLegOpeningRight,
+ to: points.backLegOpeningLeft,
+ y: points.backLegOpeningRight.y + sa - 15,
+ })
+ macro('hd', {
+ from: points.backGussetLeft,
+ to: points.backGussetRight,
+ y: points.backGussetLeft.y + sa + 15,
+ })
+ macro('vd', {
+ from: points.backWaistBandMid,
+ to: points.backGussetMid,
+ x: points.backWaistBandMid.x + sa + 15,
+ })
+ if (options.backExposure >= 0) {
+ macro('pd', {
+ path: new Path()
+ .move(points.backGussetRight)
+ .curve(
+ points.backGussetRightCp1,
+ points.backLegOpeningRightCp1,
+ points.backLegOpeningRight
+ ),
+ d: 15,
+ })
+ } else {
+ macro('pd', {
+ path: new Path()
+ .move(points.backGussetRight)
+ .curve(points.backGussetRightCp1, points.backFlareRightCp2, points.backFlareRight)
+ .curve(
+ points.backFlareRightCp1,
+ points.backLegOpeningRightCp1,
+ points.backLegOpeningRight
+ ),
+ d: 15,
+ })
+ }
+ }
+
+ return part
+ },
+}
diff --git a/designs/unice/src/elastic.mjs b/designs/unice/src/elastic.mjs
new file mode 100644
index 00000000000..ead702d83ae
--- /dev/null
+++ b/designs/unice/src/elastic.mjs
@@ -0,0 +1,39 @@
+import { gusset } from './gusset.mjs'
+
+export const elastic = {
+ name: 'unice.elastic',
+ options: {
+ elasticStretch: { pct: 8, min: 5, max: 15, menu: 'fit' },
+ },
+ after: gusset,
+ draft: ({ options, Point, points, Path, paths, store, utils, units, sa, part }) => {
+ // Stretch utility method
+ store.set('elasticScale', utils.stretchToScale(options.elasticStretch))
+
+ // Design pattern here
+ const legOpeningLength =
+ store.get('frontLegOpeningLength') +
+ store.get('backLegOpeningLength') +
+ store.get('gussetSideLength')
+ const waistBandLength = store.get('frontWaistBandLength') + store.get('backWaistBandLength')
+
+ points.elasticInfo = new Point(0, 0)
+ .attr('data-text', 'cutTwoPiecesOfElasticToFinishTheLegOpenings')
+ .attr('data-text', ':')
+ .attr('data-text', units(legOpeningLength * store.get('elasticScale') + 2 * sa))
+ .attr('data-text', '\n')
+ .attr('data-text', 'cutOnePieceOfElasticToFinishTheWaistBand')
+ .attr('data-text', ':')
+ .attr('data-text', units(waistBandLength * store.get('elasticScale') + 2 * sa))
+
+ // Draw a box around the text, so the part shows up correctly.
+ paths.box = new Path()
+ .move(new Point(-10, -10))
+ .line(new Point(-10, 15))
+ .line(new Point(200, 15))
+ .line(new Point(200, -10))
+ .close()
+
+ return part
+ },
+}
diff --git a/designs/unice/src/front.mjs b/designs/unice/src/front.mjs
new file mode 100644
index 00000000000..fd4250b08f7
--- /dev/null
+++ b/designs/unice/src/front.mjs
@@ -0,0 +1,340 @@
+import { pluginBundle } from '@freesewing/plugin-bundle'
+
+export const front = {
+ name: 'unice.front',
+ measurements: ['waist', 'seat', 'waistToSeat', 'waistToUpperLeg', 'hips', 'waistToHips'],
+ optionalMeasurements: ['crossSeam', 'crossSeamFront'],
+ options: {
+ gussetShift: 0.015, // fraction of seat circumference - could be an advanced option?
+ gussetWidth: { pct: 7.2, min: 2, max: 12, menu: 'fit' }, // Gusset width in relation to waist-to-upperleg
+ gussetLength: { pct: 12.7, min: 10, max: 16, menu: 'fit' }, // Gusset length in relation to seat
+ fabricStretchX: { pct: 15, min: 0, max: 100, menu: 'fit' }, // horizontal stretch (range set wide for beta testing)
+ fabricStretchY: { pct: 0, min: 0, max: 100, menu: 'fit' }, // vertical stretch (range set wide for beta testing)
+ rise: { pct: 60, min: 30, max: 100, menu: 'style' }, // extending rise beyond 100% would require adapting paths.sideLeft!
+ legOpening: { pct: 45, min: 5, max: 85, menu: 'style' },
+ frontDip: { pct: 5.0, min: -5, max: 15, menu: 'style' },
+ taperToGusset: { pct: 70, min: 5, max: 100, menu: 'style' },
+ // booleans
+ useCrossSeam: { bool: true, menu: 'fit' },
+ adjustStretch: { bool: true, menu: 'fit' }, // to not stretch fabric to the limits
+ },
+ plugins: [pluginBundle],
+ draft: ({
+ utils,
+ store,
+ sa,
+ Point,
+ points,
+ Path,
+ paths,
+ options,
+ measurements,
+ complete,
+ paperless,
+ macro,
+ part,
+ }) => {
+ // Stretch utility method
+
+ // Use stretch inputs to calculate four different scale factors: horizontal/vertical and 'regular'/'reduced', depending on direction of the tension
+ // xScale: for parts that go across the body (= stretched horizontally)
+ // xScaleReduced: parts that are not under (horizontal) tension, e.g. the gusset
+ // yScale: for parts which are stretched vertically but not horizontally (anything below leg opening)
+ // yScaleReduced: parts which are already under horizontal stretch, which limits vertical stretch
+
+ if (options.adjustStretch) {
+ // roughly 15% of stretch is reserved for comfort
+ // horizontal: first, 'regular' stretch (for parts that go across the body)
+ if (options.fabricStretchX < 0.30) {
+ // subtract 15, but never go below 0
+ store.set('xScale', utils.stretchToScale(Math.max(0, options.fabricStretchX - 0.15)))
+ } else {
+ store.set('xScale', utils.stretchToScale(options.fabricStretchX / 2))
+ // rough approximation of rule of thumb quoted in Sanne's July 29, 2021 showcase
+ }
+ // use half of whatever the regular stretch is (no util available, convert from stretch to fraction manually
+ store.set('xScaleReduced', (1 + store.get('xScale')) / 2)
+
+ // vertical:
+ if (options.fabricStretchY < 0.30) {
+ // subtract 15, but never go below 0
+ store.set('yScale', utils.stretchToScale(Math.max(0, options.fabricStretchY - 0.15)))
+ } else {
+ store.set('yScale', utils.stretchToScale(options.fabricStretchY / 2))
+ // rough approximation of rule of thumb quoted in Sanne's July 29, 2021 showcase
+ }
+ // reduced vertical stretch calculated below, same as for non-adjusted case
+ } else {
+ // in order: regular, then reduced horizontal stretch, followed by regular vertical stretch
+ store.set('xScale', utils.stretchToScale(options.fabricStretchX))
+ store.set('xScaleReduced', utils.stretchToScale(options.fabricStretchX / 2))
+ store.set('yScale', utils.stretchToScale(options.fabricStretchY))
+ }
+ if (options.fabricStretchY < 0.20) {
+ store.set('yScaleReduced', 1)
+ } else {
+ // reduced yScale gradually increases from equivalent of stretch 0 to 5%, then cuts off (uses third-order polynomial)
+ // function to approximate Sanne's guidelines given in Discord (roughly 2.5% for stretch 30-40%, 5% above that)
+ store.set(
+ 'yScaleReduced',
+ utils.stretchToScale(Math.min(0.05, 6.25 * Math.pow(options.fabricStretchY - 0.2, 3)))
+ )
+ }
+
+ // // temporarily overrule yScale and yScaleReduced
+ // store.set('yScale',1)
+ // store.set('yScaleReduced',1)
+
+ // // Part definition starts here
+
+ // determine height of front part: use cross seam (and cross seam front) if selected and available
+ // NOTE: neither crossSeam not frontHeight are adjusted for (vertical) stretch
+ if (options.useCrossSeam && measurements.crossSeam) {
+ store.set('crossSeam', measurements.crossSeam)
+ } else {
+ // use original approximation: front and back are roughly waistToUpperLeg high, plus gusset length
+ store.set(
+ 'crossSeam',
+ measurements.waistToUpperLeg * (1 + options.backToFrontLength) +
+ options.gussetLength * measurements.seat
+ )
+ }
+ // optionally use crossSeamFront to determine relative length of front and back
+ // this does not account for vertical stretch yet
+ if (options.useCrossSeam && measurements.crossSeamFront) {
+ // subtract half the gusset length from cross seam front, and an additional 3.5% of the seat circumference to move the gusset upward (to match commercial panties)
+ store.set(
+ 'frontHeight',
+ measurements.crossSeamFront -
+ measurements.seat * (0.5 * options.gussetLength + options.gussetShift)
+ )
+ } else {
+ // subtract gusset length, divide by roughly 2
+ store.set(
+ 'frontHeight',
+ (store.get('crossSeam') - options.gussetLength * measurements.seat) /
+ (1 + options.backToFrontLength)
+ )
+ }
+
+ // Create points
+
+ // side seam is on a line from upper leg to seat to hips (optional?) to waist
+ points.frontWaistMid = new Point(measurements.seat / 4, 0)
+ points.frontWaistLeft = new Point(
+ measurements.seat / 4 - (measurements.waist / 4) * store.get('xScale'),
+ 0
+ )
+ points.frontSeatLeft = new Point(
+ measurements.seat / 4 - (measurements.seat / 4) * store.get('xScale'),
+ measurements.waistToSeat * store.get('yScaleReduced')
+ )
+ points.frontUpperLegLeft = new Point(
+ measurements.seat / 4 - (measurements.seat / 4) * store.get('xScale'), // assume same circ. as seat
+ measurements.waistToUpperLeg * store.get('yScaleReduced')
+ )
+ points.frontHipLeft = new Point(
+ measurements.seat / 4 - (measurements.hips / 4) * store.get('xScale'),
+ measurements.waistToHips * store.get('yScaleReduced')
+ )
+
+ // use these points to define an invisible path
+ paths.sideLeft = new Path()
+ .move(points.frontUpperLegLeft)
+ .line(points.frontSeatLeft)
+ .line(points.frontHipLeft)
+ .line(points.frontWaistLeft)
+ .setHidden(true) // only show when debugging
+
+ /* Waist band is somewhere on the sideLeft path */
+ points.frontWaistBandLeft = paths.sideLeft.shiftFractionAlong(options.rise)
+ points.frontWaistBandRight = points.frontWaistBandLeft.flipX(points.frontWaistMid)
+ points.frontWaistBandMid = points.frontWaistBandLeft
+ .shiftFractionTowards(points.frontWaistBandRight, 0.5)
+ .shift(270, measurements.waistToUpperLeg * options.frontDip) /* Waist band dip */
+
+ /* Leg opening is also on the sideLeft path, and cannot be higher than rise */
+ /* Minimum side seam length is defined as 3.5% of the sideLeft path (which is at least waistToUpperLeg long) */
+ store.set('adjustedLegOpening', Math.min(options.legOpening, options.rise - 0.035)) // TODO: account for rise having a different domain
+
+ points.frontLegOpeningLeft = paths.sideLeft.shiftFractionAlong(store.get('adjustedLegOpening'))
+ points.frontLegOpeningRight = points.frontLegOpeningLeft.flipX(points.frontWaistMid) // Waist band low point
+
+ // calculate the actual front height, using yScale above and yScaleReduced below leg opening
+ store.set('frontHeightAbove', points.frontWaistLeft.dy(points.frontLegOpeningLeft))
+
+ var frontHeightBelow
+ frontHeightBelow =
+ store.get('yScale') *
+ (store.get('frontHeight') - store.get('frontHeightAbove') / store.get('yScaleReduced'))
+
+ var frontHeightReduced
+ frontHeightReduced = frontHeightBelow + store.get('frontHeightAbove')
+
+ // gusset width uses modified xScale (barely stretches) and depends on waistToUpperLeg - least sensitive to girth
+ points.frontGussetLeft = new Point(
+ measurements.seat / 4 -
+ measurements.waistToSeat * options.gussetWidth * store.get('xScaleReduced') * 2.2,
+ frontHeightReduced
+ )
+ points.frontGussetMid = new Point(measurements.seat / 4, frontHeightReduced)
+
+ /* Flip points to right side */
+ points.frontGussetRight = points.frontGussetLeft.flipX(points.frontWaistMid)
+ points.frontHipRight = points.frontSeatLeft.flipX(points.frontWaistMid)
+ points.frontWaistRight = points.frontWaistLeft.flipX(points.frontWaistMid)
+
+ console.log('points', points)
+
+ /* Middle point for label */
+ points.frontMidMid = points.frontLegOpeningLeft.shiftFractionTowards(
+ points.frontLegOpeningRight,
+ 0.5
+ )
+
+ // Create control points
+
+ /* Control points for leg opening curves */
+ points.frontLegOpeningLeftCp1 = points.frontLegOpeningLeft.shift(
+ 180,
+ points.frontGussetLeft.dy(points.frontLegOpeningLeft) / 3
+ )
+
+ /* Control point above gusset moves higher as taperToGusset (= front exposure) increases, but is limited by both the leg opening (allow minimal arching only) and the rise (leg opening must not intersect the waist band) */
+ points.frontGussetLeftCp1 = points.frontGussetLeft.shift(
+ 270,
+ Math.max(
+ Math.max(
+ (points.frontGussetLeft.dy(points.frontWaistMid) * options.taperToGusset) / 2,
+ points.frontGussetLeft.dy(points.frontLegOpeningLeft) * 2
+ ),
+ points.frontGussetLeft.dy(points.frontWaistBandMid)
+ )
+ )
+
+ /* Control point for waistband dip */
+ points.frontWaistBandLeftCp1 = points.frontWaistBandMid.shift(
+ 0,
+ points.frontWaistBandMid.dx(points.frontWaistBandLeft) / 3
+ )
+
+ /* Flip control points to right side */
+ points.frontGussetRightCp1 = points.frontGussetLeftCp1.flipX(points.frontWaistMid)
+ points.frontLegOpeningRightCp1 = points.frontLegOpeningLeftCp1.flipX(points.frontWaistMid)
+ points.frontWaistBandRightCp1 = points.frontWaistBandLeftCp1.flipX(points.frontWaistMid)
+
+ // Draw paths
+
+ paths.seam = new Path()
+ .move(points.frontWaistBandMid)
+ .curve(points.frontWaistBandLeftCp1, points.frontWaistBandLeft, points.frontWaistBandLeft) // Waist band dip
+ .line(points.frontLegOpeningLeft)
+ .curve(points.frontLegOpeningLeftCp1, points.frontGussetLeftCp1, points.frontGussetLeft)
+ .line(points.frontGussetMid)
+ .line(points.frontGussetRight)
+ .curve(
+ points.frontGussetRightCp1,
+ points.frontLegOpeningRightCp1,
+ points.frontLegOpeningRight
+ )
+ .line(points.frontWaistBandRight)
+ .curve(points.frontWaistBandRight, points.frontWaistBandRightCp1, points.frontWaistBandMid) // Waist band dip
+ .close()
+ .attr('class', 'fabric')
+
+ // Store points for use in other parts
+
+ /* Store side seam points for use in back */
+
+ store.set('sideSeamWaist', points.frontWaistBandLeft)
+ store.set('sideSeamHip', points.frontLegOpeningLeft)
+
+ /* Store gusset points for use in gusset */
+
+ store.set('frontGussetLeft', points.frontGussetLeft)
+ store.set('frontGussetRight', points.frontGussetRight)
+ store.set('frontGussetMid', points.frontGussetMid)
+
+ /* Store lengths for use in elastic */
+
+ paths.frontLegOpening = new Path()
+ .move(points.frontGussetRight)
+ .curve(
+ points.frontGussetRightCp1,
+ points.frontLegOpeningRightCp1,
+ points.frontLegOpeningRight
+ )
+ .setHidden(true)
+ store.set('frontLegOpeningLength', paths.frontLegOpening.length())
+
+ paths.frontWaistBand = new Path()
+ .move(points.frontWaistBandRight)
+ .curve(points.frontWaistBandRightCp1, points.frontWaistBandLeftCp1, points.frontWaistBandLeft)
+ .setHidden(true)
+ store.set('frontWaistBandLength', paths.frontWaistBand.length())
+
+ // Complete?
+ if (complete) {
+ if (sa) {
+ paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa')
+ }
+ }
+
+ macro('title', {
+ at: points.frontMidMid,
+ nr: 1,
+ title: 'front',
+ })
+
+ macro('grainline', {
+ from: points.frontGussetMid,
+ to: points.frontGussetMid.shiftFractionTowards(points.frontWaistBandMid, 0.5),
+ })
+
+ // Paperless?
+ if (paperless) {
+ macro('hd', {
+ from: points.frontWaistBandRight,
+ to: points.frontWaistBandLeft,
+ y: points.frontWaistBandRight.y + sa - 15,
+ })
+ macro('hd', {
+ from: points.frontLegOpeningRight,
+ to: points.frontLegOpeningLeft,
+ y: points.frontLegOpeningRight.y + sa - 15,
+ })
+ macro('hd', {
+ from: points.frontGussetLeft,
+ to: points.frontGussetRight,
+ y: points.frontGussetLeft.y + sa + 15,
+ })
+ macro('vd', {
+ from: points.frontWaistBandMid,
+ to: points.frontGussetMid,
+ x: points.frontWaistBandMid.x + sa + 15,
+ })
+ macro('ld', {
+ from: points.frontWaistBandLeft,
+ to: points.frontLegOpeningLeft,
+ d: points.frontWaistBandLeft.y + sa - 15,
+ })
+ macro('pd', {
+ path: new Path()
+ .move(points.frontGussetRight)
+ .curve(
+ points.frontGussetRightCp1,
+ points.frontLegOpeningRightCp1,
+ points.frontLegOpeningRight
+ ),
+ d: 15,
+ })
+ /* macro('vd', {
+ from: points.frontWaistBandLeft,
+ to: points.frontWaistBandMid,
+ x: points.frontWaistBandMid.x + sa + 15,
+ }) */
+ }
+
+ return part
+ },
+}
diff --git a/designs/unice/src/gusset.mjs b/designs/unice/src/gusset.mjs
new file mode 100644
index 00000000000..d620c8f9607
--- /dev/null
+++ b/designs/unice/src/gusset.mjs
@@ -0,0 +1,113 @@
+import { back } from './back.mjs'
+
+export const gusset = {
+ name: 'unice.gusset',
+ measurements: ['waist', 'seat', 'waistToSeat', 'waistToUpperLeg', 'hips', 'waistToHips'],
+ optionalMeasurements: ['crossSeam', 'crossSeamFront'],
+ options: {
+ gussetShift: 0.015, // fraction of seat circumference - could be an advanced option?
+ gussetWidth: { pct: 7.2, min: 2, max: 12, menu: 'fit' }, // Gusset width in relation to waist-to-upperleg
+ gussetLength: { pct: 12.7, min: 10, max: 16, menu: 'fit' }, // Gusset length in relation to seat
+ fabricStretch: { pct: 15, min: 0, max: 100, menu: 'fit' }, // used in Ursula
+ fabricStretchX: { pct: 15, min: 0, max: 100, menu: 'fit' }, // horizontal stretch (range set wide for beta testing)
+ fabricStretchY: { pct: 0, min: 0, max: 100, menu: 'fit' }, // vertical stretch (range set wide for beta testing)
+ rise: { pct: 60, min: 30, max: 100, menu: 'style' }, // extending rise beyond 100% would require adapting paths.sideLeft!
+ legOpening: { pct: 45, min: 5, max: 85, menu: 'style' },
+ frontDip: { pct: 5.0, min: -5, max: 15, menu: 'style' },
+ taperToGusset: { pct: 70, min: 5, max: 100, menu: 'style' },
+ // booleans
+ useCrossSeam: { bool: true, menu: 'fit' },
+ },
+ after: back,
+ draft: ({
+ store,
+ sa,
+ Point,
+ points,
+ Path,
+ paths,
+ options,
+ measurements,
+ complete,
+ paperless,
+ macro,
+ part,
+ }) => {
+ // Design pattern here
+ var yScaleDoubleLayer
+ yScaleDoubleLayer = (1 + store.get('yScale')) / 2 // double layer of fabric stretches half as much
+
+ // Create points
+ points.frontGussetLeft = new Point(store.get('frontGussetLeft').x, 0)
+ points.backGussetLeft = new Point(
+ store.get('backGussetLeft').x,
+ measurements.seat * options.gussetLength * yScaleDoubleLayer
+ )
+ points.frontGussetRight = new Point(store.get('frontGussetRight').x, 0)
+ points.backGussetRight = new Point(
+ store.get('backGussetRight').x,
+ measurements.seat * options.gussetLength * yScaleDoubleLayer
+ )
+
+ // Create control points
+ points.gussetCp1 = points.frontGussetLeft
+ .shiftFractionTowards(points.backGussetLeft, 0.5)
+ .shift(180, points.frontGussetRight.x / -15)
+
+ // Flip points to right side
+ points.gussetCp2 = points.gussetCp1.flipX(store.get('frontGussetMid'))
+
+ // Create point for title
+ points.frontMidMid = points.gussetCp1.shiftFractionTowards(points.gussetCp2, 0.5)
+
+ /* Store lengths for use in elastic */
+ paths.gussetLegOpening = new Path()
+ .move(points.backGussetRight)
+ .curve(points.backGussetRight, points.gussetCp2, points.frontGussetRight)
+ .setHidden(true)
+ store.set('gussetSideLength', paths.gussetLegOpening.length())
+
+ // Draw paths
+ paths.seam = new Path()
+ .move(points.frontGussetLeft)
+ .curve(points.gussetCp1, points.backGussetLeft, points.backGussetLeft)
+ .line(points.backGussetRight)
+ .curve(points.backGussetRight, points.gussetCp2, points.frontGussetRight)
+ .line(points.frontGussetLeft) // Without this, doesn't generate seam allowance
+ .close()
+ .attr('class', 'fabric')
+
+ // Complete?
+ if (complete) {
+ if (sa) {
+ paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa')
+ }
+ macro('title', {
+ at: points.frontMidMid,
+ nr: 3,
+ title: 'gusset',
+ })
+ }
+
+ // Paperless?
+ if (paperless) {
+ macro('hd', {
+ from: points.frontGussetLeft,
+ to: points.frontGussetRight,
+ y: points.frontGussetLeft.y + sa + 15,
+ })
+ macro('hd', {
+ from: points.backGussetLeft,
+ to: points.backGussetRight,
+ y: points.backGussetLeft.y + sa + 15,
+ })
+ macro('vd', {
+ from: points.frontGussetRight,
+ to: points.backGussetRight,
+ x: points.frontGussetRight.x + sa + 15,
+ })
+ }
+
+ return part
+ },
+}
diff --git a/designs/unice/src/index.mjs b/designs/unice/src/index.mjs
new file mode 100644
index 00000000000..035a9359450
--- /dev/null
+++ b/designs/unice/src/index.mjs
@@ -0,0 +1,15 @@
+import { Design } from '@freesewing/core'
+import { front } from './front.mjs'
+import { back } from './back.mjs'
+import { gusset } from './gusset.mjs'
+import { elastic } from './elastic.mjs'
+import { data } from '../data.mjs'
+
+// Setup our new design
+const Unice = new Design({
+ data,
+ parts: [front, back, gusset, elastic],
+})
+
+// Named exports
+export { front, back, gusset, elastic, Unice }
diff --git a/designs/examples/tests/shared.test.mjs b/designs/unice/tests/shared.test.mjs
similarity index 76%
rename from designs/examples/tests/shared.test.mjs
rename to designs/unice/tests/shared.test.mjs
index 88702efb737..8ddc94ac54a 100644
--- a/designs/examples/tests/shared.test.mjs
+++ b/designs/unice/tests/shared.test.mjs
@@ -1,5 +1,5 @@
// This file is auto-generated | Any changes you make will be overwritten.
-import { Examples } from '../src/index.mjs'
+import { Unice } from '../src/index.mjs'
// Shared tests
import { testPatternConfig } from '../../../tests/designs/config.mjs'
@@ -7,10 +7,10 @@ import { testPatternDrafting } from '../../../tests/designs/drafting.mjs'
//import { testPatternSampling } from '../../../tests/designs/sampling.mjs'
// Test config
-testPatternConfig(Examples)
+testPatternConfig(Unice)
// Test drafting - Change the second parameter to `true` to log errors
-testPatternDrafting(Examples, false)
+testPatternDrafting(Unice, false)
// Test sampling - Change the second parameter to `true` to log errors
-//testPatternSampling(Examples, false)
+//testPatternSampling(Unice, false)
diff --git a/markdown/dev/reference/api/design/en.md b/markdown/dev/reference/api/design/en.md
index 7922913be70..2856f0f9946 100644
--- a/markdown/dev/reference/api/design/en.md
+++ b/markdown/dev/reference/api/design/en.md
@@ -3,14 +3,21 @@ title: Design
order: 10
---
-The `Design` named export in FreeSewing's core library serves a single purpose:
-To create new pattern designs.
+The `Design` named export in FreeSewing's core library is a contructor that
+creates new pattern designs.
-## Design constructor
+## Signature
```js
-import { Design } from "@freesewing/core"
+Pattern Design({
+ array parts,
+ object data
+})
+```
+## Example
+
+```js
const Sorcha = new Design({
// design configuration here
})
@@ -21,9 +28,8 @@ It takes a single argument, an object holding the design's configuration.
## Design configuration
-
Since a design's configuration is managed at the part level,
-the Design constructor only expects a `parts` attribute that should
+the Design configuration object only requires a `parts` property that should
hold an array of parts to include in the Design.
```js
@@ -44,14 +50,29 @@ to [the Store](/reference/api/store).
const Sorcha = new Design({
parts: [ front, back, sleeve ],
data: {
- // Your custom data here
+ version: 3,
+ price: 12,
+ currency: 'euro'
}
})
```
-
+## Notes
-This Design constructor is a _super-constructor_.
+
+The Design constructor is a _super-constructor_.
It will return a constructor method that will a pattern based on your design.
-
+## Properties
+
+In addition to the returned constructor method, an instantiated Design object
+also provides the following properties:
+
+### Design.designConfig
+
+This holds the design configuration as passed to the Design constructor.
+
+### Design.patternConfig
+
+Holds the resolved pattern configuration based on the configuration passed to the Design constructor.
+
diff --git a/markdown/dev/reference/api/path/_curve/en.md b/markdown/dev/reference/api/path/_curve/en.md
index c009a9d41dc..07790435a61 100644
--- a/markdown/dev/reference/api/path/_curve/en.md
+++ b/markdown/dev/reference/api/path/_curve/en.md
@@ -17,24 +17,24 @@ Path path._curve(Point cp2, Point to)
## Example
-
+
```js
({ Point, points, Path, paths, part }) => {
points.from = new Point(5, 20);
- points.cp2 = new Point(60, 30);
+ points.cp2 = new Point(60, 50);
points.to = new Point(90, 20);
paths.line = new Path()
.move(points.from)
._curve(points.cp2, points.to)
- .attr("data-text", "Path._curve()")
- .attr("data-text-class", "text-sm center fill-note");
+ .setText("Path._curve()", "text-sm center fill-note")
+ .attr("data-text-dy", -1)
return part
}
```
-
+
## Notes
diff --git a/markdown/dev/reference/api/path/addclass/en.md b/markdown/dev/reference/api/path/addclass/en.md
index 750883efb74..d8c0d0bba40 100644
--- a/markdown/dev/reference/api/path/addclass/en.md
+++ b/markdown/dev/reference/api/path/addclass/en.md
@@ -4,31 +4,17 @@ title: Path.addClass()
The `Path.addClass()` method adds a CSS class to the path.
+## Signature
+
```js
Path path.addClass(string className)
```
-This method is chainable as it returns the `Path` object
+This method is chainable as it returns the `Path` object
-
-
-###### This method exists to save you some typing
-
-Note that the two following calls yield the same result:
-
-```js
-path.attr('class', 'fabric')
-path.addClass('fabric')
-```
-
-So the only purpose of this method is to save your some typing.
-
-
-
-
-Example of the Path.addClass() method
-
+## Example
+
```js
({ Point, points, Path, paths, part }) => {
@@ -43,3 +29,15 @@ Example of the Path.addClass() method
return part
}
```
+
+
+## Notes
+
+The main purpose of this method is to save your some typing,
+as the two following calls yield the same result:
+
+```js
+path.attr('class', 'fabric')
+path.addClass('fabric')
+```
+
diff --git a/markdown/dev/reference/api/path/addtext/en.md b/markdown/dev/reference/api/path/addtext/en.md
new file mode 100644
index 00000000000..92d455612f7
--- /dev/null
+++ b/markdown/dev/reference/api/path/addtext/en.md
@@ -0,0 +1,47 @@
+---
+title: Path.addText()
+---
+
+The `Path.addText()` method adds text to the path.
+
+## Signature
+
+```js
+Path path.addText(string text, string className)
+```
+
+The second argument will optionally be used to set the CSS class for the text.
+
+This method is chainable as it returns the `Path` object
+
+## Example
+
+
+```js
+({ Point, points, Path, paths, part }) => {
+ points.from = new Point(5, 10)
+ points.to = new Point(95, 10)
+
+ paths.line = new Path()
+ .move(points.from)
+ .line(points.to)
+ .addText('FreeSewing rocks')
+
+ return part
+}
+```
+
+
+## Notes
+
+The main purpose of this method is to save your some typing,
+as the two following calls yield the same result:
+
+```js
+path.attr('data-text', 'Hello')
+path.addText('Hello')
+```
+
+The difference with [Path.setText()](/reference/api/path/addtext) is that this
+method will add to the existing text whereas `Path.setText()` will overwrite
+existing text on the path,
diff --git a/markdown/dev/reference/api/path/aspathstring/en.md b/markdown/dev/reference/api/path/aspathstring/en.md
index 17a4d0412c9..047ecb05f4b 100644
--- a/markdown/dev/reference/api/path/aspathstring/en.md
+++ b/markdown/dev/reference/api/path/aspathstring/en.md
@@ -5,13 +5,13 @@ title: Path.asPathString()
This `Path.asPathString()` returs the path as a string that can be used
as the `d` attribute for an SVG `path` element.
+## Signature
+
```js
string path.asPathString()
```
-
+## Notes
This method is mostly aimed at people looking to implement their own rendering
methods, or integrate with SVG processing tools.
-
-
diff --git a/markdown/dev/reference/api/path/attr/en.md b/markdown/dev/reference/api/path/attr/en.md
index 9e3e087e97c..eba65e00d89 100644
--- a/markdown/dev/reference/api/path/attr/en.md
+++ b/markdown/dev/reference/api/path/attr/en.md
@@ -8,6 +8,8 @@ It calls `this.attributes.add()` under the hood, and returns the Path object.
If the third parameter is set to `true` it will call `this.attributes.set()`
instead, thereby overwriting the value of the attribute.
+## Signature
+
```js
Path path.attr(
string name,
@@ -18,31 +20,35 @@ Path path.attr(
This method is chainable as it returns the `Path` object
-
-Example of the Path.attr() method
-
+## Example
+
```js
({ Point, points, Path, paths, part }) => {
- points.from = new Point(10, 50);
- points.cp1 = new Point(40, 10);
- points.cp2 = new Point(90, 30);
- points.to = new Point(50, 90);
+ points.from = new Point(10, 20);
+ points.cp1 = new Point(20, -10);
+ points.cp2 = new Point(50, 50);
+ points.to = new Point(70, 20);
paths.example = new Path()
.move(points.from)
.curve(points.cp1, points.cp2, points.to)
- .addClass("canvas")
- .attr("data-text", "freesewingIsMadeByJoostDeCockAndContributors")
- .attr("data-text-class", "text-xs center");
+ .setClass("canvas")
+ .setText("FreeSewing rocks", "text-xs center")
return part
+}
```
+
-
-Methods like `addClass`, `setClass`, `addCircle`, `setCircle`, `adddText`, and `setText`
+## Notes
+
+Methods like
+[`Path.addClass`](/reference/api/path/addclass),
+[`Path.setClass`](/reference/api/path/setclass),
+[`Path.adddText`](/reference/api/path/addtext), and
+[`Path.setText`](/reference/api/path/settext)
all call this method under the hood.
-
diff --git a/markdown/dev/reference/api/path/bbox/en.md b/markdown/dev/reference/api/path/bbox/en.md
index 1b16ac663a7..3c2cf3241ab 100644
--- a/markdown/dev/reference/api/path/bbox/en.md
+++ b/markdown/dev/reference/api/path/bbox/en.md
@@ -5,6 +5,8 @@ title: Path.bbox()
The `Path.bbox()` method returns an object describing the bounding box of a path.
In other words, it gives you a rectangle the Path fits in.
+## Signature
+
```js
object path.bbox()
```
@@ -18,8 +20,6 @@ It returns an object with a signature like this:
}
```
-
+## Notes
This method is mostly aimed at people looking to implement their own layout solution.
-
-
diff --git a/markdown/dev/reference/api/path/clone/en.md b/markdown/dev/reference/api/path/clone/en.md
index 1c750154139..158935ef4d0 100644
--- a/markdown/dev/reference/api/path/clone/en.md
+++ b/markdown/dev/reference/api/path/clone/en.md
@@ -4,30 +4,36 @@ title: Path.clone()
The `Path.clone()` method returns a new `Path` object that is a deep copy of this path.
+## Signature
+
```js
Path path.clone()
```
-
-Example of the Path.clone() method
+## Example
+
+
+```js
+({ Point, points, Path, paths, part }) => {
+
+ points.A = new Point(45, 60);
+ points.B = new Point(10, 30);
+ points.BCp2 = new Point(40, 20);
+ points.C = new Point(90, 30);
+ points.CCp1 = new Point(50, -30);
+
+ paths.example = new Path()
+ .move(points.A)
+ .line(points.B)
+ .curve(points.BCp2, points.CCp1, points.C);
+
+ paths.clone = paths.example
+ .clone()
+ .setClass("note lashed stroke-xl")
+ .attr("style", "stroke-opacity: 0.5");
+
+ return part
+}
+```
-```js
-let { Point, points, Path, paths } = part.shorthand();
-
-points.A = new Point(45, 60);
-points.B = new Point(10, 30);
-points.BCp2 = new Point(40, 20);
-points.C = new Point(90, 30);
-points.CCp1 = new Point(50, -30);
-
-paths.example = new Path()
- .move(points.A)
- .line(points.B)
- .curve(points.BCp2, points.CCp1, points.C);
-
-paths.clone = paths.example
- .clone()
- .attr("class", "note lashed stroke-l")
- .attr("style", "stroke-opacity: 0.5");
-```
diff --git a/markdown/dev/reference/api/path/close/en.md b/markdown/dev/reference/api/path/close/en.md
index db3e3b7a738..3cddea95219 100644
--- a/markdown/dev/reference/api/path/close/en.md
+++ b/markdown/dev/reference/api/path/close/en.md
@@ -1,29 +1,36 @@
---
-title: close()
+title: Path.close()
---
+The `Path.close()` method closes a path by drawing a straight line from the current position to the path's start.
+
+## Signature
+
```js
Path path.close()
```
-Closes a path by drawing a straight line from the current position to the path's start.
+This method is chainable as it returns the `Path` object
-
-Example of the Path.close() method
+## Example
+
+
+```js
+({ Point, points, Path, paths, part }) => {
+
+ points.from = new Point(10, 20)
+ points.cp2 = new Point(60, 30)
+ points.to = new Point(90, 20)
+
+ paths.line = new Path()
+ .move(points.from)
+ ._curve(points.cp2, points.to)
+ .close()
+ .reverse() // To keep text from being upside-down
+ .setText('Path._close()', 'text-sm right fill-note')
+
+ return part
+}
+```
-```js
-let { Point, points, Path, paths } = part.shorthand();
-
-points.from = new Point(10, 20);
-points.cp2 = new Point(60, 30);
-points.to = new Point(90, 20);
-
-paths.line = new Path()
- .move(points.from)
- ._curve(points.cp2, points.to)
- .close()
- .reverse() // To keep text from being upside-down
- .attr("data-text", "Path._close()")
- .attr("data-text-class", "text-sm right fill-note");
-```
diff --git a/markdown/dev/reference/api/path/curve/en.md b/markdown/dev/reference/api/path/curve/en.md
index 22ce7ba5485..825450ebd22 100644
--- a/markdown/dev/reference/api/path/curve/en.md
+++ b/markdown/dev/reference/api/path/curve/en.md
@@ -1,28 +1,36 @@
---
-title: curve()
+title: Path.curve()
---
+The `Path.curve()` method draws a cubic Bezier curve from the current position
+via two control points to a given endpoint.
+
+## Signature
+
```js
Path path.curve(Point cp1, Point cp2, Point to)
```
-Draws a cubic Bezier curve from the current position via two control points to a given endpoint.
+This method is chainable as it returns the `Path` object
-
-Example of the Path.curve() method
+## Example
+
+
+```js
+({ Point, points, Path, paths, part }) => {
+
+ points.from = new Point(10, 20);
+ points.cp1 = new Point(40, 0);
+ points.cp2 = new Point(60, 40);
+ points.to = new Point(90, 20);
+
+ paths.line = new Path()
+ .move(points.from)
+ .curve(points.cp1, points.cp2, points.to)
+ .setText("Path.curve()", "text-sm center fill-note")
+
+ return part
+}
+```
-```js
-let { Point, points, Path, paths } = part.shorthand();
-
-points.from = new Point(10, 20);
-points.cp1 = new Point(40, 0);
-points.cp2 = new Point(60, 30);
-points.to = new Point(90, 20);
-
-paths.line = new Path()
- .move(points.from)
- .curve(points.cp1, points.cp2, points.to)
- .attr("data-text", "Path.curve()")
- .attr("data-text-class", "text-sm center fill-note");
-```
diff --git a/markdown/dev/reference/api/path/curve_/en.md b/markdown/dev/reference/api/path/curve_/en.md
index 5499d61726a..c74865423cb 100644
--- a/markdown/dev/reference/api/path/curve_/en.md
+++ b/markdown/dev/reference/api/path/curve_/en.md
@@ -1,35 +1,26 @@
---
-title: "curve_()"
+title: Path.curve_()
---
+The `Path.curve_()` method draws a cubic Bezier curve from the current position
+via two control points to a given endpoint. However, the end control point is
+identical to the end point.
+
+## Signature
+
```js
Path path.curve_(Point cp1, Point to)
```
-Draws a cubic Bezier curve from the current position via two control points to a given endpoint.
-However, the end control point is identical to the end point.
+This method is chainable as it returns the `Path` object
-
+## Example
-###### This method exists to save you some typing
-Note that the two following calls yield the same result:
+
```js
-.curve(point1, point2, point2)
-.curve_(point1, point2)
-```
-
-So the only purpose of this method is to save your some typing;
-
-
-
-
-Example of the Path.curve\_() method
-
-
-```js
- let { Point, points, Path, paths } = part.shorthand();
+({ Point, points, Path, paths, part }) => {
points.from = new Point(10, 20);
points.cp1 = new Point(40, 0);
@@ -38,6 +29,20 @@ Example of the Path.curve\_() method
paths.line = new Path()
.move(points.from)
.curve_(points.cp1, points.to)
- .attr("data-text", "Path.curve_()")
- .attr("data-text-class", "text-sm center fill-note");
+ .setText("Path.curve_()", "text-sm center fill-note")
+ .attr("data-text-dy", -1)
+
+ return part
+}
+```
+
+
+## Notes
+
+The main purpose of this method is to save your some typing,
+as the two following calls yield the same result:
+
+```js
+.curve(point1, point2, point2)
+.curve_(point1, point2)
```
diff --git a/markdown/dev/reference/api/path/divide/en.md b/markdown/dev/reference/api/path/divide/en.md
index 522d7b4bd2c..5bfee5e418f 100644
--- a/markdown/dev/reference/api/path/divide/en.md
+++ b/markdown/dev/reference/api/path/divide/en.md
@@ -1,42 +1,49 @@
---
-title: divide()
+title: Path.divide()
---
+The `Path.divide()` method breaks a path apart in an array of atomic paths. An
+atomic path is a path that can't be divided further and is always made up of
+one move + one drawing operation.
+
+## Signature
+
```js
array path.divide()
```
-Breaks a path apart in an array of atomic paths. An atomic path is a path that can't be divided further and is
-always made up of one move + one drawing operation.
-
-
-Example of the Path.divide() method
-
+## Example
+
```js
-let { Point, points, Path, paths } = part.shorthand();
+({ Point, points, Path, paths, part }) => {
-points.A = new Point(55, 40);
-points.B = new Point(10, 70);
-points.BCp2 = new Point(40, 20);
-points.C = new Point(90, 60);
-points.CCp1 = new Point(50, -30);
-points.D = new Point(50, 80);
-points.DCp1 = new Point(140, 50);
+ points.A = new Point(55, 40);
+ points.B = new Point(10, 70);
+ points.BCp2 = new Point(40, 20);
+ points.C = new Point(90, 60);
+ points.CCp1 = new Point(50, -30);
+ points.D = new Point(50, 80);
+ points.DCp1 = new Point(140, 50);
+
+ paths.example = new Path()
+ .move(points.A)
+ .line(points.B)
+ .curve(points.BCp2, points.CCp1, points.C)
+ .curve(points.DCp1, points.DCp1, points.D)
+ .close();
+
+ let style = "stroke-width: 4; stroke-opacity: 0.5;";
+ let i = 0;
+ for (let p of paths.example.divide()) {
+ i++;
+ paths[i] = p
+ .attr("style", style)
+ .attr('style', `stroke: hsl(${i * 70}, 100%, 50%)`)
+ }
-paths.example = new Path()
- .move(points.A)
- .line(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
- .curve(points.DCp1, points.DCp1, points.D)
- .close();
-
-let style = "stroke-width: 4; stroke-opacity: 0.5;";
-let i = 0;
-for (let p of paths.example.divide()) {
- i++;
- paths[i] = p
- .attr("style", style)
- .attr("style", `stroke: hsl(${i * 70}, 100%, 50%)`);
+ return part
}
```
+
+
diff --git a/markdown/dev/reference/api/path/edge/en.md b/markdown/dev/reference/api/path/edge/en.md
index b229c539d13..d2b0d6663ee 100644
--- a/markdown/dev/reference/api/path/edge/en.md
+++ b/markdown/dev/reference/api/path/edge/en.md
@@ -1,5 +1,5 @@
---
-title: edge()
+title: Path.edge()
---
```js
@@ -17,36 +17,37 @@ Returns the Point object at the edge of the path you specify. Edge must be one o
- `bottomLeft`
- `bottomRight`
-
-Example of the Path.edge() method
-
-
+
```js
-let { Point, points, Path, paths, Snippet, snippets } = part.shorthand();
+({ Point, points, Path, paths,snippets, Snippet, part }) => {
-points.A = new Point(45, 60);
-points.B = new Point(10, 30);
-points.BCp2 = new Point(40, 20);
-points.C = new Point(90, 30);
-points.CCp1 = new Point(50, -30);
-points.D = new Point(-60, 90);
-points.E = new Point(90, 190);
+ points.A = new Point(45, 60)
+ points.B = new Point(10, 30)
+ points.BCp2 = new Point(40, 20)
+ points.C = new Point(90, 30)
+ points.CCp1 = new Point(50, -30)
+ points.D = new Point(-60, 90)
+ points.E = new Point(90, 190)
+
+ paths.demo = new Path()
+ .move(points.A)
+ .line(points.B)
+ .curve(points.BCp2, points.CCp1, points.C)
+ .curve(points.E, points.D, points.A)
+ .close()
+
+ for (let i of [
+ "topLeft",
+ "topRight",
+ "bottomLeft",
+ "bottomRight",
+ "top",
+ "left",
+ "bottom",
+ "right"
+ ]) snippets[i] = new Snippet("notch", paths.demo.edge(i))
-paths.demo = new Path()
- .move(points.A)
- .line(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
- .curve(points.E, points.D, points.A)
- .close();
-
-for (let i of [
- "topLeft",
- "topRight",
- "bottomLeft",
- "bottomRight",
- "top",
- "left",
- "bottom",
- "right"
-]) snippets[i] = new Snippet("notch", paths.demo.edge(i));
+ return part
+}
```
+
diff --git a/markdown/dev/reference/api/path/en.md b/markdown/dev/reference/api/path/en.md
index f797e50c045..6c079467db1 100644
--- a/markdown/dev/reference/api/path/en.md
+++ b/markdown/dev/reference/api/path/en.md
@@ -13,8 +13,13 @@ Path new Path();
A Path objects comes with the following properties:
-- `render` : Set this to `false` to not render the path (exclude it from the output)
-- `attributes` : An [Attributes](/reference/api/attributes) instance holding the path's attributes
+- `attributes` : An [Attributes](/reference/api/attributes) instance holding
+ the path's attributes
+- `hidden` : When this is `true` the path will be hidden (excluded it from the
+ output). See [Path.hide()](/reference/api/path/hide),
+ [Path.unhide()](/reference/api/path/unhide), and
+ [Path.setHidden()](/reference/api/path/sethidden) for various methods that
+ allow setting this in a chainable way.
In addition, a Path object exposes the following methods:
diff --git a/markdown/dev/reference/api/path/end/en.md b/markdown/dev/reference/api/path/end/en.md
index 278791d8373..ba128d42b92 100644
--- a/markdown/dev/reference/api/path/end/en.md
+++ b/markdown/dev/reference/api/path/end/en.md
@@ -1,30 +1,38 @@
---
-title: end()
+title: Path.end()
---
+The `Path.end()` method returns the Point object at the end of the path.
+
+## Signature
+
```js
Point path.end()
```
-Returns the Point object at the end of the path.
+This method is chainable as it returns the `Path` object
-
-Example of the Path.end() method
+## Example
+
+
+```js
+({ Point, points, Path, paths, snippets, Snippet, part }) => {
+
+ points.A = new Point(45, 60)
+ points.B = new Point(10, 30)
+ points.BCp2 = new Point(40, 20)
+ points.C = new Point(90, 30)
+ points.CCp1 = new Point(50, -30)
+
+ paths.demo = new Path()
+ .move(points.A)
+ .line(points.B)
+ .curve(points.BCp2, points.CCp1, points.C)
+
+ snippets.end = new Snippet("notch", paths.demo.end())
+
+ return part
+}
+```
-```js
-let { Point, points, Path, paths, Snippet, snippets } = part.shorthand();
-
-points.A = new Point(45, 60);
-points.B = new Point(10, 30);
-points.BCp2 = new Point(40, 20);
-points.C = new Point(90, 30);
-points.CCp1 = new Point(50, -30);
-
-paths.demo = new Path()
- .move(points.A)
- .line(points.B)
- .curve(points.BCp2, points.CCp1, points.C);
-
-snippets.end = new Snippet("notch", paths.demo.end());
-```
diff --git a/markdown/dev/reference/api/path/hide/en.md b/markdown/dev/reference/api/path/hide/en.md
index ed231b36511..e0f9b535b1e 100644
--- a/markdown/dev/reference/api/path/hide/en.md
+++ b/markdown/dev/reference/api/path/hide/en.md
@@ -1,37 +1,33 @@
---
-title: hide()
+title: Path.hide()
---
+The `Path.hide()` hides the path so it does not appear in the output.
+
+## Signature
+
```js
-Path path.attr(
- string name,
- mixed value,
- bool overwrite = false
-)
+Path path.hide()
```
-This `Path.attr()` method calls `this.attributes.add()` under the hood, but returns the Path object.
+This method is chainable as it returns the `Path` object
-This allows you to chain different calls together as in the example below.
+## Example
-If the third parameter is set to `true` it will call `this.attributes.set()` instead, thereby overwriting the value of the attribute.
+
+```js
+({ Point, points, Path, paths, part }) => {
-
-Example of the Path.attr() method
+ points.top = new Point(50, 0)
+ points.left = new Point (20,50)
+ points.right = new Point (80,50)
+
+ paths.a = new Path().move(points.top).line(points.right).setText('a')
+ paths.b = new Path().move(points.right).line(points.left).setText('b').hide()
+ paths.c = new Path().move(points.left).line(points.top).setText('c')
+
+ return part
+}
+```
-```js
-let { Point, points, Path, paths } = part.shorthand();
-
-points.B = new Point(10, 50);
-points.BCp2 = new Point(40, 10);
-points.C = new Point(90, 30);
-points.CCp1 = new Point(50, 90);
-
-paths.example = new Path()
- .move(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
- .attr("class", "canvas")
- .attr("data-text", "freesewingIsMadeByJoostDeCockAndContributors")
- .attr("data-text-class", "text-xs center");
-```
diff --git a/markdown/dev/reference/api/path/insop/en.md b/markdown/dev/reference/api/path/insop/en.md
index f6b18f2378c..b9a430453f8 100644
--- a/markdown/dev/reference/api/path/insop/en.md
+++ b/markdown/dev/reference/api/path/insop/en.md
@@ -1,38 +1,51 @@
---
-title: insop()
+title: Path.insop()
---
+The `Path.insop()` method injects a Path into the [`noop`
+operation](/reference/api/path/noop) with id `id`.
+
+## Signature
+
```js
Path path.insop(string id, Path path)
```
-Injects a Path into the [`noop` operation](/reference/api/path/noop) with id `id`.
+This method is chainable as it returns the `Path` object
-This is often used to insert darts into a path
-
-Example of the Path.noop() method
+
+```js
+({ Point, points, Path, paths, part }) => {
+
+ points.left = new Point(10,10)
+ points.dartLeft = new Point(40, 10)
+ points.dartTip = new Point(50, 50)
+ points.dartRight = new Point(60, 10)
+ points.right = new Point(90, 10)
+
+ paths.withoutDart = new Path()
+ .move(points.left)
+ .line(points.dartLeft)
+ .noop('dart')
+ .line(points.right)
+
+ paths.withDart = paths.withoutDart
+ .clone()
+ .insop(
+ 'dart',
+ new Path()
+ .line(points.dartTip)
+ .line(points.dartRight)
+ )
+ .attr('style', 'stroke-width: 2px; stroke-opacity: 0.5; stroke: orange;')
+
+ return part
+}
+```
-```js
-points.left = new Point(10,10)
-points.dartLeft = new Point(40, 10)
-points.dartTip = new Point(50, 50)
-points.dartRight = new Point(60, 10)
-points.right = new Point(90, 10)
+## Notes
-paths.withoutDart = new Path()
- .move(points.left)
- .line(points.dartLeft)
- .noop('dart')
- .line(points.right)
+This is often used to insert darts into a path.
-paths.withDart = paths.without
- .insop(
- 'dart',
- new Path()
- .line(points.dartTip)
- .line(points.dartRight)
- )
- .attr('style', 'stroke-width: 2px; stroke-opacity: 0.5; stroke: orange;')
-```
diff --git a/markdown/dev/reference/api/path/intersects/en.md b/markdown/dev/reference/api/path/intersects/en.md
index 8eed5092151..ddb4171dc32 100644
--- a/markdown/dev/reference/api/path/intersects/en.md
+++ b/markdown/dev/reference/api/path/intersects/en.md
@@ -1,59 +1,61 @@
---
-title: intersects()
+title: Path.intersects()
---
- ```
- array|false path.intersects(Path path)
- ```
+The `Path.intersects()` method returns the Point object(s) where the path
+intersects with a path you pass it.
-Returns the Point object(s) where the path intersects with a path you pass it.
+## Signature
-
+```
+array|false path.intersects(Path path)
+```
-###### Use the intersection methods in Utils whenever possible
+
+
+```js
+({ Point, points, Path, paths, snippets, Snippet, getId, part }) => {
+
+ points.A = new Point(45, 60);
+ points.B = new Point(10, 30);
+ points.BCp2 = new Point(40, 20);
+ points.C = new Point(90, 30);
+ points.CCp1 = new Point(50, -30);
+ points.D = new Point(50, 130);
+ points.DCp1 = new Point(150, 30);
+
+ points._A = new Point(55, 40);
+ points._B = new Point(0, 55);
+ points._BCp2 = new Point(40, -20);
+ points._C = new Point(90, 40);
+ points._CCp1 = new Point(50, -30);
+ points._D = new Point(40, 120);
+ points._DCp1 = new Point(180, 40);
+
+ paths.demo1 = new Path()
+ .move(points.A)
+ .line(points.B)
+ .curve(points.BCp2, points.CCp1, points.C)
+ .curve(points.DCp1, points.DCp1, points.D);
+ paths.demo2 = new Path()
+ .move(points._A)
+ .line(points._B)
+ .curve(points._BCp2, points._CCp1, points._C)
+ .curve(points._DCp1, points._DCp1, points._D);
+
+ for (let p of paths.demo1.intersects(paths.demo2)) {
+ snippets[getId()] = new Snippet('notch', p)
+ }
+
+ return part
+}
+```
+
+
+
+## Notes
This is an expensive (read: slow) method that you should only use when you don't know
in advance in what segment of your path the intersection will occur.
If you do know, use one of the intersection methods in [Utils](/reference/api/utils).
-
-
-
-
-Example of the Path.intersects() method
-
-
- ```js
- let { Point, points, Path, paths, Snippet, snippets } = part.shorthand();
-
- points.A = new Point(45, 60);
- points.B = new Point(10, 30);
- points.BCp2 = new Point(40, 20);
- points.C = new Point(90, 30);
- points.CCp1 = new Point(50, -30);
- points.D = new Point(50, 130);
- points.DCp1 = new Point(150, 30);
-
- points._A = new Point(55, 40);
- points._B = new Point(0, 55);
- points._BCp2 = new Point(40, -20);
- points._C = new Point(90, 40);
- points._CCp1 = new Point(50, -30);
- points._D = new Point(40, 120);
- points._DCp1 = new Point(180, 40);
-
- paths.demo1 = new Path()
- .move(points.A)
- .line(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
- .curve(points.DCp1, points.DCp1, points.D);
- paths.demo2 = new Path()
- .move(points._A)
- .line(points._B)
- .curve(points._BCp2, points._CCp1, points._C)
- .curve(points._DCp1, points._DCp1, points._D);
-
- for (let p of paths.demo1.intersects(paths.demo2)) {
- snippets[part.getId()] = new Snippet("notch", p);
- }
- ```
diff --git a/markdown/dev/reference/api/path/intersectsx/en.md b/markdown/dev/reference/api/path/intersectsx/en.md
index 858b6edab96..9a38ef9c416 100644
--- a/markdown/dev/reference/api/path/intersectsx/en.md
+++ b/markdown/dev/reference/api/path/intersectsx/en.md
@@ -1,43 +1,50 @@
---
-title: intersectsX()
+title: Path.intersectsX()
---
+The `Path.intersectsX()` method returns the Point object(s) where the path
+intersects with a given X-value.
+
+## Signature
+
```js
array|false path.intersectsX(float x)
```
-Returns the Point object(s) where the path intersects with a given X-value.
-
-
-Example of the Path.intersectsX() method
-
+## Example
+
```js
-let { Point, points, Path, paths, Snippet, snippets } = part.shorthand();
+({ Point, points, Path, paths, snippets, Snippet, getId, part }) => {
-points.A = new Point(95, 50);
-points.B = new Point(10, 30);
-points.BCp2 = new Point(40, 20);
-points.C = new Point(90, 30);
-points.CCp1 = new Point(50, -30);
-points.D = new Point(50, 130);
-points.DCp1 = new Point(150, 30);
+ points.A = new Point(95, 50);
+ points.B = new Point(10, 30);
+ points.BCp2 = new Point(40, 20);
+ points.C = new Point(90, 30);
+ points.CCp1 = new Point(50, -30);
+ points.D = new Point(50, 130);
+ points.DCp1 = new Point(150, 30);
+
+ points.top = new Point(60, -10);
+ points.bot = new Point(60, 140);
+
+ paths.line = new Path()
+ .move(points.top)
+ .line(points.bot)
+ .attr("class", "lining dashed");
+
+ paths.demo = new Path()
+ .move(points.A)
+ .line(points.B)
+ .curve(points.BCp2, points.CCp1, points.C)
+ .curve(points.DCp1, points.DCp1, points.D);
+
+ for (let p of paths.demo.intersectsX(60)) {
+ snippets[getId()] = new Snippet("notch", p);
+ }
-points.top = new Point(60, -10);
-points.bot = new Point(60, 140);
-
-paths.line = new Path()
- .move(points.top)
- .line(points.bot)
- .attr("class", "lining dashed");
-
-paths.demo = new Path()
- .move(points.A)
- .line(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
- .curve(points.DCp1, points.DCp1, points.D);
-
-for (let p of paths.demo.intersectsX(60)) {
- snippets[part.getId()] = new Snippet("notch", p);
+ return part
}
```
+
+
diff --git a/markdown/dev/reference/api/path/intersectsy/en.md b/markdown/dev/reference/api/path/intersectsy/en.md
index df06a59385b..b825ec0e77a 100644
--- a/markdown/dev/reference/api/path/intersectsy/en.md
+++ b/markdown/dev/reference/api/path/intersectsy/en.md
@@ -1,43 +1,50 @@
---
-title: intersectsY()
+title: Path.intersectsY()
---
+The `Path.intersectsY()` method returns the Point object(s) where the path
+intersects with a given Y-value.
+
+## Signature
+
```js
array|false path.intersectsY(float y)
```
-Returns the Point object(s) where the path intersects with a given Y-value.
-
-
-Example of the Path.intersectsY() method
-
+## Example
+
```js
-let { Point, points, Path, paths, Snippet, snippets } = part.shorthand();
+({ Point, points, Path, paths, snippets, Snippet, getId, part }) => {
-points.A = new Point(55, 40);
-points.B = new Point(10, 70);
-points.BCp2 = new Point(40, 20);
-points.C = new Point(90, 60);
-points.CCp1 = new Point(50, -30);
-points.D = new Point(50, 80);
-points.DCp1 = new Point(140, 50);
+ points.A = new Point(55, 40);
+ points.B = new Point(10, 70);
+ points.BCp2 = new Point(40, 20);
+ points.C = new Point(90, 60);
+ points.CCp1 = new Point(50, -30);
+ points.D = new Point(50, 80);
+ points.DCp1 = new Point(140, 50);
-points.top = new Point(10, 58);
-points.bot = new Point(130, 58);
+ points.top = new Point(10, 58);
+ points.bot = new Point(130, 58);
-paths.line = new Path()
- .move(points.top)
- .line(points.bot)
- .attr("class", "lining dashed");
+ paths.line = new Path()
+ .move(points.top)
+ .line(points.bot)
+ .attr("class", "lining dashed");
-paths.demo = new Path()
- .move(points.A)
- .line(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
- .curve(points.DCp1, points.DCp1, points.D);
+ paths.demo = new Path()
+ .move(points.A)
+ .line(points.B)
+ .curve(points.BCp2, points.CCp1, points.C)
+ .curve(points.DCp1, points.DCp1, points.D);
-for (let p of paths.demo.intersectsY(58)) {
- snippets[part.getId()] = new Snippet("notch", p);
+ for (let p of paths.demo.intersectsY(58)) {
+ snippets[getId()] = new Snippet("notch", p);
+ }
+
+ return part
}
```
+
+
diff --git a/markdown/dev/reference/api/path/join/en.md b/markdown/dev/reference/api/path/join/en.md
index 32a2e1ab4a0..17bbb31abd5 100644
--- a/markdown/dev/reference/api/path/join/en.md
+++ b/markdown/dev/reference/api/path/join/en.md
@@ -1,44 +1,49 @@
---
-title: join()
+title: Path.join()
---
+The `Path.join()` method joins this path with another path.
+
+
+## Signature
+
```js
Path path.join(path other)
```
-Joins this path with another path.
+## Examples
-
+
+```js
+({ Point, points, Path, paths, part }) => {
+
+ points.A = new Point(45, 60)
+ points.B = new Point(10, 30)
+ points.BCp2 = new Point(40, 20)
+ points.C = new Point(90, 30)
+ points.CCp1 = new Point(50, -30)
+
+ paths.path1 = new Path()
+ .move(points.A)
+ .line(points.B)
+ .setClass("various")
+
+ paths.path2 = new Path()
+ .move(points.B)
+ .curve(points.BCp2, points.CCp1, points.C)
+ .setClass("note")
+
+ paths.joint = paths.path1
+ .join(paths.path2)
+ .setClass("lining dotted")
+
+ return part
+}
+```
+
+
+
+## Notes
You cannot join a closed path to another path
-
-
-
-Example of the Path.join() method
-
-
-```js
-let { Point, points, Path, paths } = part.shorthand();
-
-points.A = new Point(45, 60);
-points.B = new Point(10, 30);
-points.BCp2 = new Point(40, 20);
-points.C = new Point(90, 30);
-points.CCp1 = new Point(50, -30);
-
-paths.path1 = new Path()
- .move(points.A)
- .line(points.B)
- .attr("class", "various");
-
-paths.path2 = new Path()
- .move(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
- .attr("class", "canvas");
-
-paths.joint = paths.path1
- .join(paths.path2)
- .attr("class", "note lashed stroke-l")
- .attr("style", "stoke-opacity: 0.5");
-```
diff --git a/markdown/dev/reference/api/path/length/en.md b/markdown/dev/reference/api/path/length/en.md
index ca15197e6f7..e58a5e4cdb9 100644
--- a/markdown/dev/reference/api/path/length/en.md
+++ b/markdown/dev/reference/api/path/length/en.md
@@ -1,43 +1,49 @@
---
-title: length()
+title: Path.length()
---
+The `Path.length()` method returns the length of the path.
+
+## Signature
+
```js
float path.length()
```
-Returns the length of the path.
+## Example
-
-Example of the Path.length() method
+
+```js
+({ Point, points, Path, paths, macro, part }) => {
+
+ points.A = new Point(45, 60);
+ points.B = new Point(10, 30);
+ points.BCp2 = new Point(40, 20);
+ points.C = new Point(90, 30);
+ points.CCp1 = new Point(50, -30);
+
+ paths.example = new Path()
+ .move(points.A)
+ .line(points.B)
+ .curve(points.BCp2, points.CCp1, points.C);
+
+ macro("pd", {
+ path: paths.example,
+ d: -20
+ });
+
+ macro("pd", {
+ path: new Path().move(points.B).line(points.A),
+ d: 10
+ });
+
+ macro("pd", {
+ path: new Path().move(points.B).curve(points.BCp2, points.CCp1, points.C),
+ d: -10
+ });
+
+ return part
+}
+```
-```js
-let { Point, points, Path, paths, macro } = part.shorthand();
-
-points.A = new Point(45, 60);
-points.B = new Point(10, 30);
-points.BCp2 = new Point(40, 20);
-points.C = new Point(90, 30);
-points.CCp1 = new Point(50, -30);
-
-paths.example = new Path()
- .move(points.A)
- .line(points.B)
- .curve(points.BCp2, points.CCp1, points.C);
-
-macro("pd", {
- path: paths.example,
- d: -20
-});
-
-macro("pd", {
- path: new Path().move(points.B).line(points.A),
- d: 10
-});
-
-macro("pd", {
- path: new Path().move(points.B).curve(points.BCp2, points.CCp1, points.C),
- d: -10
-});
-```
diff --git a/markdown/dev/reference/api/path/line/en.md b/markdown/dev/reference/api/path/line/en.md
index 2cf569eb77e..906ec3d2974 100644
--- a/markdown/dev/reference/api/path/line/en.md
+++ b/markdown/dev/reference/api/path/line/en.md
@@ -1,26 +1,34 @@
---
-title: line()
+title: Path.line()
---
+The `Path.line()` method draws a straight line from the current position to a
+given point.
+
+## Signature
+
```js
Path path.line(Point to)
```
-Draws a straight line from the current position to a given point.
+This method is chainable as it returns the `Path` object
-
-Example of the Path.line() method
+## Example
+
+
+```js
+({ Point, points, Path, paths, part }) => {
+
+ points.from = new Point(10, 10)
+ points.to = new Point(90, 10)
+
+ paths.line = new Path()
+ .move(points.from)
+ .line(points.to)
+ .setText("Path.line()", "text-sm center fill-note")
+
+ return part
+}
+```
-```js
-let { Point, points, Path, paths } = part.shorthand();
-
-points.from = new Point(10, 10);
-points.to = new Point(90, 10);
-
-paths.line = new Path()
- .move(points.from)
- .line(points.to)
- .attr("data-text", "Path.line()")
- .attr("data-text-class", "text-sm center fill-note");
-```
diff --git a/markdown/dev/reference/api/path/move/en.md b/markdown/dev/reference/api/path/move/en.md
index 7fb24ec2aee..f80354c7f19 100644
--- a/markdown/dev/reference/api/path/move/en.md
+++ b/markdown/dev/reference/api/path/move/en.md
@@ -1,18 +1,36 @@
---
-title: move()
+title: Path.move()
---
+The `Path.move()` method moves to a given point without drawing a line.
+
+## Signature
+
```js
Path path.move(Point to)
```
-Moves to a given point without drawing a line.
+## Example
-
-###### Always start your path with a move
+
+```js
+({ Point, points, Path, paths, part }) => {
-When drawing a path, you must always start with a `move()` call,
+ points.to = new Point(50, 20)
+ .setText("Path.move()", "text-xs fill-note center")
+
+ paths.noline = new Path().move(points.to)
+
+ return part
+}
+```
+
+
+
+## Notes
+
+When drawing a path, **you must always start with a `move()` call**,
followed by your `line()` and/or `curve()` calls
and an optional `close()` call.
@@ -23,21 +41,5 @@ paths.example = new Path()
.move(points.a)
.curve(points.b, points.c, points.d)
.line(points.e)
- .close();
-```
-
-
-
-
-Example of the Path.move() method
-
-
-```js
-let { Point, points, Path, paths } = part.shorthand();
-
-points.to = new Point(50, 20)
- .attr("data-text", "Path.move()")
- .attr("data-text-class", "text-xs fill-note");
-
-paths.noline = new Path().move(points.to);
+ .close()
```
diff --git a/markdown/dev/reference/api/path/noop/en.md b/markdown/dev/reference/api/path/noop/en.md
index 88fad6961ff..38fa85198ed 100644
--- a/markdown/dev/reference/api/path/noop/en.md
+++ b/markdown/dev/reference/api/path/noop/en.md
@@ -1,41 +1,49 @@
---
-title: noop()
+title: Path.noop()
---
+The `Path.noop()` method adds a placeholder path operation.
+A `noop` operation does nothing, but is intended to be replaced later
+with [`Path.insop()`](/reference/api/path/insop).
+
+## Signature
+
```js
Path path.noop(string id)
```
-Adds a placeholder path operation.
+This method is chainable as it returns the `Path` object
-A `noop` operation does nothing, but is intended to be replaced later
-with [`Path.insop()`](/reference/api/path/insop).
+## Example
-This is often used to insert darts into a path
+
+```js
+({ Point, points, Path, paths, part }) => {
-
-Example of the Path.noop() method
+ points.left = new Point(10,10)
+ points.dartLeft = new Point(40, 10)
+ points.dartTip = new Point(50, 50)
+ points.dartRight = new Point(60, 10)
+ points.right = new Point(90, 10)
+
+ paths.withoutDart = new Path()
+ .move(points.left)
+ .line(points.dartLeft)
+ .noop('dart')
+ .line(points.right)
+
+ paths.withDart = paths.withoutDart
+ .clone()
+ .insop(
+ 'dart',
+ new Path()
+ .line(points.dartTip)
+ .line(points.dartRight)
+ )
+ .attr('style', 'stroke-width: 2px; stroke-opacity: 0.5; stroke: orange;')
+
+ return part
+}
+```
-```js
-points.left = new Point(10,10)
-points.dartLeft = new Point(40, 10)
-points.dartTip = new Point(50, 50)
-points.dartRight = new Point(60, 10)
-points.right = new Point(90, 10)
-
-paths.withoutDart = new Path()
- .move(points.left)
- .line(points.dartLeft)
- .noop('dart')
- .line(points.right)
-
-paths.withDart = paths.without
- .insop(
- 'dart',
- new Path()
- .line(points.dartTip)
- .line(points.dartRight)
- )
- .attr('style', 'stroke-width: 2px; stroke-opacity: 0.5; stroke: orange;')
-```
diff --git a/markdown/dev/reference/api/path/offset/en.md b/markdown/dev/reference/api/path/offset/en.md
index c5ce02fae6d..c52d43fcf5f 100644
--- a/markdown/dev/reference/api/path/offset/en.md
+++ b/markdown/dev/reference/api/path/offset/en.md
@@ -1,46 +1,53 @@
---
-title: offset()
+title: Path.offset()
---
+The `Path.offset()` method returns a new Path that is offset by distance from
+the original path.
+
+## Signature
+
```js
Path path.offset(float distance)
```
-Returns a new Path that is offset by distance from the original path.
+## Example
-
-Example of the Path.offset() method
+
+```js
+({ Point, points, Path, paths, part }) => {
+
+ points.A = new Point(45, 60);
+ points.B = new Point(10, 30);
+ points.BCp2 = new Point(40, 20);
+ points.C = new Point(90, 30);
+ points.CCp1 = new Point(50, -30);
+
+ paths.example = new Path()
+ .move(points.A)
+ .line(points.B)
+ .curve(points.BCp2, points.CCp1, points.C)
+ .line(points.A)
+ .close();
+
+ paths.offset = paths.example
+ .offset(-10)
+ .attr("class", "interfacing");
+
+ paths.lineOffset = new Path()
+ .move(points.A)
+ .line(points.B)
+ .offset(-5)
+ .attr("class", "various");
+
+ paths.curveOffset = new Path()
+ .move(points.B)
+ .curve(points.BCp2, points.CCp1, points.C)
+ .offset(-5)
+ .attr("class", "canvas");
+
+ return part
+}
+```
-```js
-let { Point, points, Path, paths } = part.shorthand();
-
-points.A = new Point(45, 60);
-points.B = new Point(10, 30);
-points.BCp2 = new Point(40, 20);
-points.C = new Point(90, 30);
-points.CCp1 = new Point(50, -30);
-
-paths.example = new Path()
- .move(points.A)
- .line(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
- .line(points.A)
- .close();
-
-paths.offset = paths.example
- .offset(-10)
- .attr("class", "interfacing");
-
-paths.lineOffset = new Path()
- .move(points.A)
- .line(points.B)
- .offset(-5)
- .attr("class", "various");
-
-paths.curveOffset = new Path()
- .move(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
- .offset(-5)
- .attr("class", "canvas");
-```
diff --git a/markdown/dev/reference/api/path/reverse/en.md b/markdown/dev/reference/api/path/reverse/en.md
index 55f8f102fc9..d9952973e0b 100644
--- a/markdown/dev/reference/api/path/reverse/en.md
+++ b/markdown/dev/reference/api/path/reverse/en.md
@@ -1,42 +1,49 @@
---
-title: reverse()
+title: Path.reverse()
---
+The `Path.reverse()` returns a path that is the reversed version of this path.
+As in, start becomes end, and end becomes start.
+
+## Signature
+
```js
-Path path.reverse()
+Path path.reverse(bool cloneAttributes=false)
```
-Returns a path that is the reversed version of this path. As in, start becomes end, and end becomes start.
+If you pass a truthy value to this method, it will return a deep clone of the
+path, including its attributes. By default, it will return a shallow
+copy, whithout the attributes.
-
+## Example
+
+
+
+```js
+({ Point, points, Path, paths, part }) => {
+
+ points.B = new Point(10, 30);
+ points.BCp2 = new Point(40, 20);
+ points.C = new Point(90, 30);
+ points.CCp1 = new Point(50, -30);
+
+ paths.example = new Path()
+ .move(points.B)
+ .curve(points.BCp2, points.CCp1, points.C)
+ .setText("FreeSewing rocks", "text-xs fill-note center")
+
+ paths.reverse = paths.example.reverse(true)
+
+ return part
+}
+```
+
+
+## Notes
The reversed path is a shallow copy.
It will in other words not inherit the attributes of the original path.
-If you want a deep copy, including the attributes, use `Path.clone().reverse()`.
+If you want a deep copy, including the attributes, use `Path.reverse(true)`.
-
-
-Example of the Path.reverse() method
-
-
-```js
-let { Point, points, Path, paths } = part.shorthand();
-
-points.B = new Point(10, 30);
-points.BCp2 = new Point(40, 20);
-points.C = new Point(90, 30);
-points.CCp1 = new Point(50, -30);
-
-paths.example = new Path()
- .move(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
- .attr("data-text", "freesewingIsMadeByJoostDeCockAndContributors")
- .attr("data-text-class", "text-xs fill-note");
-
-paths.reverse = paths.example
- .reverse()
- .attr("data-text", "freesewingIsMadeByJoostDeCockAndContributors")
- .attr("data-text-class", "text-xs fill-lining");
-```
diff --git a/markdown/dev/reference/api/path/roughlength/en.md b/markdown/dev/reference/api/path/roughlength/en.md
index 5280edae521..de51a13fdce 100644
--- a/markdown/dev/reference/api/path/roughlength/en.md
+++ b/markdown/dev/reference/api/path/roughlength/en.md
@@ -1,37 +1,50 @@
---
-title: roughLength()
+title: Path.roughLength()
---
+The `Path.roughLength()` method returns a (very) rough estimate of the path's length.
+
+## Signature
+
```js
-Path path.attr(
- string name,
- mixed value,
- bool overwrite = false
-)
+Number path.roughLength()
```
-This `Path.attr()` method calls `this.attributes.add()` under the hood, but returns the Path object.
+## Example
-This allows you to chain different calls together as in the example below.
+
+```js
+({ Point, points, Path, paths, macro, units, part }) => {
-If the third parameter is set to `true` it will call `this.attributes.set()` instead, thereby overwriting the value of the attribute.
+ points.B = new Point(10, 30);
+ points.BCp2 = new Point(40, 20);
+ points.C = new Point(120, 30);
+ points.CCp1 = new Point(50, -30);
+
+ paths.example = new Path()
+ .move(points.B)
+ .curve(points.BCp2, points.CCp1, points.C);
+
+ macro("pd", {
+ path: paths.example,
+ d: -10,
+ text: `Path.roughLength() = ${units(paths.example.roughLength())}`
+ })
+ macro("pd", {
+ path: paths.example,
+ d: 10,
+ text: `Path.length() = ${units(paths.example.length())}`
+ });
+
-
-Example of the Path.attr() method
+ return part
+}
+```
-```js
-let { Point, points, Path, paths } = part.shorthand();
+## Notes
-points.B = new Point(10, 50);
-points.BCp2 = new Point(40, 10);
-points.C = new Point(90, 30);
-points.CCp1 = new Point(50, 90);
+The `Path.roughLength()` is not intended to give an estimate that is accurate, but rather differentiatate between paths that are a few millimeter long, or meters long.
-paths.example = new Path()
- .move(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
- .attr("class", "canvas")
- .attr("data-text", "freesewingIsMadeByJoostDeCockAndContributors")
- .attr("data-text-class", "text-xs center");
-```
+It calculates the length without *walking the (cubic) Bezier curve* making it very fast and very inaccurate (for curves).
+It is typically used to determine how much precision to apply when walking a curve.
diff --git a/markdown/dev/reference/api/path/setclass/en.md b/markdown/dev/reference/api/path/setclass/en.md
index b4c4f8f5471..28a3407faf2 100644
--- a/markdown/dev/reference/api/path/setclass/en.md
+++ b/markdown/dev/reference/api/path/setclass/en.md
@@ -1,37 +1,43 @@
---
-title: setClass()
+title: Path.setClass()
---
+The `Path.setClass()` method sets the CSS class(es) of the path.
+
+## Signature
+
```js
-Path path.attr(
- string name,
- mixed value,
- bool overwrite = false
-)
+Path path.setClass(string className)
```
-This `Path.attr()` method calls `this.attributes.add()` under the hood, but returns the Path object.
+This method is chainable as it returns the `Path` object
-This allows you to chain different calls together as in the example below.
+## Example
-If the third parameter is set to `true` it will call `this.attributes.set()` instead, thereby overwriting the value of the attribute.
+
+```js
+({ Point, points, Path, paths, part }) => {
-
-Example of the Path.attr() method
+ points.from = new Point(5, 10)
+ points.to = new Point(95, 10)
+
+ paths.line = new Path()
+ .move(points.from)
+ .line(points.to)
+ .setClass('note dashed')
+
+ return part
+}
+```
+## Notes
+
+The main purpose of this method is to save your some typing,
+as the two following calls yield the same result:
+
```js
-let { Point, points, Path, paths } = part.shorthand();
-
-points.B = new Point(10, 50);
-points.BCp2 = new Point(40, 10);
-points.C = new Point(90, 30);
-points.CCp1 = new Point(50, 90);
-
-paths.example = new Path()
- .move(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
- .attr("class", "canvas")
- .attr("data-text", "freesewingIsMadeByJoostDeCockAndContributors")
- .attr("data-text-class", "text-xs center");
+path.attr('class', 'fabric', true)
+path.addClass('fabric')
```
+
diff --git a/markdown/dev/reference/api/path/sethidden/en.md b/markdown/dev/reference/api/path/sethidden/en.md
index 4ff2a979132..31fb5df586c 100644
--- a/markdown/dev/reference/api/path/sethidden/en.md
+++ b/markdown/dev/reference/api/path/sethidden/en.md
@@ -1,37 +1,34 @@
---
-title: setHidden()
+title: Path.setHidden()
---
+The `Path.setHidden()` method either hides or unhides the path depending on the
+value you pass it.
+
+## Signature
+
```js
-Path path.attr(
- string name,
- mixed value,
- bool overwrite = false
-)
+Path path.setHidden(bool hidden = false)
```
-This `Path.attr()` method calls `this.attributes.add()` under the hood, but returns the Path object.
+This method is chainable as it returns the `Path` object
-This allows you to chain different calls together as in the example below.
+## Example
-If the third parameter is set to `true` it will call `this.attributes.set()` instead, thereby overwriting the value of the attribute.
+
+```js
+({ Point, points, Path, paths, part }) => {
-
-Example of the Path.attr() method
+ points.top = new Point(50, 0)
+ points.left = new Point (20,50)
+ points.right = new Point (80,50)
+
+ paths.a = new Path().move(points.top).line(points.right).setText('a')
+ paths.b = new Path().move(points.right).line(points.left).setText('b').setHidden(true)
+ paths.c = new Path().move(points.left).line(points.top).setText('c')
+
+ return part
+}
+```
-```js
-let { Point, points, Path, paths } = part.shorthand();
-
-points.B = new Point(10, 50);
-points.BCp2 = new Point(40, 10);
-points.C = new Point(90, 30);
-points.CCp1 = new Point(50, 90);
-
-paths.example = new Path()
- .move(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
- .attr("class", "canvas")
- .attr("data-text", "freesewingIsMadeByJoostDeCockAndContributors")
- .attr("data-text-class", "text-xs center");
-```
diff --git a/markdown/dev/reference/api/path/setrender/en.md b/markdown/dev/reference/api/path/setrender/en.md
deleted file mode 100644
index 8e809bd146d..00000000000
--- a/markdown/dev/reference/api/path/setrender/en.md
+++ /dev/null
@@ -1,12 +0,0 @@
----
-title: setRender()
----
-
-```js
-Path path.setRender(bool render)
-```
-
-This is a chainable method to sets the `path.render` property.
-If you set it to `false` your path will not be rendered.
-
-Add example
diff --git a/markdown/dev/reference/api/path/settext/en.md b/markdown/dev/reference/api/path/settext/en.md
new file mode 100644
index 00000000000..578b3c08908
--- /dev/null
+++ b/markdown/dev/reference/api/path/settext/en.md
@@ -0,0 +1,48 @@
+---
+title: Path.setText()
+---
+
+The `Path.addText()` method set text on the path.
+
+## Signature
+
+```js
+Path path.setText(string text, string className)
+```
+
+The second argument will optionally be used to set the CSS class for the text.
+
+This method is chainable as it returns the `Path` object
+
+## Example
+
+
+```js
+({ Point, points, Path, paths, part }) => {
+ points.from = new Point(5, 10)
+ points.to = new Point(95, 10)
+
+ paths.line = new Path()
+ .move(points.from)
+ .line(points.to)
+ .addText('FreeSewing rocks')
+
+ return part
+}
+```
+
+
+## Notes
+
+The main purpose of this method is to save your some typing,
+as the two following calls yield the same result:
+
+```js
+path.attr('data-text', 'Hello')
+path.setText('Hello')
+```
+
+The difference with [Path.addText()](/reference/api/path/addtext) is that this
+method will overwrite existing text on the path, whereas `Path.addText()` will
+add to the existing text.
+
diff --git a/markdown/dev/reference/api/path/shiftalong/en.md b/markdown/dev/reference/api/path/shiftalong/en.md
index bda434d566f..c31b402bcc8 100644
--- a/markdown/dev/reference/api/path/shiftalong/en.md
+++ b/markdown/dev/reference/api/path/shiftalong/en.md
@@ -1,54 +1,55 @@
---
-title: shiftAlong()
+title: Path.shiftAlong()
---
-```js
-Point path.shiftAlong(float distance[, int stepsPerMm=25])
-```
+The `Path.shiftAlong()` method returns a point that lies at distance travelled
+along the path.
-Returns a point that lies at distance travelled along the path.
-
-
-Example of the Path.shiftAlong() method
-
+## Signature
```js
-let { Point, points, Path, paths, Snippet, snippets } = part.shorthand();
-
-points.A = new Point(45, 60);
-points.B = new Point(10, 30);
-points.BCp2 = new Point(40, 20);
-points.C = new Point(90, 30);
-points.CCp1 = new Point(50, -30);
-
-paths.example = new Path()
- .move(points.A)
- .line(points.B)
- .curve(points.BCp2, points.CCp1, points.C);
-
-points.x1 = paths.example
- .shiftAlong(20)
- .attr("data-text", "2cm")
- .attr("data-text-class", "center fill-note")
- .attr("data-text-lineheight", 6);
-points.x2 = paths.example
- .shiftAlong(90)
- .attr("data-text", "9cm")
- .attr("data-text-class", "center fill-note")
- .attr("data-text-lineheight", 6);
-
-snippets.x1 = new Snippet("notch", points.x1);
-snippets.x2 = new Snippet("notch", points.x2);
+Point path.shiftAlong(float distance[, int stepsPerMm=10])
```
-
-
-##### The second parameter is optional
-
The second parameter controls the precision by which the path will be _walked_.
-By default, we'll divide it into 25 steps per mm.
+By default, we'll divide it into 10 steps per mm.
If you don't need that precision, you can pass a lower number.
-But for most cases, you can just ignore it.
+If you need more precision, you can pass a higher number.
+For most cases, the default will be fine.
-
+## Example
+
+
+```js
+({ Point, points, Path, paths, Snippet, snippets, part }) => {
+
+ points.A = new Point(45, 60);
+ points.B = new Point(10, 30);
+ points.BCp2 = new Point(40, 20);
+ points.C = new Point(90, 30);
+ points.CCp1 = new Point(50, -30);
+
+ paths.example = new Path()
+ .move(points.A)
+ .line(points.B)
+ .curve(points.BCp2, points.CCp1, points.C);
+
+ points.x1 = paths.example
+ .shiftAlong(20)
+ .attr("data-text", "2cm")
+ .attr("data-text-class", "center fill-note")
+ .attr("data-text-lineheight", 6);
+ points.x2 = paths.example
+ .shiftAlong(90)
+ .attr("data-text", "9cm")
+ .attr("data-text-class", "center fill-note")
+ .attr("data-text-lineheight", 6);
+
+ snippets.x1 = new Snippet("notch", points.x1);
+ snippets.x2 = new Snippet("notch", points.x2);
+
+ return part
+}
+```
+
diff --git a/markdown/dev/reference/api/path/shiftfractionalong/en.md b/markdown/dev/reference/api/path/shiftfractionalong/en.md
index 1672c60cc41..490dc0047fe 100644
--- a/markdown/dev/reference/api/path/shiftfractionalong/en.md
+++ b/markdown/dev/reference/api/path/shiftfractionalong/en.md
@@ -1,54 +1,52 @@
---
-title: shiftFractionAlong()
+title: Path.shiftFractionAlong()
---
+The `Path.shiftFractionAlong()` returns a point that lies at fraction of the
+length of the path travelled along the path.
+
+## Signature
+
```js
Point path.shiftFractionAlong(float fraction[, int stepsPerMm=25])
```
-Returns a point that lies at fraction of the length of the path travelled along the path.
-
-
-Example of the Path.shiftFractionAlong() method
-
-
-```js
-let { Point, points, Path, paths, Snippet, snippets } = part.shorthand();
-
-points.A = new Point(45, 60);
-points.B = new Point(10, 30);
-points.BCp2 = new Point(40, 20);
-points.C = new Point(90, 30);
-points.CCp1 = new Point(50, -30);
-
-paths.example = new Path()
- .move(points.A)
- .line(points.B)
- .curve(points.BCp2, points.CCp1, points.C);
-
-points.x1 = paths.example
- .shiftFractionAlong(0.2)
- .attr("data-text", "msg_20")
- .attr("data-text-class", "center")
- .attr("data-text-lineheight", 6);
-points.x2 = paths.example
- .shiftFractionAlong(0.9)
- .attr("data-text", "msg_90")
- .attr("data-text-class", "center")
- .attr("data-text-lineheight", 6);
-
-snippets.xl = new Snippet("notch", points.x1);
-snippets.x2 = new Snippet("notch", points.x2);
-```
-
-
-
-##### The second parameter is optional
-
The second parameter controls the precision by which the path will be _walked_.
-By default, we'll divide it into 25 steps per mm.
+By default, we'll divide it into 10 steps per mm.
If you don't need that precision, you can pass a lower number.
-But for most cases, you can just ignore it.
+If you need more precision, you can pass a higher number.
+For most cases, the default will be fine.
+
+## Example
+
+
+```js
+({ Point, points, Path, paths, Snippet, snippets, part }) => {
+
+ points.A = new Point(45, 60);
+ points.B = new Point(10, 30);
+ points.BCp2 = new Point(40, 20);
+ points.C = new Point(90, 30);
+ points.CCp1 = new Point(50, -30);
+
+ paths.example = new Path()
+ .move(points.A)
+ .line(points.B)
+ .curve(points.BCp2, points.CCp1, points.C);
+
+ points.x1 = paths.example
+ .shiftFractionAlong(0.2)
+ .setText("0.2", "center")
+ points.x2 = paths.example
+ .shiftFractionAlong(0.9)
+ .setText("0.9", "center")
+
+ snippets.xl = new Snippet("notch", points.x1);
+ snippets.x2 = new Snippet("notch", points.x2);
+
+ return part
+}
+```
+
-
diff --git a/markdown/dev/reference/api/path/smurve/en.md b/markdown/dev/reference/api/path/smurve/en.md
index 3189c37f7ee..75b967474f1 100644
--- a/markdown/dev/reference/api/path/smurve/en.md
+++ b/markdown/dev/reference/api/path/smurve/en.md
@@ -1,37 +1,41 @@
---
-title: smurve()
+title: Path.smurve()
---
+The `Path.smurve()` method draws a smooth curve from the current point via a control point to an endpoint.
+A smooth curve means it will use the reflection of the end control point of the previous curve.
+
+## Signature
+
```js
-Path path.attr(
- string name,
- mixed value,
- bool overwrite = false
-)
+Path path.smurve(Point cp2, Point end)
```
-This `Path.attr()` method calls `this.attributes.add()` under the hood, but returns the Path object.
+This method is chainable as it returns the `Path` object
-This allows you to chain different calls together as in the example below.
+## Example
-If the third parameter is set to `true` it will call `this.attributes.set()` instead, thereby overwriting the value of the attribute.
+
+```js
+({ Point, points, Path, paths, part }) => {
-
-Example of the Path.attr() method
+ points.aFrom = new Point(10, 10);
+ points.aCp1 = new Point(40, 40);
+ points.aCp2 = new Point(70, -20);
+ points.aTo = new Point(100, 10);
+
+ points.bCp2 = new Point(50,50)
+ points.bTo = new Point(10,50)
+
+ paths.smurve = new Path()
+ .move(points.aFrom)
+ .curve(points.aCp1, points.aCp2,points.aTo)
+ .smurve(points.bCp2, points.bTo)
+ .reverse() // Puts text at the end
+ .setText('Path.smurve()')
+
+ return part
+}
+```
-```js
-let { Point, points, Path, paths } = part.shorthand();
-
-points.B = new Point(10, 50);
-points.BCp2 = new Point(40, 10);
-points.C = new Point(90, 30);
-points.CCp1 = new Point(50, 90);
-
-paths.example = new Path()
- .move(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
- .attr("class", "canvas")
- .attr("data-text", "freesewingIsMadeByJoostDeCockAndContributors")
- .attr("data-text-class", "text-xs center");
-```
diff --git a/markdown/dev/reference/api/path/smurve_/en.md b/markdown/dev/reference/api/path/smurve_/en.md
index 202b3036809..ed785005404 100644
--- a/markdown/dev/reference/api/path/smurve_/en.md
+++ b/markdown/dev/reference/api/path/smurve_/en.md
@@ -1,37 +1,42 @@
---
-title: smurve_()
+title: Path.smurve_()
---
+The `Path.smurve_()` method draws a smooth curve from the current point an endpoint.
+In addition, the end point's control point lies on top of the end point.
+
+A smooth curve means it will use the reflection of the end control point of the previous curve.
+
+## Signature
+
```js
-Path path.attr(
- string name,
- mixed value,
- bool overwrite = false
-)
+Path path.smurve_(Point cp2, Point end)
```
-This `Path.attr()` method calls `this.attributes.add()` under the hood, but returns the Path object.
+This method is chainable as it returns the `Path` object
-This allows you to chain different calls together as in the example below.
+## Example
-If the third parameter is set to `true` it will call `this.attributes.set()` instead, thereby overwriting the value of the attribute.
+
+```js
+({ Point, points, Path, paths, part }) => {
-
-Example of the Path.attr() method
+ points.aFrom = new Point(10, 10);
+ points.aCp1 = new Point(40, 40);
+ points.aCp2 = new Point(70, -20);
+ points.aTo = new Point(100, 10);
+
+ points.bTo = new Point(10,50)
+
+ paths.smurve = new Path()
+ .move(points.aFrom)
+ .curve(points.aCp1, points.aCp2,points.aTo)
+ .smurve_(points.bTo)
+ .reverse() // Puts text at the end
+ .setText('Path.smurve()')
+
+ return part
+}
+```
-```js
-let { Point, points, Path, paths } = part.shorthand();
-
-points.B = new Point(10, 50);
-points.BCp2 = new Point(40, 10);
-points.C = new Point(90, 30);
-points.CCp1 = new Point(50, 90);
-
-paths.example = new Path()
- .move(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
- .attr("class", "canvas")
- .attr("data-text", "freesewingIsMadeByJoostDeCockAndContributors")
- .attr("data-text-class", "text-xs center");
-```
diff --git a/markdown/dev/reference/api/path/split/en.md b/markdown/dev/reference/api/path/split/en.md
index c1d5d2117ca..644a5c91c7e 100644
--- a/markdown/dev/reference/api/path/split/en.md
+++ b/markdown/dev/reference/api/path/split/en.md
@@ -1,42 +1,49 @@
---
-title: split
+title: Path.split()
---
+The `Path.split()` method splits a path in two halves, on a point along that
+path that you pass it.
+
+## Signature
+
```js
array path.split(Point splitPoint)
```
-Splits a path in two halves, on a point along that path that you pass it.
-
-
-Example of the Path.split() method
-
+## Example
+
```js
-let { Point, points, Path, paths, Snippet, snippets } = part.shorthand();
+({ Point, points, Path, paths, snippets, Snippet, part }) => {
-points.A = new Point(45, 60);
-points.B = new Point(10, 30);
-points.BCp2 = new Point(40, 20);
-points.C = new Point(90, 30);
-points.CCp1 = new Point(50, -30);
-points.D = new Point(50, 130);
-points.DCp1 = new Point(150, 30);
+ points.A = new Point(45, 60);
+ points.B = new Point(10, 30);
+ points.BCp2 = new Point(40, 20);
+ points.C = new Point(90, 30);
+ points.CCp1 = new Point(50, -30);
+ points.D = new Point(50, 130);
+ points.DCp1 = new Point(150, 30);
+
+ paths.demo = new Path()
+ .move(points.D)
+ .curve(points.DCp1, points.DCp1, points.C)
+ .curve(points.CCp1, points.BCp2, points.B)
+ .line(points.A);
+
+ points.split = paths.demo.shiftFractionAlong(0.75);
+ snippets.split = new Snippet("notch", points.split);
+
+ let style = "stroke-width: 3; stroke-opacity: 0.5;";
+ let halves = paths.demo.split(points.split);
+ for (let i in halves) {
+ paths[i] = halves[i]
+ .attr("style", style)
+ .attr("style", `stroke: hsl(${i * 70}, 100%, 50%)`);
+ }
-paths.demo = new Path()
- .move(points.D)
- .curve(points.DCp1, points.DCp1, points.C)
- .curve(points.CCp1, points.BCp2, points.B)
- .line(points.A);
-
-points.split = paths.demo.shiftFractionAlong(0.75);
-snippets.split = new Snippet("notch", points.split);
-
-let style = "stroke-width: 3; stroke-opacity: 0.5;";
-let halves = paths.demo.split(points.split);
-for (let i in halves) {
- paths[i] = halves[i]
- .attr("style", style)
- .attr("style", `stroke: hsl(${i * 70}, 100%, 50%)`);
+ return part
}
```
+
+
diff --git a/markdown/dev/reference/api/path/start/en.md b/markdown/dev/reference/api/path/start/en.md
index 5c07bbce771..8403460cc0e 100644
--- a/markdown/dev/reference/api/path/start/en.md
+++ b/markdown/dev/reference/api/path/start/en.md
@@ -1,30 +1,38 @@
---
-title: start()
+title: Path.start()
---
+The `Path.start()` method returns the Point object at the start of the path.
+
+## Signature
+
```js
Point path.start()
```
-Returns the Point object at the start of the path.
+This method is chainable as it returns the `Path` object
-
-Example of the Path.start() method
+## Example
+
+
+```js
+({ Point, points, Path, paths, snippets, Snippet, part }) => {
+
+ points.A = new Point(45, 60)
+ points.B = new Point(10, 30)
+ points.BCp2 = new Point(40, 20)
+ points.C = new Point(90, 30)
+ points.CCp1 = new Point(50, -30)
+
+ paths.demo = new Path()
+ .move(points.A)
+ .line(points.B)
+ .curve(points.BCp2, points.CCp1, points.C)
+
+ snippets.end = new Snippet("notch", paths.demo.start())
+
+ return part
+}
+```
-```js
-let { Point, points, Path, paths, Snippet, snippets } = part.shorthand();
-
-points.A = new Point(45, 60);
-points.B = new Point(10, 30);
-points.BCp2 = new Point(40, 20);
-points.C = new Point(90, 30);
-points.CCp1 = new Point(50, -30);
-
-paths.example = new Path()
- .move(points.A)
- .line(points.B)
- .curve(points.BCp2, points.CCp1, points.C);
-
-snippets.start = new Snippet("notch", paths.example.start());
-```
diff --git a/markdown/dev/reference/api/path/translate/en.md b/markdown/dev/reference/api/path/translate/en.md
index 6bfbcc1385c..909d038d246 100644
--- a/markdown/dev/reference/api/path/translate/en.md
+++ b/markdown/dev/reference/api/path/translate/en.md
@@ -1,45 +1,51 @@
---
-title: translate()
+title: Path.translate()
---
+The `Path.translate()` method returns a path with
+[a translate transform](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#Translate)
+applied.
+
+## Example
+
```js
Path path.translate(float deltaX, float deltaY)
```
-Returns a path with
-[a translate transform](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform#Translate)
-applied.
+## Example
-
-Example of the Path.translate() method
+
+```js
+({ Point, points, Path, paths, part, macro }) => {
+
+ points.A = new Point(45, 60)
+ points.B = new Point(10, 30)
+ points.BCp2 = new Point(40, 20)
+ points.C = new Point(90, 30)
+ points.CCp1 = new Point(50, -30)
+
+ paths.A = new Path()
+ .move(points.A)
+ .line(points.B)
+ .curve(points.BCp2, points.CCp1, points.C)
+
+ paths.B = paths.A.translate(60, 30)
+
+ points.step1 = points.B.shift(0, 60)
+ points.step2 = points.step1.shift(-90, 30)
+ macro("ld", {
+ from: points.B,
+ to: points.step1,
+ noStartMarker: true
+ })
+ macro("ld", {
+ from: points.step1,
+ to: points.step2,
+ noStartMarker: true
+ })
+
+ return part
+}
+```
-```js
-let { Point, points, Path, paths, macro } = part.shorthand();
-
-points.A = new Point(45, 60);
-points.B = new Point(10, 30);
-points.BCp2 = new Point(40, 20);
-points.C = new Point(90, 30);
-points.CCp1 = new Point(50, -30);
-
-paths.A = new Path()
- .move(points.A)
- .line(points.B)
- .curve(points.BCp2, points.CCp1, points.C);
-
-paths.B = paths.A.translate(60, 30);
-
-points.step1 = points.B.shift(0, 60);
-points.step2 = points.step1.shift(-90, 30);
-macro("ld", {
- from: points.B,
- to: points.step1,
- noStartMarker: true
-});
-macro("ld", {
- from: points.step1,
- to: points.step2,
- noStartMarker: true
-});
-```
diff --git a/markdown/dev/reference/api/path/trim/en.md b/markdown/dev/reference/api/path/trim/en.md
index 495a67047a7..e4ca44c638a 100644
--- a/markdown/dev/reference/api/path/trim/en.md
+++ b/markdown/dev/reference/api/path/trim/en.md
@@ -1,18 +1,68 @@
---
-title: trim()
+title: Path.trim()
---
+The `Path.trim()` method Returns a new Path that is this path with overlapping
+parts removed.
+
```js
Path path.trim()
```
-Returns a new Path that is this path with overlapping parts removed.
+
+
+
+```js
+({ Point, points, Path, paths, part }) => {
+
+ points.center = new Point(0, 0)
+ points.base = new Point(0, 10)
+ points.tip = new Point(0, 50)
+ points.tipCpRight = new Point(30, 50)
+ points.tipCpLeft = new Point(-30, 50)
+ paths.example = new Path().move(points.base)
+ for (let i = 0; i < 4; i++) {
+ points["base" + i] = points.base.rotate(60 * i, points.center)
+ points["tip" + i] = points.tip.rotate(60 * i, points.center)
+ points["tipCpRight" + i] = points.tipCpRight.rotate(60 * i, points.center)
+ points["tipCpLeft" + i] = points.tipCpLeft.rotate(60 * i, points.center)
+ if (i < 2) {
+ paths.example
+ .line(points["base" + i])
+ .curve(points["base" + i], points["tipCpLeft" + i], points["tip" + i])
+ .curve(
+ points["tipCpRight" + i],
+ points["base" + i],
+ points["base" + i]
+ );
+ } else {
+ paths.example
+ .line(points["base" + i])
+ .line(points["tip" + i])
+ .line(points["tipCpRight" + i])
+ .line(points["base" + i])
+ }
+ }
+
+ paths.offset = paths.example
+ .offset(10)
+ .setClass("lining dotted stroke-sm")
+
+ paths.trimmed = paths.offset
+ .trim()
+ .setClass("various stroke-xl")
+ .attr("style", "stroke-opacity: 0.5;")
+
+ return part
+}
+```
+
+
+
+## Notes
This method is typically used when [Path.offset()](/reference/api/path/offset) caused some overlap.
-
-
-
-###### Use sparsely or performance will suffer
+However, use this sparsely or performance will suffer.
This method is recursive and complex, and the performance penalty for using
it on a long/complex path will be significant.
@@ -22,54 +72,3 @@ To limit the impact of path.trim(), follow this approach:
- construct a minimal path that contains the overlap
- trim it
- now join it to the rest of your path
-
-You can see an example of this
-[in the front part of the Bruce pattern](https://github.com/freesewing/freesewing/blob/3ca5d0edfe54c7ac20aaf3af2f3544aee72f9b99/designs/bruce/src/front.js#L158).
-
-
-
-
-Example of the Path.trim() method
-
-
-```js
-let { Point, points, Path, paths } = part.shorthand();
-
-points.center = new Point(0, 0);
-points.base = new Point(0, 10);
-points.tip = new Point(0, 50);
-points.tipCpRight = new Point(30, 50);
-points.tipCpLeft = new Point(-30, 50);
-paths.example = new Path().move(points.base);
-for (let i = 0; i < 4; i++) {
- points["base" + i] = points.base.rotate(60 * i, points.center);
- points["tip" + i] = points.tip.rotate(60 * i, points.center);
- points["tipCpRight" + i] = points.tipCpRight.rotate(60 * i, points.center);
- points["tipCpLeft" + i] = points.tipCpLeft.rotate(60 * i, points.center);
- if (i < 2) {
- paths.example
- .line(points["base" + i])
- .curve(points["base" + i], points["tipCpLeft" + i], points["tip" + i])
- .curve(
- points["tipCpRight" + i],
- points["base" + i],
- points["base" + i]
- );
- } else {
- paths.example
- .line(points["base" + i])
- .line(points["tip" + i])
- .line(points["tipCpRight" + i])
- .line(points["base" + i]);
- }
-}
-
-paths.offset = paths.example
- .offset(10)
- .attr("class", "lining dotted stroke-sm");
-
-paths.trimmed = paths.offset
- .trim()
- .attr("class", "various stroke-xl")
- .attr("style", "stroke-opacity: 0.5;");
-```
diff --git a/markdown/dev/reference/api/path/unhide/en.md b/markdown/dev/reference/api/path/unhide/en.md
index 11909d5870c..8b7ae18915e 100644
--- a/markdown/dev/reference/api/path/unhide/en.md
+++ b/markdown/dev/reference/api/path/unhide/en.md
@@ -1,37 +1,35 @@
---
-title: unhide()
+title: Path.unhide()
---
+The `Path.unhide()` method unhides the path so it does appears in the output.
+
+By default, paths are not hidden. So you should only call this on path previously hidden via `Path.hide()`.
+
+## Signature
+
```js
-Path path.attr(
- string name,
- mixed value,
- bool overwrite = false
-)
+Path path.unhide()
```
-This `Path.attr()` method calls `this.attributes.add()` under the hood, but returns the Path object.
+This method is chainable as it returns the `Path` object
-This allows you to chain different calls together as in the example below.
+## Example
-If the third parameter is set to `true` it will call `this.attributes.set()` instead, thereby overwriting the value of the attribute.
+
+```js
+({ Point, points, Path, paths, part }) => {
-
-Example of the Path.attr() method
+ points.top = new Point(50, 0)
+ points.left = new Point (20,50)
+ points.right = new Point (80,50)
+
+ paths.a = new Path().move(points.top).line(points.right).setText('a')
+ paths.b = new Path().move(points.right).line(points.left).setText('b').hide().unhide()
+ paths.c = new Path().move(points.left).line(points.top).setText('c')
+
+ return part
+}
+```
-```js
-let { Point, points, Path, paths } = part.shorthand();
-
-points.B = new Point(10, 50);
-points.BCp2 = new Point(40, 10);
-points.C = new Point(90, 30);
-points.CCp1 = new Point(50, 90);
-
-paths.example = new Path()
- .move(points.B)
- .curve(points.BCp2, points.CCp1, points.C)
- .attr("class", "canvas")
- .attr("data-text", "freesewingIsMadeByJoostDeCockAndContributors")
- .attr("data-text-class", "text-xs center");
-```
diff --git a/markdown/dev/reference/api/point/addcircle/en.md b/markdown/dev/reference/api/point/addcircle/en.md
index c6c5626a6b0..99142ffdf17 100644
--- a/markdown/dev/reference/api/point/addcircle/en.md
+++ b/markdown/dev/reference/api/point/addcircle/en.md
@@ -2,11 +2,11 @@
title: Point.addCircle()
---
-Adds a circle to a Point. Under the hood, this will call `Point.attr()` as circles
-are added by setting attributes. Refer to [Drawing circles](/howtos/code/drawing-circles) for
-more details.
+The `Point.addCircle()` method adds a circle to a Point. Under the hood, this
+will call `Point.attr()` as circles are added by setting attributes. Refer to
+[Drawing circles](/howtos/code/drawing-circles) for more details.
-## Point.addCircle() signature
+## Signature
```js
Point point.addCircle(
@@ -15,12 +15,9 @@ Point point.addCircle(
)
```
-## Point.addCircle() example
-
-
-Examples of Point.addCircle(), compare this to [Point.setCircle](/reference/api/point/setcircle)
-
+## Example
+
```js
({ Point, points, part }) => {
points.a = new Point(30, 10)
@@ -41,4 +38,6 @@ Examples of Point.addCircle(), compare this to [Point.setCircle](/reference/api/
return part
}
```
+
+
diff --git a/markdown/dev/reference/api/point/addtext/en.md b/markdown/dev/reference/api/point/addtext/en.md
index 887c4242e2a..21d590cf2ed 100644
--- a/markdown/dev/reference/api/point/addtext/en.md
+++ b/markdown/dev/reference/api/point/addtext/en.md
@@ -2,11 +2,11 @@
title: Point.addText()
---
-Adds text on a Point. Under the hood, this will call `Point.attr()` as text
-is added by setting attributes. Refer to [Adding text](/howtos/code/adding-text) for
-more details.
+The `Point.addText()` method adds text on a Point. Under the hood, this will
+call `Point.attr()` as text is added by setting attributes. Refer to [Adding
+text](/howtos/code/adding-text) for more details.
-## Point.addText() signature
+## Signature
```js
Point point.addText(
@@ -15,21 +15,28 @@ Point point.addText(
)
```
-## Point.addText() example
-
-
-Examples of Point.addText(), compare this to [Point.setText](/reference/api/point/settext)
-
+## Example
+
```js
-({ Point, points, part }) => {
+({ Point, points, Path, paths, part }) => {
points.anchor = new Point(100, 25)
- .addText('supportFreesewingBecomeAPatron', 'center')
- .addText('please?')
+ .addText('FreeSewing')
+ .addText('rocks')
+
+ // Avoid the text getting cropped
+ paths.hidden = new Path()
+ .move(points.anchor)
+ .line(points.anchor.shift(0, 80))
+ .addClass('hidden')
+
return part
}
```
+
-Remember to [use translation keys, not text](/guides/best-practices/use-translation-keys)
+## Notes
+
+Remember to [use translation keys, not text](/guides/best-practices/use-translation-keys)
diff --git a/markdown/dev/reference/api/point/angle/en.md b/markdown/dev/reference/api/point/angle/en.md
index 493432026e9..199a006ecc0 100644
--- a/markdown/dev/reference/api/point/angle/en.md
+++ b/markdown/dev/reference/api/point/angle/en.md
@@ -2,33 +2,36 @@
title: Point.angle()
---
-A point's `angle()` method returns the angle (in degrees) between this point and
-the point passed into the method. An angle of 0° points to the right, and the angle increases counterclockwise.
+The `Point.angle()` method returns the angle (in degrees) between this point
+and the point passed into the method. An angle of 0° points to the right, and
+the angle increases counterclockwise.
-## Point.angle() signature
+## Signature
```js
float point.angle(Point pointB)
```
-## Point.angle() Example
+## Example
-
-An example of the Point.angle() method
+
+```js
+({ Point, points, Path, paths, part }) => {
+
+ points.sun = new Point(10, 5);
+ points.moon = points.sun.shift(-15, 70);
+ points.text = points.sun
+ .shiftFractionTowards(points.moon, 0.8)
+ .attr("data-text", points.sun.angle(points.moon)+"°")
+ .attr("data-text-class", "text-sm fill-note center");
+
+ paths.line = new Path()
+ .move(points.sun)
+ .line(points.moon)
+ .attr("class", "dashed");
+
+ return part
+}
+```
-```js
-let { Point, points, Path, paths } = part.shorthand();
-
-points.sun = new Point(10, 5);
-points.moon = points.sun.shift(-15, 70);
-points.text = points.sun
- .shiftFractionTowards(points.moon, 0.8)
- .attr("data-text", points.sun.angle(points.moon)+"°")
- .attr("data-text-class", "text-sm fill-note center");
-
-paths.line = new Path()
- .move(points.sun)
- .line(points.moon)
- .attr("class", "dashed");
-```
diff --git a/markdown/dev/reference/api/point/attr/en.md b/markdown/dev/reference/api/point/attr/en.md
index 1f0de570cd2..92843e0927e 100644
--- a/markdown/dev/reference/api/point/attr/en.md
+++ b/markdown/dev/reference/api/point/attr/en.md
@@ -2,10 +2,11 @@
title: Point.attr()
---
-Adds an attribute to the point, and returns the original point. Setting the third parameter
-to `true` will replace the value of the attribute instead of adding it.
+The `Point.attr()` method adds an attribute to the point, and returns the
+original point. Setting the third parameter to `true` will replace the value of
+the attribute instead of adding it.
-## Point.attr() signature
+## Signature
```js
Point point.attr(
@@ -15,21 +16,29 @@ Point point.attr(
)
```
-The `Point.attr()` method calls [`this.attributes.add()`](/reference/api/attributes/add/) under the hood, but returns the `Point` object.
-This allows you to chain different calls together as in the example below.
-
If the third parameter is set to `true` it will call [`this.attributes.set()`](/reference/api/attributes/set/) instead, thereby overwriting the value of the attribute.
-## Point.attr() example
-
-An example of the Point.attr() method
+This method is chainable as it returns the `Path` object
+
+## Example
+
+
+```js
+({ Point, points, Path, paths, part }) => {
+
+ points.anchor = new Point(100, 25)
+ .attr('data-text', 'FreeSewing')
+ .attr('data-text', 'rocks')
+
+ // Avoid the text getting cropped
+ paths.hidden = new Path()
+ .move(points.anchor)
+ .line(points.anchor.shift(0, 80))
+ .addClass('hidden')
+
+ return part
+}
+```
-```js
-let { Point, points } = part.shorthand();
-
-points.anchor = new Point(100, 25)
- .attr("data-text", "freesewingIsMadeByJoostDeCockAndContributors")
- .attr("data-text-class", "center");
-```
diff --git a/markdown/dev/reference/api/point/clone/en.md b/markdown/dev/reference/api/point/clone/en.md
index 91cec6088b8..10cc77cae88 100644
--- a/markdown/dev/reference/api/point/clone/en.md
+++ b/markdown/dev/reference/api/point/clone/en.md
@@ -2,37 +2,45 @@
title: Point.clone()
---
-Returns a new `Point` with the same coordinates and attributes as the original point.
+The `Point.clone()` method returns a new `Point` with the same coordinates and
+attributes as the original point.
-## Point.clone() signature
+## Signature
```js
Point point.clone()
```
-
+This method is chainable as it returns the `Point` object
-###### Copy vs clone
-
-The [`Point.copy()`](/reference/api/point/copy/) method will only copy the point's coordinates, whereas this
-`Point.clone()` method will also copy its attributes.
-
-
-
-## Point.clone() example
-
-
-An example of the Point.clone() method
-
+## Example
+
```js
- let { Point, points, Snippet, snippets } = part.shorthand();
+({ Point, points, Path, paths, Snippet, snippets, part }) => {
points.A = new Point(25, 25)
- .attr("data-text", "Point A")
- .attr("data-text-class", "text-xl")
- .attr("data-text-fill-opacity", "0.5");
- points.B = points.A.clone().attr("data-text", "Point B");
+ .setText("Point A", "text-xl")
+ .attr("data-text-fill-opacity", "0.5")
+ points.B = points.A.clone().setText("Point B")
- snippets.x = new Snippet("notch", points.A);
+ snippets.x = new Snippet("notch", points.A)
+
+ // Avoid the text getting cropped
+ paths.hidden = new Path()
+ .move(new Point(20,10))
+ .move(new Point(75,30))
+ .addClass('hidden')
+
+ return part
+}
```
+
+
+
+## Notes
+
+The [`Point.copy()`](/reference/api/point/copy/) method will only copy the
+point's coordinates, whereas this `Point.clone()` method will also copy its
+attributes.
+
diff --git a/markdown/dev/reference/api/point/copy/en.md b/markdown/dev/reference/api/point/copy/en.md
index 41f80e76887..ea95531f2d7 100644
--- a/markdown/dev/reference/api/point/copy/en.md
+++ b/markdown/dev/reference/api/point/copy/en.md
@@ -2,37 +2,43 @@
title: Point.copy()
---
-A point's `copy()` method returns a new point with the same coordinates as the original point.
-This method does _not_ copy any attributes the original point may have.
+The `Point.copy()` method returns a new point with the same coordinates as the
+original point. This method does _not_ copy any attributes the original point
+may have.
-## Point.copy() signature
+## Signature
```js
Point point.copy()
```
-
-
-###### Copy vs clone
-
-this `Point.copy()` method will only copy the point's coordinates.
-To also copy the attributes, use [`Point.clone()`](/reference/api/point/clone/) instead.
-
-
## Point.copy() example
-
-An example of the Point.copy() method
+
+```js
+({ Point, points, Path, paths, Snippet, snippets, part }) => {
+
+ points.A = new Point(25, 25)
+ .setText("Point A", "text-xl")
+ .attr("data-text-fill-opacity", "0.5")
+ points.B = points.A.clone().setText("Point B")
+
+ snippets.x = new Snippet("notch", points.A)
+
+ // Avoid the text getting cropped
+ paths.hidden = new Path()
+ .move(new Point(20,10))
+ .move(new Point(75,30))
+ .addClass('hidden')
+
+ return part
+}
+```
-```js
-let { Point, points, Snippet, snippets } = part.shorthand();
-points.A = new Point(50, 25)
- .attr("data-text", "Point A")
- .attr("data-text-class", "text-xl");
-points.B = points.A.copy().attr("data-text", "Point B");
+## Notes
-snippets.x = new Snippet("notch", points.A);
-```
+The `Point.copy()` method will only copy the point's coordinates.
+To also copy the attributes, use [`Point.clone()`](/reference/api/point/clone/) instead.
diff --git a/markdown/dev/reference/api/point/dist/en.md b/markdown/dev/reference/api/point/dist/en.md
index aeee3e00553..724b297e2ae 100644
--- a/markdown/dev/reference/api/point/dist/en.md
+++ b/markdown/dev/reference/api/point/dist/en.md
@@ -2,35 +2,35 @@
title: Point.dist()
---
-A point's `dist()` method returns the distance (in mm) between this point and the point you pass it.
+The `Point.dist()` method returns the distance (in mm) between this point and
+the point you pass it.
-## Point.dist() signature
+## Signature
```js
float point.dist(Point point)
```
-## Point.dist() example
+## Example
-
-An example of the Point.dist() method
+
+```js
+({ Point, points, Path, paths, units, part }) => {
+
+ points.from = new Point(10, 10)
+ points.to = new Point(80, 70)
+
+ points.text = points.from
+ .shiftFractionTowards(points.to, 0.6)
+ .setText(units(points.from.dist(points.to)), 'text-sm fill-note center')
+
+ paths.line = new Path()
+ .move(points.from)
+ .line(points.to)
+ .attr('class', 'dashed')
+
+ return part
+}
+```
-```js
-let { Point, points, Path, paths } = part.shorthand()
-
-points.from = new Point(10, 10)
-points.to = new Point(80, 70)
-
-points.text = points.from
- .shiftFractionTowards(points.to, 0.6)
- .attr('data-text', points.from.dist(points.to) + 'mm')
- .attr('data-text-class', 'text-sm fill-note center')
-
-paths.line = new Path()
- .move(points.from)
- .line(points.to)
- .attr('class', 'dashed')
-
-return part
-```
diff --git a/packages/core/src/path.mjs b/packages/core/src/path.mjs
index 8e6f23954be..3110731ebb5 100644
--- a/packages/core/src/path.mjs
+++ b/packages/core/src/path.mjs
@@ -67,6 +67,20 @@ Path.prototype.addClass = function (className = false) {
return this
}
+/**
+ * A chainable way to add text to a Path
+ *
+ * @param {string} text - The text to add to the Path
+ * @param {string} className - The CSS classes to apply to the text
+ * @return {Path} this - The Path instance
+ */
+Path.prototype.addText = function (text = '', className = false) {
+ this.attributes.add('data-text', text)
+ if (className) this.attributes.add('data-text-class', className)
+
+ return this
+}
+
/**
* Returns the SVG pathstring for this path
*
@@ -536,7 +550,7 @@ Path.prototype.offset = function (distance) {
*
* @return {object} reverse - A Path instance that is the reversed version of this Path
*/
-Path.prototype.reverse = function () {
+Path.prototype.reverse = function (cloneAttributes = false) {
let sections = []
let current
let closed = false
@@ -555,6 +569,7 @@ Path.prototype.reverse = function () {
let rev = new Path().__withLog(this.log).move(current)
for (let section of sections.reverse()) rev.ops.push(section.ops[1])
if (closed) rev.close()
+ if (cloneAttributes) rev.attributes = this.attributes.clone()
return rev
}
@@ -613,6 +628,19 @@ Path.prototype.setHidden = function (hidden = false) {
return this
}
+/**
+ * A chainable way to set text on a Path
+ *
+ * @param {string} text - The text to add to the Path
+ * @param {string} className - The CSS classes to apply to the text
+ * @return {Path} this - The Path instance
+ */
+Path.prototype.setText = function (text = '', className = false) {
+ this.attributes.set('data-text', text)
+ if (className) this.attributes.set('data-text-class', className)
+
+ return this
+}
/**
* Returns a point that lies at distance along this Path
*
diff --git a/packages/core/src/pattern.mjs b/packages/core/src/pattern.mjs
index 67c6a7280a3..ddfd9344078 100644
--- a/packages/core/src/pattern.mjs
+++ b/packages/core/src/pattern.mjs
@@ -149,8 +149,9 @@ Pattern.prototype.draft = function () {
this.setStores[set].log.error(
`Unable to draft pattern part __${partName}__. Part.draft() is not callable`
)
- this.parts[set][partName].hidden =
- this.parts[set][partName].hidden === true ? true : !this.__wants(partName, set)
+ // FIXME: THis won't work not that this is immutable
+ // But is it still needed?
+ // this.parts[set][partName].hidden === true ? true : !this.__wants(partName, set)
} else {
this.setStores[set].log.debug(
`Part \`${partName}\` is not needed. Skipping draft and setting hidden to \`true\``
@@ -180,6 +181,7 @@ Pattern.prototype.getConfig = function () {
* @return {object} this - The Pattern instance
*/
Pattern.prototype.getRenderProps = function () {
+ this.store.log.info('Gathering render props')
// Run pre-render hook
let svg = new Svg(this)
svg.hooks = this.hooks
@@ -193,15 +195,6 @@ Pattern.prototype.getRenderProps = function () {
props.height = this.height
props.autoLayout = this.autoLayout
props.settings = this.settings
- props.logs = {
- pattern: this.store.logs,
- sets: this.setStores.map((store) => ({
- debug: store.logs.debug,
- info: store.logs.info,
- error: store.logs.error,
- warning: store.logs.warning,
- })),
- }
props.parts = []
for (const set of this.parts) {
const setParts = {}
@@ -211,6 +204,10 @@ Pattern.prototype.getRenderProps = function () {
...set[p].asProps(),
store: this.setStores[set[p].set],
}
+ } else if (this.setStores[set?.set]) {
+ this.setStores[set.set].log.info(
+ `Part${p} is hidden in set ${set.set}. Not adding to render props`
+ )
}
}
props.parts.push(setParts)
@@ -219,7 +216,16 @@ Pattern.prototype.getRenderProps = function () {
for (let s in this.stacks) {
if (!this.__isStackHidden(s)) {
props.stacks[s] = this.stacks[s].asProps()
- }
+ } else this.store.log.info(`Stack ${s} is hidden. Skipping in render props.`)
+ }
+ props.logs = {
+ pattern: this.store.logs,
+ sets: this.setStores.map((store) => ({
+ debug: store.logs.debug,
+ info: store.logs.info,
+ error: store.logs.error,
+ warning: store.logs.warning,
+ })),
}
return props
@@ -500,40 +506,48 @@ function getPluginName(plugin) {
* @return {Pattern} this - The Pattern instance
*/
Pattern.prototype.__addPartPlugins = function (part) {
+ if (!part.plugins) return this
if (!this.config.plugins) this.config.plugins = {}
const plugins = { ...this.config.plugins }
- if (!part.plugins) return this
// Side-step immutability of the part object to ensure plugins is an array
let partPlugins = part.plugins
if (!Array.isArray(partPlugins)) partPlugins = [partPlugins]
- for (const plugin of partPlugins) plugins[getPluginName(plugin)] = plugin
+ // Go through list of part plugins
for (let plugin of partPlugins) {
const name = getPluginName(plugin)
+ this.store.log.debug(
+ plugin.plugin
+ ? `🔌 Resolved __${name}__ conditional plugin in \`${part.name}\``
+ : `🔌 Resolved __${name}__ plugin in \`${part.name}\``
+ )
// Handle [plugin, data] scenario
if (Array.isArray(plugin)) {
const pluginObj = { ...plugin[0], data: plugin[1] }
plugin = pluginObj
}
- if (plugin.plugin)
- this.store.log.debug(`🔌 Resolved __${name}__ conditional plugin in \`${part.name}\``)
- else this.store.log.debug(`🔌 Resolved __${name}__ plugin in \`${part.name}\``)
- // Do not overwrite an existing plugin with a conditional plugin unless it is also conditional
- if (plugin.plugin && plugin.condition) {
- if (!plugins[name]) {
- plugins[name] = plugin
- this.store.log.info(`Plugin \`${name}\` was conditionally added.`)
- } else if (plugins[name]?.condition) {
- plugins[name + '_'] = plugin
- this.store.log.info(
- `Plugin \`${name}\` was conditionally added again. Renaming to ${name}_.`
- )
- } else
- this.store.log.info(
- `Plugin \`${name}\` was requested conditionally, but is already added explicitly. Not loading.`
- )
- } else {
+ if (!plugins[name]) {
+ // New plugin, so we load it
plugins[name] = plugin
- this.store.log.info(`Plugin \`${name}\` was added.`)
+ this.store.log.info(
+ plugin.condition
+ ? `New plugin conditionally added: \`${name}\``
+ : `New plugin added: \`${name}\``
+ )
+ } else {
+ // Existing plugin, takes some more work
+ if (plugin.plugin && plugin.condition) {
+ // Multiple instances of the same plugin with different conditions
+ // will all be added, so we need to change the name.
+ if (plugins[name]?.condition) {
+ plugins[name + '_'] = plugin
+ this.store.log.info(
+ `Plugin \`${name}\` was conditionally added again. Renaming to ${name}_.`
+ )
+ } else
+ this.store.log.info(
+ `Plugin \`${name}\` was requested conditionally, but is already added explicitly. Not loading.`
+ )
+ }
}
}
@@ -697,6 +711,7 @@ Pattern.prototype.__isPartHidden = function (partName) {
if (this.__designParts?.[partName]?.hideAll) return true
if (this.__mutated.partHide?.[partName]) return true
if (this.__mutated.partHideAll?.[partName]) return true
+ if (this.parts?.[this.activeSet]?.[partName]?.hidden) return true
return false
}
@@ -722,6 +737,7 @@ Pattern.prototype.__isStackHidden = function (stackName) {
if (this.__designParts?.[partName]?.hideAll) return true
if (this.__mutated.partHide?.[partName]) return true
if (this.__mutated.partHideAll?.[partName]) return true
+ if (this.parts?.[this.activeSet]?.[partName]?.hidden) return true
}
return false
@@ -1230,7 +1246,7 @@ Pattern.prototype.__resolveParts = function (count = 0, distance = 0) {
if (part.hideAll) this.__mutated.partHide[part.name] = true
// Inject (from)
if (part.from) {
- if (part.hideDependencies || part.hideAll) {
+ if (part.hideDependencies || this.__mutated.partHideAll[name]) {
// Don't mutate the part, keep this info in the pattern object
this.__mutated.partHide[part.from.name] = true
this.__mutated.partHideAll[part.from.name] = true
@@ -1249,9 +1265,6 @@ Pattern.prototype.__resolveParts = function (count = 0, distance = 0) {
this.__addDependency(name, part, dep)
}
} else {
- if (part.hideDependencies) {
- this.__mutated.partHide[part.after.name] = true
- }
this.__mutated.partDistance[part.after.name] = distance
this.__designParts[part.after.name] = part.after
this.__addDependency(name, part, part.after)
diff --git a/packages/core/src/point.mjs b/packages/core/src/point.mjs
index 744b9c18935..0a4d5e3ad8a 100644
--- a/packages/core/src/point.mjs
+++ b/packages/core/src/point.mjs
@@ -50,6 +50,7 @@ Point.prototype.addText = function (text = '', className = false) {
return this.__check()
}
+
/**
* Returns the angle between this Point and that Point
*
@@ -202,7 +203,7 @@ Point.prototype.setCircle = function (radius = false, className = false) {
}
/**
- * A chainable way to add text to a Point
+ * A chainable way to set text on a Point
*
* @param {string} text - The text to add to the Point
* @param {string} className - The CSS classes to apply to the text
diff --git a/packages/core/tests/pattern-init.test.mjs b/packages/core/tests/pattern-init.test.mjs
index 27116f877c2..7af41d5e2d9 100644
--- a/packages/core/tests/pattern-init.test.mjs
+++ b/packages/core/tests/pattern-init.test.mjs
@@ -702,6 +702,9 @@ describe('Pattern', () => {
it('Should check whether created parts get the pattern context', () => {
let partContext
+ const plugin = {
+ name: 'example',
+ }
const part = {
name: 'test',
draft: ({ Point, paths, Path, part, context }) => {
@@ -710,6 +713,7 @@ describe('Pattern', () => {
return part
},
+ plugins: [plugin],
}
const Pattern = new Design({ parts: [part], data: { name: 'test', version: '1' } })
const pattern = new Pattern()
diff --git a/plugins/plugin-bust/src/index.mjs b/plugins/plugin-bust/src/index.mjs
index 1c0599f7cb4..0e6cd5ac18f 100644
--- a/plugins/plugin-bust/src/index.mjs
+++ b/plugins/plugin-bust/src/index.mjs
@@ -4,12 +4,12 @@ export const plugin = {
name,
version,
hooks: {
- preDraft: ({ settings }) => {
- for (const set of settings) {
- if (set.measurements) {
- if (typeof set.measurements.bust === 'undefined') {
- set.measurements.bust = set.measurements.chest
- set.measurements.chest = set.measurements.highBust
+ preDraft: function ({ settings }) {
+ for (const i in settings) {
+ if (settings[i].measurements) {
+ if (typeof settings[i].measurements.bust === 'undefined') {
+ settings[i].measurements.bust = settings[i].measurements.chest
+ settings[i].measurements.chest = settings[i].measurements.highBust
}
}
}
diff --git a/plugins/plugin-gore/src/index.mjs b/plugins/plugin-gore/src/index.mjs
index 9cc58b84aa7..8d1efc9ff1c 100644
--- a/plugins/plugin-gore/src/index.mjs
+++ b/plugins/plugin-gore/src/index.mjs
@@ -4,55 +4,48 @@ export const plugin = {
name,
version,
macros: {
- gore: function (so) {
+ gore: function (so, { points, paths, Path }) {
const from = so.from
const gores = so.gores
const radius = so.radius //radius of the sphere
const prefix = so.prefix
const extraLength = so.extraLength //the length of the straight section after a complete semisphere
- this.points[prefix + 'p1'] = from.shift(0, (radius * Math.PI) / 2 + extraLength)
- this.points[prefix + 'Cp1'] = this.points[prefix + 'p1'].shift(
+ points[prefix + 'p1'] = from.shift(0, (radius * Math.PI) / 2 + extraLength)
+ points[prefix + 'Cp1'] = points[prefix + 'p1'].shift(
180 - 180 / gores,
radius / 2 / Math.cos(Math.PI / gores)
)
- this.points[prefix + 'p3'] = from.shift(90, (radius * Math.PI) / gores)
- this.points[prefix + 'p2'] = this.points[prefix + 'p3'].shift(0, extraLength)
- this.points[prefix + 'Cp2'] = this.points[prefix + 'p2'].shift(
- 0,
- (radius * (Math.PI - 2)) / 2
- )
+ points[prefix + 'p3'] = from.shift(90, (radius * Math.PI) / gores)
+ points[prefix + 'p2'] = points[prefix + 'p3'].shift(0, extraLength)
+ points[prefix + 'Cp2'] = points[prefix + 'p2'].shift(0, (radius * (Math.PI - 2)) / 2)
if (extraLength < 0) {
//top curve used to calculate the new points if extraLength < 0
- this.paths.auxiliaryPath = new this.Path()
- .move(this.points[prefix + 'p1'])
- .curve(
- this.points[prefix + 'Cp1'],
- this.points[prefix + 'Cp2'],
- this.points[prefix + 'p2']
- )
+ paths.auxiliaryPath = new Path()
+ .move(points[prefix + 'p1'])
+ .curve(points[prefix + 'Cp1'], points[prefix + 'Cp2'], points[prefix + 'p2'])
.hide()
- this.points[prefix + 'p2'] = this.paths.auxiliaryPath.intersectsX(0)[0] //the new point p2 is the one in which the auxiliary curve intersects x=0
- this.paths.auxiliaryPath = this.paths.auxiliaryPath.split(this.points[prefix + 'p2'])[0] //the auxiliary curve is split
- this.points[prefix + 'Cp1'] = this.paths.auxiliaryPath.ops[1].cp1 //the new control points are those of the new curve
- this.points[prefix + 'Cp2'] = this.paths.auxiliaryPath.ops[1].cp2
- this.points[prefix + 'p3'] = this.points[prefix + 'p2'].clone()
+ points[prefix + 'p2'] = paths.auxiliaryPath.intersectsX(0)[0] //the new point p2 is the one in which the auxiliary curve intersects x=0
+ paths.auxiliaryPath = paths.auxiliaryPath.split(points[prefix + 'p2'])[0] //the auxiliary curve is split
+ points[prefix + 'Cp1'] = paths.auxiliaryPath.ops[1].cp1 //the new control points are those of the new curve
+ points[prefix + 'Cp2'] = paths.auxiliaryPath.ops[1].cp2
+ points[prefix + 'p3'] = points[prefix + 'p2'].clone()
}
//the seam path is generated
- this.paths[prefix + 'seam'] = new this.Path()
+ paths[prefix + 'seam'] = new Path()
.move(from)
- .line(this.points[prefix + 'p1'])
- .curve(this.points[prefix + 'Cp1'], this.points[prefix + 'Cp2'], this.points[prefix + 'p2'])
- .line(this.points[prefix + 'p3'])
+ .line(points[prefix + 'p1'])
+ .curve(points[prefix + 'Cp1'], points[prefix + 'Cp2'], points[prefix + 'p2'])
+ .line(points[prefix + 'p3'])
.line(from)
.close()
.attr('class', so.class ? so.class : '')
- if (so?.hidden) this.paths[prefix + 'seam'].hide()
- else this.paths[prefix + 'seam'].unhide()
+ if (so?.hidden) paths[prefix + 'seam'].hide()
+ else paths[prefix + 'seam'].unhide()
},
},
}
diff --git a/plugins/plugin-gore/tests/plugin.test.mjs b/plugins/plugin-gore/tests/plugin.test.mjs
index 1ff95ff2b0f..2132fb05b69 100644
--- a/plugins/plugin-gore/tests/plugin.test.mjs
+++ b/plugins/plugin-gore/tests/plugin.test.mjs
@@ -8,7 +8,7 @@ describe('Gore Plugin Tests', () => {
it('Should create a default gore', () => {
const part = {
name: 'test',
- draft: ({ Point, points, macro }) => {
+ draft: ({ Point, points, macro, part }) => {
points.anchorPoint = new Point(50, 50)
macro('gore', {
from: points.anchorPoint,
@@ -17,12 +17,15 @@ describe('Gore Plugin Tests', () => {
extraLength: 0,
prefix: 'gore',
})
+
+ return part
},
+ plugins: [plugin],
}
- const Test = new Design({ plugins: [plugin], parts: [part] })
+ const Test = new Design({ parts: [part] })
const pattern = new Test()
pattern.draft()
- let c = pattern.parts.test.points
+ let c = pattern.parts[0].test.points
expect(round(c.gorep1.y)).to.equal(50)
expect(round(c.gorep2.x)).to.equal(50)
expect(round(c.gorep2.y)).to.equal(30.37)
@@ -33,7 +36,7 @@ describe('Gore Plugin Tests', () => {
it('Should use a configurable number of gores', () => {
const part = {
name: 'test',
- draft: ({ Point, points, macro }) => {
+ draft: ({ Point, points, macro, part }) => {
points.anchorPoint = new Point(50, 50)
macro('gore', {
from: points.anchorPoint,
@@ -42,12 +45,15 @@ describe('Gore Plugin Tests', () => {
extraLength: 0,
prefix: 'gore',
})
+
+ return part
},
+ plugins: [plugin],
}
- const Test = new Design({ plugins: [plugin], parts: [part] })
+ const Test = new Design({ parts: [part] })
const pattern = new Test()
pattern.draft()
- let c = pattern.parts.test.points
+ let c = pattern.parts[0].test.points
expect(round(c.gorep1.x)).to.equal(89.27)
expect(round(c.gorep1.y)).to.equal(50)
expect(round(c.gorep2.x)).to.equal(50)
@@ -59,7 +65,7 @@ describe('Gore Plugin Tests', () => {
it('Should use a configurable extra length', () => {
const part = {
name: 'test',
- draft: ({ Point, points, macro }) => {
+ draft: ({ Point, points, macro, part }) => {
points.anchorPoint = new Point(50, 50)
macro('gore', {
from: points.anchorPoint,
@@ -68,12 +74,15 @@ describe('Gore Plugin Tests', () => {
extraLength: 20,
prefix: 'gore',
})
+
+ return part
},
+ plugins: [plugin],
}
- const Test = new Design({ plugins: [plugin], parts: [part] })
+ const Test = new Design({ parts: [part] })
const pattern = new Test()
pattern.draft()
- let c = pattern.parts.test.points
+ let c = pattern.parts[0].test.points
expect(round(c.gorep1.x)).to.equal(109.27)
expect(round(c.gorep1.y)).to.equal(50)
expect(round(c.gorep2.x)).to.equal(70)
@@ -85,7 +94,7 @@ describe('Gore Plugin Tests', () => {
it('Should use a configurable radius', () => {
const part = {
name: 'test',
- draft: ({ Point, points, macro }) => {
+ draft: ({ Point, points, macro, part }) => {
points.anchorPoint = new Point(50, 50)
macro('gore', {
from: points.anchorPoint,
@@ -94,12 +103,15 @@ describe('Gore Plugin Tests', () => {
extraLength: 0,
prefix: 'gore',
})
+
+ return part
},
+ plugins: [plugin],
}
- const Test = new Design({ plugins: [plugin], parts: [part] })
+ const Test = new Design({ parts: [part] })
const pattern = new Test()
pattern.draft()
- let c = pattern.parts.test.points
+ let c = pattern.parts[0].test.points
expect(round(c.gorep1.x)).to.equal(97.12)
expect(round(c.gorep1.y)).to.equal(50)
expect(round(c.gorep2.x)).to.equal(50)
@@ -111,7 +123,7 @@ describe('Gore Plugin Tests', () => {
it('Should generate a seam path', () => {
const part = {
name: 'test',
- draft: ({ Point, points, macro }) => {
+ draft: ({ Point, points, macro, part }) => {
points.anchorPoint = new Point(50, 50)
macro('gore', {
from: points.anchorPoint,
@@ -120,12 +132,15 @@ describe('Gore Plugin Tests', () => {
extraLength: 0,
prefix: 'gore',
})
+
+ return part
},
+ plugins: [plugin],
}
- const Test = new Design({ plugins: [plugin], parts: [part] })
+ const Test = new Design({ parts: [part] })
const pattern = new Test()
pattern.draft()
- let c = pattern.parts.test.paths.goreseam.ops
+ let c = pattern.parts[0].test.paths.goreseam.ops
expect(round(c[1].to.x)).to.equal(89.27)
expect(round(c[1].to.y)).to.equal(50)
expect(round(c[2].to.x)).to.equal(50)
diff --git a/plugins/plugin-grainline/src/index.mjs b/plugins/plugin-grainline/src/index.mjs
index 854fc7cdf6a..eb56aebda63 100644
--- a/plugins/plugin-grainline/src/index.mjs
+++ b/plugins/plugin-grainline/src/index.mjs
@@ -19,19 +19,18 @@ export const plugin = {
},
},
macros: {
- grainline: function (so = {}) {
+ grainline: function (so = {}, { points, paths, Path, complete, setGrain }) {
if (so === false) {
- delete this.points.grainlineFrom
- delete this.points.grainlineTo
- delete this.paths.grainline
- this.setGrain(90) // Restoring default
+ delete points.grainlineFrom
+ delete points.grainlineTo
+ delete paths.grainline
+ setGrain(90) // Restoring default
return true
}
so = {
...dflts,
...so,
}
- const { points, complete, setGrain } = this.shorthand()
// setGrain relies on plugin-cutlist
if (typeof setGrain === 'function') {
setGrain(so.from.angle(so.to))
@@ -39,7 +38,7 @@ export const plugin = {
if (complete) {
points.grainlineFrom = so.from.shiftFractionTowards(so.to, 0.05)
points.grainlineTo = so.to.shiftFractionTowards(so.from, 0.05)
- this.paths.grainline = new this.Path()
+ paths.grainline = new Path()
.move(points.grainlineFrom)
.line(points.grainlineTo)
.attr('class', 'note')
diff --git a/plugins/plugin-grainline/tests/plugin.test.mjs b/plugins/plugin-grainline/tests/plugin.test.mjs
index 32650f516cc..f8061011dbf 100644
--- a/plugins/plugin-grainline/tests/plugin.test.mjs
+++ b/plugins/plugin-grainline/tests/plugin.test.mjs
@@ -8,19 +8,22 @@ describe('Grainline Plugin Tests', () => {
it('Should run the default grainline macro', () => {
const part = {
name: 'test',
- draft: ({ points, Point, macro }) => {
+ draft: ({ points, Point, macro, part }) => {
points.from = new Point(10, 20)
points.to = new Point(10, 230)
macro('grainline', {
from: points.from,
to: points.to,
})
+
+ return part
},
+ plugins: [plugin],
}
- const Pattern = new Design({ plugins: [plugin], parts: [part] })
+ const Pattern = new Design({ parts: [part] })
const pattern = new Pattern()
pattern.draft()
- const c = pattern.parts.test.paths.grainline
+ const c = pattern.parts[0].test.paths.grainline
expect(c.attributes.get('class')).to.equal('note')
expect(c.attributes.get('marker-start')).to.equal('url(#grainlineFrom)')
expect(c.attributes.get('marker-end')).to.equal('url(#grainlineTo)')
diff --git a/plugins/plugin-measurements/src/index.mjs b/plugins/plugin-measurements/src/index.mjs
index c25950326a9..5e2ac7a8d1c 100644
--- a/plugins/plugin-measurements/src/index.mjs
+++ b/plugins/plugin-measurements/src/index.mjs
@@ -5,31 +5,31 @@ export const plugin = {
version,
hooks: {
preDraft: function ({ settings }) {
- if (settings.measurements) {
- if (
- typeof settings.measurements.seatBack !== 'undefined' &&
- typeof settings.measurements.seat !== 'undefined'
- ) {
- settings.measurements.seatFront =
- settings.measurements.seat - settings.measurements.seatBack
- settings.measurements.seatBackArc = settings.measurements.seatBack / 2
- settings.measurements.seatFrontArc = settings.measurements.seatFront / 2
- }
- if (
- typeof settings.measurements.waist !== 'undefined' &&
- typeof settings.measurements.waistBack !== 'undefined'
- ) {
- settings.measurements.waistFront =
- settings.measurements.waist - settings.measurements.waistBack
- settings.measurements.waistBackArc = settings.measurements.waistBack / 2
- settings.measurements.waistFrontArc = settings.measurements.waistFront / 2
- }
- if (
- typeof settings.measurements.crossSeam !== 'undefined' &&
- typeof settings.measurements.crossSeamFront !== 'undefined'
- ) {
- settings.measurements.crossSeamBack =
- settings.measurements.crossSeam - settings.measurements.crossSeamFront
+ for (const set of settings) {
+ if (set.measurements) {
+ if (
+ typeof set.measurements.seatBack !== 'undefined' &&
+ typeof set.measurements.seat !== 'undefined'
+ ) {
+ set.measurements.seatFront = set.measurements.seat - set.measurements.seatBack
+ set.measurements.seatBackArc = set.measurements.seatBack / 2
+ set.measurements.seatFrontArc = set.measurements.seatFront / 2
+ }
+ if (
+ typeof set.measurements.waist !== 'undefined' &&
+ typeof set.measurements.waistBack !== 'undefined'
+ ) {
+ set.measurements.waistFront = set.measurements.waist - set.measurements.waistBack
+ set.measurements.waistBackArc = set.measurements.waistBack / 2
+ set.measurements.waistFrontArc = set.measurements.waistFront / 2
+ }
+ if (
+ typeof set.measurements.crossSeam !== 'undefined' &&
+ typeof set.measurements.crossSeamFront !== 'undefined'
+ ) {
+ set.measurements.crossSeamBack =
+ set.measurements.crossSeam - set.measurements.crossSeamFront
+ }
}
}
},
diff --git a/plugins/plugin-measurements/tests/plugin.test.mjs b/plugins/plugin-measurements/tests/plugin.test.mjs
index 2d558136917..005a5e57df9 100644
--- a/plugins/plugin-measurements/tests/plugin.test.mjs
+++ b/plugins/plugin-measurements/tests/plugin.test.mjs
@@ -12,62 +12,47 @@ const measurements = {
crossSeam: 100,
crossSeamFront: 42,
}
-
const part = {
name: 'test',
- draft: ({ points, Point }) => {
+ draft: ({ points, Point, part }) => {
points.from = new Point(10, 20)
points.to = new Point(10, 230)
+
+ return part
},
+ measurements: Object.keys(measurements),
+ plugins: [plugin],
}
-const Pattern = new Design({ plugins: [plugin], parts: [part] })
-const pattern = new Pattern({ measurements })
-pattern.draft()
+const Pattern = new Design({ parts: [part] })
describe('Measurements Plugin Tests', () => {
it('Should set the extra measurements', () => {
- expect(pattern.settings.measurements.seatFront).to.equal(40)
- expect(pattern.settings.measurements.seatFrontArc).to.equal(20)
- expect(pattern.settings.measurements.seatBackArc).to.equal(30)
- expect(pattern.settings.measurements.waistFront).to.equal(55)
- expect(pattern.settings.measurements.waistFrontArc).to.equal(27.5)
- expect(pattern.settings.measurements.crossSeamBack).to.equal(58)
+ const pattern = new Pattern({ measurements })
+ pattern.draft()
+ expect(pattern.settings[0].measurements.seatFront).to.equal(40)
+ expect(pattern.settings[0].measurements.seatFrontArc).to.equal(20)
+ expect(pattern.settings[0].measurements.seatBackArc).to.equal(30)
+ expect(pattern.settings[0].measurements.waistFront).to.equal(55)
+ expect(pattern.settings[0].measurements.waistFrontArc).to.equal(27.5)
+ expect(pattern.settings[0].measurements.crossSeamBack).to.equal(58)
})
it('Should calculate seatFront from seat and seatBack', function () {
- const testPattern = new Design({
- measurements: {},
- plugins: [plugin],
- })
- const pattern = new testPattern()
- const userMeasurements = { seat: 50, seatBack: 20 }
- pattern.settings.measurements = userMeasurements
+ const pattern = new Pattern({ measurements: { seat: 50, seatBack: 20 } })
pattern.draft()
- expect(pattern.settings.measurements.seatFront).to.equal(30)
+ expect(pattern.settings[0].measurements.seatFront).to.equal(30)
})
it('Should calculate waistFrontArc and waistBackArc from waist and waistBack', function () {
- const testPattern = new Design({
- measurements: {},
- plugins: [plugin],
- })
- const pattern = new testPattern()
- const userMeasurements = { waist: 50, waistBack: 20 }
- pattern.settings.measurements = userMeasurements
+ const pattern = new Pattern({ measurements: { waist: 50, waistBack: 20 } })
pattern.draft()
- expect(pattern.settings.measurements.waistFrontArc).to.equal(15)
- expect(pattern.settings.measurements.waistBackArc).to.equal(10)
+ expect(pattern.settings[0].measurements.waistFrontArc).to.equal(15)
+ expect(pattern.settings[0].measurements.waistBackArc).to.equal(10)
})
it('Should calculate crossSeamBack from crossSeam and crossSeamFront', function () {
- const testPattern = new Design({
- measurements: {},
- plugins: [plugin],
- })
- const pattern = new testPattern()
- const userMeasurements = { crossSeam: 50, crossSeamFront: 20 }
- pattern.settings.measurements = userMeasurements
+ const pattern = new Pattern({ measurements: { crossSeam: 50, crossSeamFront: 20 } })
pattern.draft()
- expect(pattern.settings.measurements.crossSeamBack).to.equal(30)
+ expect(pattern.settings[0].measurements.crossSeamBack).to.equal(30)
})
})
diff --git a/plugins/plugin-mirror/tests/plugin.test.mjs b/plugins/plugin-mirror/tests/plugin.test.mjs
index 1a6b755410a..3dbee0a1de5 100644
--- a/plugins/plugin-mirror/tests/plugin.test.mjs
+++ b/plugins/plugin-mirror/tests/plugin.test.mjs
@@ -7,7 +7,7 @@ const expect = chai.expect
describe('Mirror Plugin Tests', () => {
const part = {
name: 'test',
- draft: ({ points, Point, macro, paths, Path }) => {
+ draft: ({ points, Point, macro, paths, Path, part }) => {
points.mirrorA = new Point(-100, -100)
points.mirrorB = new Point(100, 100)
points.a = new Point(10, 20)
@@ -23,58 +23,61 @@ describe('Mirror Plugin Tests', () => {
macro('mirror', settings)
macro('mirror', { ...settings, prefix: 'test' })
macro('mirror', { ...settings, clone: false })
+
+ return part
},
+ plugins: [plugin],
}
- const Pattern = new Design({ plugins: [plugin], parts: [part] })
+ const Pattern = new Design({ parts: [part] })
const pattern = new Pattern()
pattern.draft()
it('Should mirror points', () => {
- expect(pattern.parts.test.points.mirroredA.x).to.equal(20)
- expect(pattern.parts.test.points.mirroredA.y).to.equal(10)
- expect(pattern.parts.test.points.mirroredB.x).to.equal(40)
- expect(pattern.parts.test.points.mirroredB.y).to.equal(30)
+ expect(pattern.parts[0].test.points.mirroredA.x).to.equal(20)
+ expect(pattern.parts[0].test.points.mirroredA.y).to.equal(10)
+ expect(pattern.parts[0].test.points.mirroredB.x).to.equal(40)
+ expect(pattern.parts[0].test.points.mirroredB.y).to.equal(30)
})
it('Should mirror points with custom prefix', () => {
- expect(pattern.parts.test.points.testA.x).to.equal(20)
- expect(pattern.parts.test.points.testA.y).to.equal(10)
- expect(pattern.parts.test.points.testB.x).to.equal(40)
- expect(pattern.parts.test.points.testB.y).to.equal(30)
+ expect(pattern.parts[0].test.points.testA.x).to.equal(20)
+ expect(pattern.parts[0].test.points.testA.y).to.equal(10)
+ expect(pattern.parts[0].test.points.testB.x).to.equal(40)
+ expect(pattern.parts[0].test.points.testB.y).to.equal(30)
})
it('Should mirror points without cloning them', () => {
- expect(pattern.parts.test.points.a.x).to.equal(20)
- expect(pattern.parts.test.points.a.y).to.equal(10)
- expect(pattern.parts.test.points.b.x).to.equal(40)
- expect(pattern.parts.test.points.b.y).to.equal(30)
+ expect(pattern.parts[0].test.points.a.x).to.equal(20)
+ expect(pattern.parts[0].test.points.a.y).to.equal(10)
+ expect(pattern.parts[0].test.points.b.x).to.equal(40)
+ expect(pattern.parts[0].test.points.b.y).to.equal(30)
})
it('Should mirror paths', () => {
- expect(pattern.parts.test.paths.mirroredTest.ops[0].to.x).to.equal(2)
- expect(pattern.parts.test.paths.mirroredTest.ops[0].to.y).to.equal(1)
- expect(pattern.parts.test.paths.mirroredTest.ops[1].cp1.x).to.equal(20)
- expect(pattern.parts.test.paths.mirroredTest.ops[1].cp1.y).to.equal(10)
- expect(pattern.parts.test.paths.mirroredTest.ops[1].cp2.x).to.equal(40)
- expect(pattern.parts.test.paths.mirroredTest.ops[1].cp2.y).to.equal(30)
- expect(pattern.parts.test.paths.mirroredTest.ops[1].to.x).to.equal(60)
- expect(pattern.parts.test.paths.mirroredTest.ops[1].to.y).to.equal(50)
+ expect(pattern.parts[0].test.paths.mirroredTest.ops[0].to.x).to.equal(2)
+ expect(pattern.parts[0].test.paths.mirroredTest.ops[0].to.y).to.equal(1)
+ expect(pattern.parts[0].test.paths.mirroredTest.ops[1].cp1.x).to.equal(20)
+ expect(pattern.parts[0].test.paths.mirroredTest.ops[1].cp1.y).to.equal(10)
+ expect(pattern.parts[0].test.paths.mirroredTest.ops[1].cp2.x).to.equal(40)
+ expect(pattern.parts[0].test.paths.mirroredTest.ops[1].cp2.y).to.equal(30)
+ expect(pattern.parts[0].test.paths.mirroredTest.ops[1].to.x).to.equal(60)
+ expect(pattern.parts[0].test.paths.mirroredTest.ops[1].to.y).to.equal(50)
})
it('Should mirror paths with custom prefix', () => {
- expect(pattern.parts.test.paths.testTest.ops[0].to.x).to.equal(2)
- expect(pattern.parts.test.paths.testTest.ops[0].to.y).to.equal(1)
- expect(pattern.parts.test.paths.testTest.ops[1].cp1.x).to.equal(20)
- expect(pattern.parts.test.paths.testTest.ops[1].cp1.y).to.equal(10)
- expect(pattern.parts.test.paths.testTest.ops[1].cp2.x).to.equal(40)
- expect(pattern.parts.test.paths.testTest.ops[1].cp2.y).to.equal(30)
- expect(pattern.parts.test.paths.testTest.ops[1].to.x).to.equal(60)
- expect(pattern.parts.test.paths.testTest.ops[1].to.y).to.equal(50)
+ expect(pattern.parts[0].test.paths.testTest.ops[0].to.x).to.equal(2)
+ expect(pattern.parts[0].test.paths.testTest.ops[0].to.y).to.equal(1)
+ expect(pattern.parts[0].test.paths.testTest.ops[1].cp1.x).to.equal(20)
+ expect(pattern.parts[0].test.paths.testTest.ops[1].cp1.y).to.equal(10)
+ expect(pattern.parts[0].test.paths.testTest.ops[1].cp2.x).to.equal(40)
+ expect(pattern.parts[0].test.paths.testTest.ops[1].cp2.y).to.equal(30)
+ expect(pattern.parts[0].test.paths.testTest.ops[1].to.x).to.equal(60)
+ expect(pattern.parts[0].test.paths.testTest.ops[1].to.y).to.equal(50)
})
it('Should mirror paths without cloning them', () => {
- expect(pattern.parts.test.paths.test.ops[0].to.x).to.equal(2)
- expect(pattern.parts.test.paths.test.ops[0].to.y).to.equal(1)
- expect(pattern.parts.test.paths.test.ops[1].cp1.x).to.equal(20)
- expect(pattern.parts.test.paths.test.ops[1].cp1.y).to.equal(10)
- expect(pattern.parts.test.paths.test.ops[1].cp2.x).to.equal(40)
- expect(pattern.parts.test.paths.test.ops[1].cp2.y).to.equal(30)
- expect(pattern.parts.test.paths.test.ops[1].to.x).to.equal(60)
- expect(pattern.parts.test.paths.test.ops[1].to.y).to.equal(50)
+ expect(pattern.parts[0].test.paths.test.ops[0].to.x).to.equal(2)
+ expect(pattern.parts[0].test.paths.test.ops[0].to.y).to.equal(1)
+ expect(pattern.parts[0].test.paths.test.ops[1].cp1.x).to.equal(20)
+ expect(pattern.parts[0].test.paths.test.ops[1].cp1.y).to.equal(10)
+ expect(pattern.parts[0].test.paths.test.ops[1].cp2.x).to.equal(40)
+ expect(pattern.parts[0].test.paths.test.ops[1].cp2.y).to.equal(30)
+ expect(pattern.parts[0].test.paths.test.ops[1].to.x).to.equal(60)
+ expect(pattern.parts[0].test.paths.test.ops[1].to.y).to.equal(50)
})
})
diff --git a/plugins/plugin-notches/tests/plugin.test.mjs b/plugins/plugin-notches/tests/plugin.test.mjs
index 2a6c27d1bde..5f9553532b7 100644
--- a/plugins/plugin-notches/tests/plugin.test.mjs
+++ b/plugins/plugin-notches/tests/plugin.test.mjs
@@ -9,8 +9,9 @@ const part = {
draft: ({ Point, snippets, Snippet }) => {
snippets.button = new Snippet('notch', new Point(10, 20))
},
+ plugins: [plugin],
}
-const Pattern = new Design({ plugins: [plugin], parts: [part] })
+const Pattern = new Design({ parts: [part] })
const pattern = new Pattern()
pattern.draft().render()
@@ -26,11 +27,14 @@ describe('Notches Plugin Test', () => {
it('Draws a notch on an anchor point', () => {
const part = {
name: 'test',
- draft: ({ Point, snippets, Snippet }) => {
+ draft: ({ Point, snippets, Snippet, part }) => {
snippets.button = new Snippet('notch', new Point(10, 20))
+
+ return part
},
+ plugins: [plugin],
}
- const Pattern = new Design({ plugins: [plugin], parts: [part] })
+ const Pattern = new Design({ parts: [part] })
const pattern = new Pattern()
pattern.draft().render()
const c = pattern.svg
diff --git a/plugins/plugin-round/src/index.mjs b/plugins/plugin-round/src/index.mjs
index 567217a725d..b9cce3edffe 100644
--- a/plugins/plugin-round/src/index.mjs
+++ b/plugins/plugin-round/src/index.mjs
@@ -6,6 +6,7 @@ export const plugin = {
macros: {
round: function (so) {
const C = 0.55191502449
+ const { hide = true } = so
// Find angle between points
let from = so.from
let to = so.to
@@ -31,7 +32,7 @@ export const plugin = {
this.points[prefix + 'End']
)
.attr('class', so.class ? so.class : '')
- if (so?.hidden) this.paths[prefix + 'Rounded'].hide()
+ if (hide) this.paths[prefix + 'Rounded'].hide()
else this.paths[prefix + 'Rounded'].unhide()
},
},
diff --git a/plugins/plugin-scalebox/src/miniscale.mjs b/plugins/plugin-scalebox/src/miniscale.mjs
index 533beeb5645..b7876518fd0 100644
--- a/plugins/plugin-scalebox/src/miniscale.mjs
+++ b/plugins/plugin-scalebox/src/miniscale.mjs
@@ -1,7 +1,7 @@
-export function miniscale(so) {
+export function miniscale(so, { points, paths, Point, Path, scale }) {
// Passing `false` will remove the miniscale
if (so === false) {
- for (let id of [
+ for (const id of [
'__miniscaleMetricTopLeft',
'__miniscaleMetricTopRight',
'__miniscaleMetricBottomRight',
@@ -13,15 +13,13 @@ export function miniscale(so) {
'__miniscaleMetric',
'__miniscaleImperial',
])
- delete this.points[id]
- for (let id of ['__miniscaleMetric', '__miniscaleImperial']) delete this.paths[id]
+ delete points[id]
+ for (const id of ['__miniscaleMetric', '__miniscaleImperial']) delete paths[id]
return true
}
- const scale = this.context.settings.scale
-
// Convert scale to a value between 0 and 5, inclusive.
- const scaleIndex = Math.ceil(6 * Math.max(0.1, Math.min(1, this.context.settings.scale))) - 1
+ const scaleIndex = Math.ceil(6 * Math.max(0.1, Math.min(1, scale))) - 1
// Metric size in mm / display value and imperial size in mm / display value for each scale index.
const sizes = [
@@ -37,20 +35,21 @@ export function miniscale(so) {
const metricDisplaySize = sizes[scaleIndex][1]
const imperialDisplaySize = sizes[scaleIndex][3]
// Box points
- this.points.__miniscaleMetricTopLeft = new this.Point(so.at.x - m, so.at.y - m)
- this.points.__miniscaleMetricTopRight = new this.Point(so.at.x + m, so.at.y - m)
- this.points.__miniscaleMetricBottomLeft = new this.Point(so.at.x - m, so.at.y + m)
- this.points.__miniscaleMetricBottomRight = new this.Point(so.at.x + m, so.at.y + m)
- this.points.__miniscaleImperialTopLeft = new this.Point(so.at.x - i, so.at.y - i)
- this.points.__miniscaleImperialTopRight = new this.Point(so.at.x + i, so.at.y - i)
- this.points.__miniscaleImperialBottomLeft = new this.Point(so.at.x - i, so.at.y + i)
- this.points.__miniscaleImperialBottomRight = new this.Point(so.at.x + i, so.at.y + i)
+ points.__miniscaleMetricTopLeft = new Point(so.at.x - m, so.at.y - m)
+ points.__miniscaleMetricTopRight = new Point(so.at.x + m, so.at.y - m)
+ points.__miniscaleMetricBottomLeft = new Point(so.at.x - m, so.at.y + m)
+ points.__miniscaleMetricBottomRight = new Point(so.at.x + m, so.at.y + m)
+ points.__miniscaleImperialTopLeft = new Point(so.at.x - i, so.at.y - i)
+ points.__miniscaleImperialTopRight = new Point(so.at.x + i, so.at.y - i)
+ points.__miniscaleImperialBottomLeft = new Point(so.at.x - i, so.at.y + i)
+ points.__miniscaleImperialBottomRight = new Point(so.at.x + i, so.at.y + i)
// Text anchor points
- this.points.__miniscaleMetric = new this.Point(so.at.x, so.at.y - 2 * scale)
- this.points.__miniscaleImperial = new this.Point(so.at.x, so.at.y + 8 * scale)
+ points.__miniscaleMetric = new Point(so.at.x, so.at.y - 2 * scale)
+ points.__miniscaleImperial = new Point(so.at.x, so.at.y + 8 * scale)
// Rotation
if (so.rotate) {
- let points = [
+ so.rotate = Number(so.rotate)
+ let toRotate = [
'__miniscaleMetricTopLeft',
'__miniscaleMetricTopRight',
'__miniscaleMetricBottomLeft',
@@ -62,34 +61,34 @@ export function miniscale(so) {
'__miniscaleMetric',
'__miniscaleImperial',
]
- for (let pid of points) this.points[pid] = this.points[pid].rotate(so.rotate, so.at)
- for (let pid of points.slice(8)) {
- this.points[pid].attributes.set(
+ for (const pid of toRotate) points[pid] = points[pid].rotate(so.rotate, so.at)
+ for (const pid of toRotate.slice(8)) {
+ points[pid].attributes.set(
'data-text-transform',
- `rotate(${so.rotate * -1}, ${this.points[pid].x}, ${this.points[pid].y})`
+ `rotate(${so.rotate * -1}, ${points[pid].x}, ${points[pid].y})`
)
}
}
// Paths
- this.paths.__miniscaleImperial = new this.Path()
+ paths.__miniscaleImperial = new Path()
.attr('class', 'scalebox imperial fill-current')
- .move(this.points.__miniscaleImperialTopLeft)
- .line(this.points.__miniscaleImperialBottomLeft)
- .line(this.points.__miniscaleImperialBottomRight)
- .line(this.points.__miniscaleImperialTopRight)
+ .move(points.__miniscaleImperialTopLeft)
+ .line(points.__miniscaleImperialBottomLeft)
+ .line(points.__miniscaleImperialBottomRight)
+ .line(points.__miniscaleImperialTopRight)
.close()
- this.paths.__miniscaleMetric = new this.Path()
+ paths.__miniscaleMetric = new Path()
.attr('class', 'scalebox metric fill-bg')
- .move(this.points.__miniscaleMetricTopLeft)
- .line(this.points.__miniscaleMetricBottomLeft)
- .line(this.points.__miniscaleMetricBottomRight)
- .line(this.points.__miniscaleMetricTopRight)
+ .move(points.__miniscaleMetricTopLeft)
+ .line(points.__miniscaleMetricBottomLeft)
+ .line(points.__miniscaleMetricBottomRight)
+ .line(points.__miniscaleMetricTopRight)
.close()
// Text
- this.points.__miniscaleMetric = this.points.__miniscaleMetric
+ points.__miniscaleMetric = points.__miniscaleMetric
.attr('data-text', `${metricDisplaySize} x ${metricDisplaySize}`)
.attr('data-text-class', 'text-xs center')
- this.points.__miniscaleImperial = this.points.__miniscaleImperial
+ points.__miniscaleImperial = points.__miniscaleImperial
.attr('data-text', `${imperialDisplaySize} x ${imperialDisplaySize}`)
.attr('data-text-class', 'text-xs center ')
}
diff --git a/plugins/plugin-scalebox/src/scalebox.mjs b/plugins/plugin-scalebox/src/scalebox.mjs
index 35fec755fcf..55a343f102b 100644
--- a/plugins/plugin-scalebox/src/scalebox.mjs
+++ b/plugins/plugin-scalebox/src/scalebox.mjs
@@ -1,4 +1,4 @@
-export function scalebox(so) {
+export function scalebox(so, { store, points, paths, scale, Point, Path }) {
// Passing `false` will remove the scalebox
if (so === false) {
for (let id of [
@@ -17,15 +17,13 @@ export function scalebox(so) {
'__scaleboxMetric',
'__scaleboxImperial',
])
- delete this.points[id]
- for (let id of ['__scaleboxMetric', '__scaleboxImperial']) delete this.paths[id]
+ delete points[id]
+ for (let id of ['__scaleboxMetric', '__scaleboxImperial']) delete paths[id]
return true
}
- const scale = this.context.settings.scale
-
// Convert scale to a value between 0 and 9, inclusive.
- const scaleIndex = Math.round(10 * Math.max(0.1, Math.min(1, this.context.settings.scale))) - 1
+ const scaleIndex = Math.round(10 * Math.max(0.1, Math.min(1, scale))) - 1
// Metric width and height in mm and display width and height for each scale index.
const metricSizes = [
@@ -66,48 +64,43 @@ export function scalebox(so) {
const imperialDisplayHeight = imperialSizes[scaleIndex][3]
// Box points
- this.points.__scaleboxMetricTopLeft = new this.Point(
- so.at.x - metricWidth / 2,
- so.at.y - metricHeight / 2
- )
- this.points.__scaleboxMetricTopRight = new this.Point(
- so.at.x + metricWidth / 2,
- so.at.y - metricHeight / 2
- )
- this.points.__scaleboxMetricBottomLeft = new this.Point(
+ points.__scaleboxMetricTopLeft = new Point(so.at.x - metricWidth / 2, so.at.y - metricHeight / 2)
+ points.__scaleboxMetricTopRight = new Point(so.at.x + metricWidth / 2, so.at.y - metricHeight / 2)
+ points.__scaleboxMetricBottomLeft = new Point(
so.at.x - metricWidth / 2,
so.at.y + metricHeight / 2
)
- this.points.__scaleboxMetricBottomRight = new this.Point(
+ points.__scaleboxMetricBottomRight = new Point(
so.at.x + metricWidth / 2,
so.at.y + metricHeight / 2
)
- this.points.__scaleboxImperialTopLeft = new this.Point(
+ points.__scaleboxImperialTopLeft = new Point(
so.at.x - imperialWidth / 2,
so.at.y - imperialHeight / 2
)
- this.points.__scaleboxImperialTopRight = new this.Point(
+ points.__scaleboxImperialTopRight = new Point(
so.at.x + imperialWidth / 2,
so.at.y - imperialHeight / 2
)
- this.points.__scaleboxImperialBottomLeft = new this.Point(
+ points.__scaleboxImperialBottomLeft = new Point(
so.at.x - imperialWidth / 2,
so.at.y + imperialHeight / 2
)
- this.points.__scaleboxImperialBottomRight = new this.Point(
+ points.__scaleboxImperialBottomRight = new Point(
so.at.x + imperialWidth / 2,
so.at.y + imperialHeight / 2
)
// Text anchor points
- this.points.__scaleboxLead = new this.Point(so.at.x - 45 * scale, so.at.y - 15 * scale)
- this.points.__scaleboxTitle = this.points.__scaleboxLead.shift(-90, 10 * scale)
- this.points.__scaleboxText = this.points.__scaleboxTitle.shift(-90, 12 * scale)
- this.points.__scaleboxLink = this.points.__scaleboxText.shift(-90, 5 * scale)
- this.points.__scaleboxMetric = new this.Point(so.at.x, so.at.y + 20 * scale)
- this.points.__scaleboxImperial = new this.Point(so.at.x, so.at.y + 24 * scale)
+ points.__scaleboxLead = new Point(so.at.x - 45 * scale, so.at.y - 15 * scale)
+ points.__scaleboxTitle = points.__scaleboxLead.shift(-90, 10 * scale)
+ points.__scaleboxText = points.__scaleboxTitle.shift(-90, 12 * scale)
+ points.__scaleboxLink = points.__scaleboxText.shift(-90, 5 * scale)
+ points.__scaleboxMetric = new Point(so.at.x, so.at.y + 20 * scale)
+ points.__scaleboxImperial = new Point(so.at.x, so.at.y + 24 * scale)
// Rotation
if (so.rotate) {
- let points = [
+ so.rotate = Number(so.rotate)
+ let toRotate = [
'__scaleboxMetricTopLeft',
'__scaleboxMetricTopRight',
'__scaleboxMetricBottomLeft',
@@ -123,61 +116,61 @@ export function scalebox(so) {
'__scaleboxMetric',
'__scaleboxImperial',
]
- for (let pid of points) this.points[pid] = this.points[pid].rotate(so.rotate, so.at)
- for (let pid of points.slice(8)) {
- this.points[pid].attributes.set(
+ for (let pid of toRotate) points[pid] = points[pid].rotate(so.rotate, so.at)
+ for (let pid of toRotate.slice(8)) {
+ points[pid].attributes.set(
'data-text-transform',
- `rotate(${so.rotate * -1}, ${this.points[pid].x}, ${this.points[pid].y})`
+ `rotate(${so.rotate * -1}, ${points[pid].x}, ${points[pid].y})`
)
}
}
// Paths
- this.paths.__scaleboxImperial = new this.Path()
+ paths.__scaleboxImperial = new Path()
.attr('class', 'scalebox imperial fill-current')
- .move(this.points.__scaleboxImperialTopLeft)
- .line(this.points.__scaleboxImperialBottomLeft)
- .line(this.points.__scaleboxImperialBottomRight)
- .line(this.points.__scaleboxImperialTopRight)
+ .move(points.__scaleboxImperialTopLeft)
+ .line(points.__scaleboxImperialBottomLeft)
+ .line(points.__scaleboxImperialBottomRight)
+ .line(points.__scaleboxImperialTopRight)
.close()
- this.paths.__scaleboxMetric = new this.Path()
+ paths.__scaleboxMetric = new Path()
.attr('class', 'scalebox metric fill-bg')
- .move(this.points.__scaleboxMetricTopLeft)
- .line(this.points.__scaleboxMetricBottomLeft)
- .line(this.points.__scaleboxMetricBottomRight)
- .line(this.points.__scaleboxMetricTopRight)
+ .move(points.__scaleboxMetricTopLeft)
+ .line(points.__scaleboxMetricBottomLeft)
+ .line(points.__scaleboxMetricBottomRight)
+ .line(points.__scaleboxMetricTopRight)
.close()
// Lead
- this.points.__scaleboxLead = this.points.__scaleboxLead
+ points.__scaleboxLead = points.__scaleboxLead
.attr('data-text', so.lead || 'FreeSewing')
.attr('data-text-class', 'text-sm')
// Title
- if (so.title) this.points.__scaleboxTitle.attributes.set('data-text', so.title)
+ if (so.title) points.__scaleboxTitle.attributes.set('data-text', so.title)
else {
- let name = this.context.config?.data?.name || 'No Name'
+ let name = store.data?.name || 'No Name'
if (name.indexOf('@freesewing/') !== -1) name = name.replace('@freesewing/', '')
- this.points.__scaleboxTitle = this.points.__scaleboxTitle
+ points.__scaleboxTitle = points.__scaleboxTitle
.attr('data-text', name)
- .attr('data-text', 'v' + (this.context.config?.data?.version || 'No Version'))
+ .attr('data-text', 'v' + (store.data?.version || 'No Version'))
}
- this.points.__scaleboxTitle.attributes.add('data-text-class', 'text-lg')
+ points.__scaleboxTitle.attributes.add('data-text-class', 'text-lg')
// Text
if (typeof so.text === 'string') {
- this.points.__scaleboxText.attr('data-text', so.text)
+ points.__scaleboxText.attr('data-text', so.text)
} else {
- this.points.__scaleboxText.attr('data-text', 'supportFreesewingBecomeAPatron')
- this.points.__scaleboxLink = this.points.__scaleboxLink
+ points.__scaleboxText.attr('data-text', 'supportFreesewingBecomeAPatron')
+ points.__scaleboxLink = points.__scaleboxLink
.attr('data-text', 'freesewing.org/patrons/join')
.attr('data-text-class', 'text-sm fill-note')
}
- this.points.__scaleboxText.attr('data-text-class', 'text-xs').attr('data-text-lineheight', 4)
+ points.__scaleboxText.attr('data-text-class', 'text-xs').attr('data-text-lineheight', 4)
// Instructions
- this.points.__scaleboxMetric = this.points.__scaleboxMetric
+ points.__scaleboxMetric = points.__scaleboxMetric
.attr('data-text', 'theWhiteInsideOfThisBoxShouldMeasure')
.attr('data-text', `${metricDisplayWidth}`)
.attr('data-text', 'x')
.attr('data-text', `${metricDisplayHeight}`)
.attr('data-text-class', 'text-xs center')
- this.points.__scaleboxImperial = this.points.__scaleboxImperial
+ points.__scaleboxImperial = points.__scaleboxImperial
.attr('data-text', 'theBlackOutsideOfThisBoxShouldMeasure')
.attr('data-text', `${imperialDisplayWidth}`)
.attr('data-text', 'x')
diff --git a/plugins/plugin-scalebox/tests/plugin.test.mjs b/plugins/plugin-scalebox/tests/plugin.test.mjs
index 1c77708efa4..57cf10d1842 100644
--- a/plugins/plugin-scalebox/tests/plugin.test.mjs
+++ b/plugins/plugin-scalebox/tests/plugin.test.mjs
@@ -8,17 +8,20 @@ describe('Scalebox Plugin Tests', () => {
it('Should run the default scalebox macro', () => {
const part = {
name: 'test',
- draft: ({ points, Point, macro }) => {
+ draft: ({ points, Point, macro, part }) => {
points.anchor = new Point(100, 200)
macro('scalebox', {
at: points.anchor,
})
+
+ return part
},
+ plugins: [plugin],
}
- const Pattern = new Design({ parts: [part], plugins: [plugin] })
+ const Pattern = new Design({ parts: [part] })
const pattern = new Pattern()
pattern.draft()
- let p = pattern.parts.test.points
+ let p = pattern.parts[0].test.points
expect(p.__scaleboxMetricTopLeft.x).to.equal(50)
expect(p.__scaleboxMetricTopLeft.y).to.equal(175)
expect(p.__scaleboxMetricTopRight.x).to.equal(150)
@@ -47,7 +50,7 @@ describe('Scalebox Plugin Tests', () => {
expect(p.__scaleboxMetric.y).to.equal(220)
expect(p.__scaleboxImperial.x).to.equal(100)
expect(p.__scaleboxImperial.y).to.equal(224)
- p = pattern.parts.test.paths.__scaleboxMetric
+ p = pattern.parts[0].test.paths.__scaleboxMetric
expect(p.ops[0].type).to.equal('move')
expect(p.ops[1].type).to.equal('line')
expect(p.ops[2].type).to.equal('line')
@@ -61,7 +64,7 @@ describe('Scalebox Plugin Tests', () => {
expect(p.ops[2].to.y).to.equal(225)
expect(p.ops[3].to.x).to.equal(150)
expect(p.ops[3].to.y).to.equal(175)
- p = pattern.parts.test.paths.__scaleboxImperial
+ p = pattern.parts[0].test.paths.__scaleboxImperial
expect(p.ops[0].type).to.equal('move')
expect(p.ops[1].type).to.equal('line')
expect(p.ops[2].type).to.equal('line')
@@ -87,11 +90,12 @@ describe('Scalebox Plugin Tests', () => {
rotate: 90,
})
},
+ plugins: [plugin],
}
- const Pattern = new Design({ parts: [part], plugins: [plugin] })
+ const Pattern = new Design({ parts: [part] })
const pattern = new Pattern()
pattern.draft()
- const p = pattern.parts.test.points
+ const p = pattern.parts[0].test.points
expect(round(p.__scaleboxMetricTopLeft.x)).to.equal(75)
expect(round(p.__scaleboxMetricTopLeft.y)).to.equal(250)
expect(round(p.__scaleboxMetricTopRight.x)).to.equal(75)
@@ -125,27 +129,29 @@ describe('Scalebox Plugin Tests', () => {
it('Should run the scalebox macro with default text', () => {
const part = {
name: 'test',
- draft: ({ points, Point, macro }) => {
+ draft: ({ points, Point, macro, part }) => {
points.anchor = new Point(100, 200)
macro('scalebox', {
at: points.anchor,
})
+
+ return part
},
+ plugins: [plugin],
}
const Pattern = new Design({
parts: [part],
- plugins: [plugin],
data: { name: 'test', version: '1.2.3' },
})
const pattern = new Pattern()
pattern.draft()
- let p = pattern.parts.test.points.__scaleboxLead.attributes
+ let p = pattern.parts[0].test.points.__scaleboxLead.attributes
expect(p.get('data-text')).to.equal('FreeSewing')
expect(p.get('data-text-class')).to.equal('text-sm')
- p = pattern.parts.test.points.__scaleboxTitle.attributes
+ p = pattern.parts[0].test.points.__scaleboxTitle.attributes
expect(p.get('data-text')).to.equal('test v1.2.3')
expect(p.get('data-text-class')).to.equal('text-lg')
- p = pattern.parts.test.points.__scaleboxText.attributes
+ p = pattern.parts[0].test.points.__scaleboxText.attributes
expect(p.get('data-text-class')).to.equal('text-xs')
expect(p.get('data-text-lineheight')).to.equal('4')
expect(p.list['data-text'][0]).to.equal('supportFreesewingBecomeAPatron')
@@ -154,7 +160,7 @@ describe('Scalebox Plugin Tests', () => {
it('Should run the scalebox macro with custom text', () => {
const part = {
name: 'test',
- draft: ({ points, Point, macro }) => {
+ draft: ({ points, Point, macro, part }) => {
points.anchor = new Point(100, 200)
macro('scalebox', {
at: points.anchor,
@@ -162,22 +168,24 @@ describe('Scalebox Plugin Tests', () => {
title: 'theTitle',
text: 'theText',
})
+
+ return part
},
+ plugins: [plugin],
}
const Pattern = new Design({
parts: [part],
- plugins: [plugin],
data: { name: 'test', version: '1.2.3' },
})
const pattern = new Pattern()
pattern.draft()
- let p = pattern.parts.test.points.__scaleboxLead.attributes
+ let p = pattern.parts[0].test.points.__scaleboxLead.attributes
expect(p.get('data-text')).to.equal('theLead')
expect(p.get('data-text-class')).to.equal('text-sm')
- p = pattern.parts.test.points.__scaleboxTitle.attributes
+ p = pattern.parts[0].test.points.__scaleboxTitle.attributes
expect(p.get('data-text')).to.equal('theTitle')
expect(p.get('data-text-class')).to.equal('text-lg')
- p = pattern.parts.test.points.__scaleboxText.attributes
+ p = pattern.parts[0].test.points.__scaleboxText.attributes
expect(p.get('data-text')).to.equal('theText')
expect(p.get('data-text-class')).to.equal('text-xs')
expect(p.get('data-text-lineheight')).to.equal('4')
@@ -186,7 +194,7 @@ describe('Scalebox Plugin Tests', () => {
it('Should apply scale to the scalebox macro', () => {
const part = {
name: 'test',
- draft: ({ points, Point, macro }) => {
+ draft: ({ points, Point, macro, part }) => {
points.anchor = new Point(100, 200)
macro('scalebox', {
at: points.anchor,
@@ -194,7 +202,10 @@ describe('Scalebox Plugin Tests', () => {
title: 'theTitle',
text: 'theText',
})
+
+ return part
},
+ plugins: [plugin],
}
const Pattern = new Design({
parts: [part],
@@ -203,7 +214,7 @@ describe('Scalebox Plugin Tests', () => {
})
const pattern = new Pattern({ scale: 0.5 })
pattern.draft()
- let p = pattern.parts.test.points
+ let p = pattern.parts[0].test.points
expect(p.__scaleboxMetricTopLeft.x).to.equal(75)
expect(p.__scaleboxMetricTopLeft.y).to.equal(187.5)
expect(p.__scaleboxMetricTopRight.x).to.equal(125)
@@ -231,12 +242,15 @@ describe('Scalebox Plugin Tests', () => {
it('Should apply scale to the miniscale macro', () => {
const part = {
name: 'test',
- draft: ({ points, Point, macro }) => {
+ draft: ({ points, Point, macro, part }) => {
points.anchor = new Point(100, 200)
macro('miniscale', {
at: points.anchor,
})
+
+ return part
},
+ plugins: [plugin],
}
const Pattern = new Design({
parts: [part],
@@ -245,7 +259,7 @@ describe('Scalebox Plugin Tests', () => {
})
const pattern = new Pattern({ scale: 0.5 })
pattern.draft()
- let p = pattern.parts.test.points
+ let p = pattern.parts[0].test.points
expect(p.__miniscaleMetricTopLeft.x).to.equal(92)
expect(p.__miniscaleMetricTopLeft.y).to.equal(192)
expect(p.__miniscaleMetricTopRight.x).to.equal(108)
diff --git a/plugins/plugin-sprinkle/src/index.mjs b/plugins/plugin-sprinkle/src/index.mjs
index 16e29577838..59595bd9216 100644
--- a/plugins/plugin-sprinkle/src/index.mjs
+++ b/plugins/plugin-sprinkle/src/index.mjs
@@ -4,11 +4,11 @@ export const plugin = {
name,
version,
macros: {
- sprinkle: function (so) {
+ sprinkle: function (so, { snippets, Snippet, points }) {
for (let pid of so.on) {
- this.snippets[pid + '-' + so.snippet] = new this.Snippet(so.snippet, this.points[pid])
- if (so.scale) this.snippets[pid + '-' + so.snippet].attr('data-scale', so.scale)
- if (so.rotate) this.snippets[pid + '-' + so.snippet].attr('data-rotate', so.rotate)
+ snippets[pid + '-' + so.snippet] = new Snippet(so.snippet, points[pid])
+ if (so.scale) snippets[pid + '-' + so.snippet].attr('data-scale', so.scale)
+ if (so.rotate) snippets[pid + '-' + so.snippet].attr('data-rotate', so.rotate)
}
},
},
diff --git a/plugins/plugin-theme/src/css.mjs b/plugins/plugin-theme/src/css.mjs
index d77bdc8d33d..326dd01c47a 100644
--- a/plugins/plugin-theme/src/css.mjs
+++ b/plugins/plugin-theme/src/css.mjs
@@ -1,4 +1,4 @@
-export const paperless = `
+export const paperlessStyle = `
/* Paperless grid */
svg.freesewing path.grid {
fill: none;
@@ -26,7 +26,7 @@ svg.freesewing path.gridline-xs {
svg.freesewing path.gridbox {
fill: url(#grid);
}`
-export const sample = `
+export const sampleStyle = `
/* Sample classes */
svg.freesewing path.sample {
stroke-width: 0.75
diff --git a/plugins/plugin-theme/src/index.mjs b/plugins/plugin-theme/src/index.mjs
index 18813f91156..bfb6a70d367 100644
--- a/plugins/plugin-theme/src/index.mjs
+++ b/plugins/plugin-theme/src/index.mjs
@@ -1,5 +1,5 @@
import { name, version } from '../data.mjs'
-import { sample, paperless, buildStylesheet } from './css.mjs'
+import { sampleStyle, paperlessStyle, buildStylesheet } from './css.mjs'
const grid = {
metric: `
@@ -28,16 +28,18 @@ export const plugin = {
const current = svg.attributes.get('class')
if (!current || current.indexOf('freesewing') !== -1) {
svg.attributes.set('class', 'freesewing')
- svg.style += sample
- svg.style += paperless
+ svg.style += sampleStyle
+ svg.style += paperlessStyle
svg.style += buildStylesheet(svg.pattern.settings.scale, data.stripped)
- // FIXME : Re-implement this for v3
- /*
- if (svg.pattern.settings[0].paperless) {
- svg.pattern.settings.units === 'imperial'
+ let paperless = false
+ for (const set of svg.pattern.settings) {
+ if (set.paperless) paperless = true
+ }
+ if (paperless) {
+ svg.pattern.settings[0].units === 'imperial'
? (svg.defs += grid.imperial)
: (svg.defs += grid.metric)
- for (const key in svg.pattern.parts) {
+ for (const key in svg.pattern.parts[0]) {
const part = svg.pattern.parts[key]
if (!part.hidden && svg.pattern.__needs(key)) {
let anchor = new svg.pattern.Point(0, 0)
@@ -57,7 +59,6 @@ export const plugin = {
}
}
}
- */
}
},
},
diff --git a/plugins/plugin-title/src/index.mjs b/plugins/plugin-title/src/index.mjs
index f644744b8d4..f6a43442013 100644
--- a/plugins/plugin-title/src/index.mjs
+++ b/plugins/plugin-title/src/index.mjs
@@ -31,7 +31,7 @@ export const plugin = {
},
},
macros: {
- title: function (so) {
+ title: function (so, { points, scale, locale, store }) {
const prefix = so.prefix || ''
// Passing `false` will remove the title
@@ -43,7 +43,7 @@ export const plugin = {
`_${prefix}_titleFor`,
`_${prefix}_exportDate`,
])
- delete this.points[id]
+ delete points[id]
return true
}
@@ -59,36 +59,36 @@ export const plugin = {
}
so = { ...defaults, ...so }
- so.scale = so.scale * this.context.settings.scale
+ so.scale = so.scale * scale
let overwrite = true
if (so.append) overwrite = false
- this.points[`_${prefix}_titleNr`] = so.at
+ points[`_${prefix}_titleNr`] = so.at
.clone()
.attr('data-text', so.nr, overwrite)
.attr('data-text-class', 'text-4xl fill-note font-bold')
.attr('data-text-transform', transform(so.at))
let shift = 8
if (so.title) {
- this.points[`_${prefix}_titleName`] = so.at
+ points[`_${prefix}_titleName`] = so.at
.shift(-90 - so.rotation, shift * so.scale)
.attr('data-text', so.title)
.attr('data-text-class', 'text-lg fill-current font-bold')
.attr('data-text-transform', transform(so.at.shift(-90 - so.rotation, 13 * so.scale)))
shift += 8
}
- let name = this.context.config?.data?.name || 'No Name'
+ let name = store.data?.name || 'No Name'
name = name.replace('@freesewing/', '')
- this.points[`_${prefix}_titlePattern`] = so.at
+ points[`_${prefix}_titlePattern`] = so.at
.shift(-90 - so.rotation, shift * so.scale)
.attr('data-text', name)
- .attr('data-text', 'v' + (this.context.config?.data?.version || 'No Version'))
+ .attr('data-text', 'v' + (store.data?.version || 'No Version'))
.attr('data-text-class', 'fill-note')
.attr('data-text-transform', transform(so.at.shift(-90 - so.rotation, shift * so.scale)))
- if (this.context.settings.metadata && this.context.settings.metadata.for) {
+ if (store.data.for) {
shift += 8
- this.points[`_${prefix}_titleFor`] = so.at
+ points[`_${prefix}_titleFor`] = so.at
.shift(-90 - so.rotation, shift * so.scale)
- .attr('data-text', '( ' + this.context.settings.metadata.for + ' )')
+ .attr('data-text', '( ' + store.data.for + ' )')
.attr('data-text-class', 'fill-current font-bold')
.attr('data-text-transform', transform(so.at.shift(-90 - so.rotation, shift * so.scale)))
}
@@ -98,11 +98,11 @@ export const plugin = {
let mins = now.getMinutes()
if (hours < 10) hours = `0${hours}`
if (mins < 10) mins = `0${mins}`
- this.points[`_${prefix}_exportDate`] = so.at
+ points[`_${prefix}_exportDate`] = so.at
.shift(-90 - so.rotation, shift * so.scale)
.attr(
'data-text',
- now.toLocaleDateString(this.context.settings.locale || 'en', {
+ now.toLocaleDateString(locale || 'en', {
weekday: 'long',
year: 'numeric',
month: 'short',
diff --git a/plugins/plugin-title/tests/plugin.test.mjs b/plugins/plugin-title/tests/plugin.test.mjs
index a51e5126bc4..c4e801efd24 100644
--- a/plugins/plugin-title/tests/plugin.test.mjs
+++ b/plugins/plugin-title/tests/plugin.test.mjs
@@ -8,35 +8,37 @@ describe('Title Plugin Tests', () => {
it('Should run the title macro', () => {
const part = {
name: 'test',
- draft: ({ points, Point, macro }) => {
+ draft: ({ points, Point, macro, part }) => {
points.anchor = new Point(-12, -34)
macro('title', {
at: points.anchor,
nr: 3,
title: 'unitTest',
})
+
+ return part
},
+ plugins: [plugin],
}
const Pattern = new Design({
data: { name: 'testPattern', version: 99 },
parts: [part],
- plugins: [plugin],
})
const pattern = new Pattern()
pattern.draft().render()
- let p = pattern.parts.test.points.__titleNr
+ let p = pattern.parts[0].test.points.__titleNr
expect(p.x).to.equal(-12)
expect(p.y).to.equal(-34)
expect(p.attributes.get('data-text')).to.equal('3')
expect(p.attributes.get('data-text-class')).to.equal('text-4xl fill-note font-bold')
expect(p.attributes.get('data-text-x')).to.equal('-12')
expect(p.attributes.get('data-text-y')).to.equal('-34')
- p = pattern.parts.test.points.__titleName
+ p = pattern.parts[0].test.points.__titleName
expect(p.attributes.get('data-text')).to.equal('unitTest')
expect(p.attributes.get('data-text-class')).to.equal('text-lg fill-current font-bold')
expect(p.attributes.get('data-text-x')).to.equal('-12')
expect(p.attributes.get('data-text-y')).to.equal('-26')
- p = pattern.parts.test.points.__titlePattern
+ p = pattern.parts[0].test.points.__titlePattern
expect(p.attributes.get('data-text')).to.equal('testPattern v99')
expect(p.attributes.get('data-text-class')).to.equal('fill-note')
expect(p.attributes.get('data-text-x')).to.equal('-12')
@@ -46,7 +48,7 @@ describe('Title Plugin Tests', () => {
it('Should run the title macro with append flag', () => {
const part = {
name: 'test',
- draft: ({ points, Point, macro }) => {
+ draft: ({ points, Point, macro, part }) => {
points.anchor = new Point(-12, -34).attr('data-text', '#')
macro('title', {
at: points.anchor,
@@ -54,16 +56,18 @@ describe('Title Plugin Tests', () => {
title: 'unitTest',
append: true,
})
+
+ return part
},
+ plugins: [plugin],
}
const Pattern = new Design({
data: { name: 'testPattern', version: 99 },
parts: [part],
- plugins: [plugin],
})
const pattern = new Pattern()
pattern.draft().render()
- let p = pattern.parts.test.points.__titleNr
+ let p = pattern.parts[0].test.points.__titleNr
expect(p.x).to.equal(-12)
expect(p.y).to.equal(-34)
expect(p.attributes.get('data-text')).to.equal('# 3')
@@ -75,7 +79,7 @@ describe('Title Plugin Tests', () => {
it('Should run the title macro with point prefix', () => {
const part = {
name: 'test',
- draft: ({ points, Point, macro }) => {
+ draft: ({ points, Point, macro, part }) => {
points.anchor = new Point(-12, -34).attr('data-text', '#')
macro('title', {
at: points.anchor,
@@ -83,28 +87,30 @@ describe('Title Plugin Tests', () => {
title: 'unitTest',
prefix: 'foo',
})
+
+ return part
},
+ plugins: [plugin],
}
const Pattern = new Design({
data: { name: 'testPattern', version: 99 },
parts: [part],
- plugins: [plugin],
})
const pattern = new Pattern()
pattern.draft().render()
- let p = pattern.parts.test.points._foo_titleNr
+ let p = pattern.parts[0].test.points._foo_titleNr
expect(p.x).to.equal(-12)
expect(p.y).to.equal(-34)
expect(p.attributes.get('data-text')).to.equal('3')
expect(p.attributes.get('data-text-class')).to.equal('text-4xl fill-note font-bold')
expect(p.attributes.get('data-text-x')).to.equal('-12')
expect(p.attributes.get('data-text-y')).to.equal('-34')
- p = pattern.parts.test.points._foo_titleName
+ p = pattern.parts[0].test.points._foo_titleName
expect(p.attributes.get('data-text')).to.equal('unitTest')
expect(p.attributes.get('data-text-class')).to.equal('text-lg fill-current font-bold')
expect(p.attributes.get('data-text-x')).to.equal('-12')
expect(p.attributes.get('data-text-y')).to.equal('-26')
- p = pattern.parts.test.points._foo_titlePattern
+ p = pattern.parts[0].test.points._foo_titlePattern
expect(p.attributes.get('data-text')).to.equal('testPattern v99')
expect(p.attributes.get('data-text-class')).to.equal('fill-note')
expect(p.attributes.get('data-text-x')).to.equal('-12')
diff --git a/sites/lab/components/layouts/lab.js b/sites/lab/components/layouts/lab.js
index e269676042c..61efdb474ff 100644
--- a/sites/lab/components/layouts/lab.js
+++ b/sites/lab/components/layouts/lab.js
@@ -7,17 +7,15 @@ export const BeforeNav = ({ app }) => (
-
-
+
>
)
-const LabLayout = ({ app, AltMenu, children=[] }) => (
+const LabLayout = ({ app, AltMenu, children = [] }) => (
+
diff --git a/sites/shared/components/mdx/example/index.js b/sites/shared/components/mdx/example/index.js
index 75848cca293..474e35ad990 100644
--- a/sites/shared/components/mdx/example/index.js
+++ b/sites/shared/components/mdx/example/index.js
@@ -1,33 +1,41 @@
-import React, { useState } from 'react'
-import { Examples } from '@freesewing/examples'
-import { Rendertest } from '@freesewing/rendertest'
-import { Tutorial } from '@freesewing/tutorial'
+import { Tab, Tabs } from '../tabs.js'
+import Md from 'react-markdown'
+import { plugin } from '@freesewing/plugin-bundle'
+import { Design } from '@freesewing/core'
import Svg from '../../workbench/draft/svg'
import Defs from '../../workbench/draft/defs'
import Stack from '../../workbench/draft/stack'
import { useGist } from 'shared/hooks/useGist'
-export const examplePatterns = {
- examples: Examples,
- //rendertest: Rendertest,
- //tutorial: Tutorial,
+// Get code from children
+const asText = (reactEl) => {
+ if (typeof reactEl.props.children === 'string') return reactEl.props.children
+ if (Array.isArray(reactEl.props.children)) {
+ return reactEl.props.children.map((el) => (typeof el === 'string' ? el : asText(el))).join('')
+ }
+ if (typeof reactEl.props.children === 'object') return asText(reactEl.props.children)
+
+ return ''
}
-const Example = ({ app, part, pattern='examples', xray=false }) => {
- const Pattern = examplePatterns[pattern]
+// The actual example
+const Example = ({ app, draft, xray = false }) => {
// State for gist
- const { gist, setGist, unsetGist, updateGist, gistReady, undoGist, resetGist } = useGist(
- 'example-mdx',
- app
- )
+ const { gist, unsetGist, updateGist } = useGist('example-mdx', app)
if (xray) {
gist._state.xray = { enabled: true }
gist.margin = 20
}
- if (part !== '') gist.only = [ "examples."+part]
- const draft = new Pattern(gist)
const patternProps = draft.draft().getRenderProps()
+ console.log(draft)
+ if (draft.store.logs.error.length > 0 || draft.setStores[0].logs.error.length > 0)
+ return (
+
+
{draft.store.logs.error.join('\n')}
+
{draft.setStores[0].logs.error.join('\n')}
+
+ )
return (