Merge pull request #3919 from freesewing/develop
Get up to date with develop
This commit is contained in:
commit
e9ab680c53
394 changed files with 9683 additions and 6225 deletions
|
@ -22,7 +22,7 @@
|
|||
</a><a
|
||||
href="#contributors-"
|
||||
title="All Contributors"
|
||||
><img src="https://img.shields.io/badge/all_contributors-106-pink.svg"
|
||||
><img src="https://img.shields.io/badge/all_contributors-107-pink.svg"
|
||||
alt="All Contributors"/>
|
||||
</a></p><p align='center'><a
|
||||
href="https://twitter.com/freesewing_org"
|
||||
|
@ -273,19 +273,20 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
|||
<td align="center" valign="top" width="14.28%"><a href="https://weblog.redisdead.net"><img src="https://avatars.githubusercontent.com/u/6494414?v=4?s=100" width="100px;" alt="hellgy"/><br /><sub><b>hellgy</b></sub></a><br /><a href="#design-hellgy" title="Design">🎨</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jackseye"><img src="https://avatars.githubusercontent.com/u/27834526?v=4?s=100" width="100px;" alt="jackseye"/><br /><sub><b>jackseye</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=jackseye" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/marckiesel"><img src="https://avatars.githubusercontent.com/u/39653780?v=4?s=100" width="100px;" alt="marckiesel"/><br /><sub><b>marckiesel</b></sub></a><br /><a href="#translation-marckiesel" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/marpants"><img src="https://avatars.githubusercontent.com/u/61366665?v=4?s=100" width="100px;" alt="marpants"/><br /><sub><b>marpants</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=marpants" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://tech.lgbt/@mergerg"><img src="https://avatars.githubusercontent.com/u/64447714?v=4?s=100" width="100px;" alt="mergerg"/><br /><sub><b>mergerg</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=raphaelsiz" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Mesil"><img src="https://avatars.githubusercontent.com/u/14284175?v=4?s=100" width="100px;" alt="mesil"/><br /><sub><b>mesil</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/issues?q=author%3Amesil" title="Bug reports">🐛</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Mesil"><img src="https://avatars.githubusercontent.com/u/14284175?v=4?s=100" width="100px;" alt="mesil"/><br /><sub><b>mesil</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/issues?q=author%3Amesil" title="Bug reports">🐛</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/starfetch"><img src="https://avatars.githubusercontent.com/u/80041179?v=4?s=100" width="100px;" alt="starfetch"/><br /><sub><b>starfetch</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=starfetch" title="Code">💻</a> <a href="https://github.com/freesewing/freesewing/commits?author=starfetch" title="Documentation">📖</a> <a href="#translation-starfetch" title="Translation">🌍</a> <a href="#design-starfetch" title="Design">🎨</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/timorl"><img src="https://avatars.githubusercontent.com/u/4363804?v=4?s=100" width="100px;" alt="timorl"/><br /><sub><b>timorl</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=timorl" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/ttimearl"><img src="https://avatars.githubusercontent.com/u/77916590?v=4?s=100" width="100px;" alt="ttimearl"/><br /><sub><b>ttimearl</b></sub></a><br /><a href="#content-ttimearl" title="Content">🖋</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/chrisgloom"><img src="https://avatars.githubusercontent.com/u/15905991?v=4?s=100" width="100px;" alt="tuesgloomsday"/><br /><sub><b>tuesgloomsday</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=chrisgloom" title="Documentation">📖</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/valadaptive"><img src="https://avatars.githubusercontent.com/u/79560998?v=4?s=100" width="100px;" alt="valadaptive"/><br /><sub><b>valadaptive</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=valadaptive" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/viocky"><img src="https://avatars.githubusercontent.com/u/39279173?v=4?s=100" width="100px;" alt="viocky"/><br /><sub><b>viocky</b></sub></a><br /><a href="#translation-viocky" title="Translation">🌍</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/woolishboy"><img src="https://avatars.githubusercontent.com/u/57816321?v=4?s=100" width="100px;" alt="woolishboy"/><br /><sub><b>woolishboy</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=woolishboy" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/woolishboy"><img src="https://avatars.githubusercontent.com/u/57816321?v=4?s=100" width="100px;" alt="woolishboy"/><br /><sub><b>woolishboy</b></sub></a><br /><a href="https://github.com/freesewing/freesewing/commits?author=woolishboy" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/cloutiy"><img src="https://avatars.githubusercontent.com/u/8433147?v=4?s=100" width="100px;" alt="yc"/><br /><sub><b>yc</b></sub></a><br /><a href="#translation-cloutiy" title="Translation">🌍</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// This file is auto-generated | All changes you make will be overwritten.
|
||||
export const name = '@freesewing/plugin-annotations'
|
||||
export const version = '3.0.0-alpha.8'
|
||||
export const version = '3.0.0-alpha.9'
|
||||
export const data = { name, version }
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@freesewing/plugin-annotations",
|
||||
"version": "3.0.0-alpha.8",
|
||||
"version": "3.0.0-alpha.9",
|
||||
"description": "A FreeSewing plugin that provides pattern annotations",
|
||||
"author": "Joost De Cock <joost@joost.at> (https://github.com/joostdecock)",
|
||||
"homepage": "https://freesewing.org/",
|
||||
|
@ -46,7 +46,7 @@
|
|||
"wcibuild_step1": "node build.mjs"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@freesewing/core": "3.0.0-alpha.8"
|
||||
"@freesewing/core": "3.0.0-alpha.9"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -12,8 +12,12 @@ export const bannerMacros = {
|
|||
}
|
||||
so.path.attr('data-text-dy', so.dy).attr('data-text-class', `${so.className} center`)
|
||||
const spacer = ' '.repeat(so.spaces)
|
||||
let banner = spacer
|
||||
for (let i = 0; i < so.repeat; i++) banner += so.text + ' '.repeat(so.spaces)
|
||||
so.path.attr('data-text', banner)
|
||||
|
||||
for (let i = 0; i < so.repeat; i++) {
|
||||
so.path.attr('data-text', spacer)
|
||||
so.path.attr('data-text', so.text)
|
||||
}
|
||||
|
||||
so.path.attr('data-text', spacer)
|
||||
},
|
||||
}
|
||||
|
|
103
plugins/plugin-annotations/src/cutlist.mjs
Normal file
103
plugins/plugin-annotations/src/cutlist.mjs
Normal file
|
@ -0,0 +1,103 @@
|
|||
export const cutlistStores = [
|
||||
['cutlist.addCut', addCut],
|
||||
['cutlist.removeCut', removeCut],
|
||||
['cutlist.setGrain', setGrain],
|
||||
['cutlist.setCutOnFold', setCutOnFold],
|
||||
['cutlist.getCutFabrics', getCutFabrics],
|
||||
]
|
||||
|
||||
export const cutlistHooks = {
|
||||
prePartDraft: [
|
||||
function (pattern) {
|
||||
const injectedPart = pattern.config.inject[pattern.activePart]
|
||||
if (!injectedPart) return
|
||||
|
||||
const store = pattern.setStores[pattern.activeSet]
|
||||
const injectedCutlist = store.get(['cutlist', injectedPart], {})
|
||||
store.set(['cutlist', pattern.activePart], { ...injectedCutlist })
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a set of cutting instructions for the part
|
||||
* @param {Store} store the Store
|
||||
* @param {Object} so a set of cutting instructions for a material
|
||||
* @param {number} so.cut = 2 the number of pieces to cut from the specified fabric
|
||||
* @param {string} so.material = fabric the name of the material to cut from
|
||||
* @param {boolean} so.identical = false should even numbers of pieces be cut in the same direction or mirrored
|
||||
* @param {boolean} so.bias = false should the pieces in these cutting instructions be cut on the bias
|
||||
* @param {boolean} so.ignoreOnFold should these cutting instructions ignore any cutOnFold information set by the part
|
||||
*/
|
||||
function addCut(store, so = {}) {
|
||||
const { cut = 2, material = 'fabric', identical = false, bias = false, ignoreOnFold = false } = so
|
||||
const partName = store.get('activePart')
|
||||
if (cut === false) {
|
||||
if (material === false) store.unset(['cutlist', partName, 'materials'])
|
||||
else store.unset(['cutlist', partName, 'materials', material])
|
||||
return store
|
||||
}
|
||||
if (!(Number.isInteger(cut) && cut > -1)) {
|
||||
store.log.error(`Tried to set cut to a value that is not a positive integer`)
|
||||
return store
|
||||
}
|
||||
if (typeof material !== 'string') {
|
||||
store.log.warning(`Tried to set material to a value that is not a string`)
|
||||
return store
|
||||
}
|
||||
const path = ['cutlist', partName, 'materials', material]
|
||||
const existing = store.get(path, [])
|
||||
store.set(path, existing.concat({ cut, identical, bias, ignoreOnFold }))
|
||||
|
||||
return store
|
||||
}
|
||||
|
||||
/** Method to remove the cut info */
|
||||
function removeCut(store, material = false) {
|
||||
return addCut(store, { cut: false, material })
|
||||
}
|
||||
|
||||
/** Method to add the grain info */
|
||||
function setGrain(store, grain = false) {
|
||||
const partName = store.get('activePart')
|
||||
const path = ['cutlist', partName, 'grain']
|
||||
if (grain === false) return store.unset(path)
|
||||
if (typeof grain !== 'number') {
|
||||
store.log.error('Called part.setGrain() with a value that is not a number')
|
||||
return store
|
||||
}
|
||||
return store.set(path, grain)
|
||||
}
|
||||
|
||||
/** Method to add the cutOnFold info */
|
||||
function setCutOnFold(store, p1, p2) {
|
||||
const partName = store.get('activePart')
|
||||
const path = ['cutlist', partName, 'cutOnFold']
|
||||
if (p1 === false && typeof p2 === 'undefined') {
|
||||
return store.unset(path)
|
||||
}
|
||||
if (!isNaN(p1.x) && !isNaN(p1.y) && !isNaN(p2.x) && !isNaN(p2.y)) {
|
||||
store.set(path, [p1, p2])
|
||||
} else
|
||||
store.log.error('Called part.setCutOnFold() but at least one parameter is not a Point instance')
|
||||
|
||||
return store
|
||||
}
|
||||
|
||||
/** Get a list of fabrics used by the pattern for the given settings */
|
||||
function getCutFabrics(store, settings) {
|
||||
const cutlist = store.get('cutlist')
|
||||
const list = settings.only ? [].concat(settings.only) : Object.keys(cutlist)
|
||||
|
||||
const fabrics = []
|
||||
list.forEach((partName) => {
|
||||
if (!cutlist[partName]?.materials) {
|
||||
return
|
||||
}
|
||||
for (var m in cutlist[partName].materials) {
|
||||
if (!fabrics.includes(m)) fabrics.push(m)
|
||||
}
|
||||
})
|
||||
|
||||
return fabrics
|
||||
}
|
|
@ -18,17 +18,15 @@ export const cutonfoldDefs = [
|
|||
|
||||
// Export macros
|
||||
export const cutonfoldMacros = {
|
||||
cutonfold: function (so, { points, paths, Path, complete, setCutOnFold, setGrain, scale }) {
|
||||
cutonfold: function (so, { points, paths, Path, complete, store, scale }) {
|
||||
if (so === false) {
|
||||
delete points.cutonfoldFrom
|
||||
delete points.cutonfoldTo
|
||||
delete points.cutonfoldVia1
|
||||
delete points.cutonfoldVia2
|
||||
delete paths.cutonfold
|
||||
// setCutOnFold relies on plugin-cutlist
|
||||
if (typeof setCutOnFold === 'function') {
|
||||
setCutOnFold(false) // Restore default
|
||||
}
|
||||
delete paths.cutonfoldCutonfold
|
||||
|
||||
store.cutlist.setCutOnFold(false) // Restore default
|
||||
return true
|
||||
}
|
||||
so = {
|
||||
|
@ -37,10 +35,11 @@ export const cutonfoldMacros = {
|
|||
prefix: 'cutonfold',
|
||||
...so,
|
||||
}
|
||||
if (typeof setCutOnFold === 'function') {
|
||||
setCutOnFold(so.from, so.to)
|
||||
if (so.grainline) setGrain(so.from.angle(so.to))
|
||||
}
|
||||
|
||||
// store in cutlist
|
||||
store.cutlist.setCutOnFold(so.from, so.to)
|
||||
if (so.grainline) store.cutlist.setGrain(so.from.angle(so.to))
|
||||
|
||||
if (complete) {
|
||||
points[so.prefix + 'From'] = so.from.shiftFractionTowards(so.to, so.margin / 100)
|
||||
points[so.prefix + 'To'] = so.to.shiftFractionTowards(so.from, so.margin / 100)
|
||||
|
|
|
@ -20,22 +20,22 @@ const dflts = { text: 'grainline' }
|
|||
|
||||
// Export macros
|
||||
export const grainlineMacros = {
|
||||
grainline: function (so = {}, { points, paths, Path, complete, setGrain }) {
|
||||
grainline: function (so = {}, { points, paths, Path, complete, store }) {
|
||||
if (so === false) {
|
||||
delete points.grainlineFrom
|
||||
delete points.grainlineTo
|
||||
delete paths.grainline
|
||||
setGrain(90) // Restoring default
|
||||
if (store.cutlist?.setGrain) store.cutlist.setGrain(90) // Restoring default
|
||||
return true
|
||||
}
|
||||
so = {
|
||||
...dflts,
|
||||
...so,
|
||||
}
|
||||
// setGrain relies on plugin-cutlist
|
||||
if (typeof setGrain === 'function') {
|
||||
setGrain(so.from.angle(so.to))
|
||||
}
|
||||
|
||||
// store in cutlist
|
||||
store.cutlist.setGrain(so.from.angle(so.to))
|
||||
|
||||
if (complete) {
|
||||
points.grainlineFrom = so.from.shiftFractionTowards(so.to, 0.05)
|
||||
points.grainlineTo = so.to.shiftFractionTowards(so.from, 0.05)
|
||||
|
|
|
@ -8,6 +8,7 @@ import { bannerMacros } from './banner.mjs'
|
|||
import { bannerboxMacros } from './bannerbox.mjs'
|
||||
import { bartackMacros } from './bartack.mjs'
|
||||
import { crossboxMacros } from './crossbox.mjs'
|
||||
import { cutlistStores, cutlistHooks } from './cutlist.mjs'
|
||||
import { scaleboxMacros } from './scalebox.mjs'
|
||||
import { titleMacros } from './title.mjs'
|
||||
// Defs and Macros
|
||||
|
@ -41,6 +42,7 @@ export const plugin = {
|
|||
}
|
||||
},
|
||||
],
|
||||
prePartDraft: [...cutlistHooks.prePartDraft],
|
||||
},
|
||||
macros: {
|
||||
...bannerMacros,
|
||||
|
@ -55,6 +57,7 @@ export const plugin = {
|
|||
...sewtogetherMacros,
|
||||
...titleMacros,
|
||||
},
|
||||
store: [...cutlistStores],
|
||||
}
|
||||
|
||||
export const annotationsPlugin = plugin
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
const titleMacro = function (so, { points, scale, locale, store }) {
|
||||
const titleMacro = function (so, { points, scale, locale, store, part }) {
|
||||
const prefix = so.prefix || ''
|
||||
let overwrite = !so.append
|
||||
|
||||
// Passing `false` will remove the title
|
||||
if (so === false) {
|
||||
if (so === false || overwrite) {
|
||||
for (const id of [
|
||||
`_${prefix}_titleNr`,
|
||||
`_${prefix}_titleName`,
|
||||
|
@ -11,7 +12,8 @@ const titleMacro = function (so, { points, scale, locale, store }) {
|
|||
`_${prefix}_exportDate`,
|
||||
])
|
||||
delete points[id]
|
||||
return true
|
||||
|
||||
if (so === false) return true
|
||||
}
|
||||
|
||||
const transform = function (anchor) {
|
||||
|
@ -20,44 +22,72 @@ const titleMacro = function (so, { points, scale, locale, store }) {
|
|||
|
||||
return `matrix(${so.scale}, 0, 0, ${so.scale}, ${cx}, ${cy}) rotate(${so.rotation} ${anchor.x} ${anchor.y})`
|
||||
}
|
||||
let shift = 8
|
||||
const nextPoint = (text, textClass, shiftAmt = shift) => {
|
||||
const newPoint = so.at.shift(-90 - so.rotation, shiftAmt * so.scale).addText(text, textClass)
|
||||
newPoint.attr('data-text-transform', transform(newPoint))
|
||||
return newPoint
|
||||
}
|
||||
const defaults = {
|
||||
scale: 1,
|
||||
rotation: 0,
|
||||
cutlist: true,
|
||||
}
|
||||
|
||||
so = { ...defaults, ...so }
|
||||
so.scale = so.scale * scale
|
||||
let overwrite = true
|
||||
if (so.append) overwrite = false
|
||||
|
||||
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) {
|
||||
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)))
|
||||
points[`_${prefix}_titleName`] = nextPoint(so.title, 'text-lg fill-current font-bold')
|
||||
shift += 8
|
||||
}
|
||||
|
||||
// Cut List instructions
|
||||
const partCutlist = store.get(['cutlist', part.name])
|
||||
// if there's a cutlist and it should be included
|
||||
if (so.cutlist && partCutlist?.materials) {
|
||||
// get the default cutonfold
|
||||
const cutonfold = partCutlist.cutOnFold
|
||||
// each material
|
||||
for (const material in partCutlist.materials) {
|
||||
// each set of instructions
|
||||
partCutlist.materials[material].forEach(({ cut, identical, bias, ignoreOnFold }, c) => {
|
||||
// make a new point for this set of instructions
|
||||
const cutPoint = nextPoint('plugin:cut', 'text-md fill-current').addText(cut)
|
||||
|
||||
// if they're not identical, add that to the point's text
|
||||
if (!identical && cut > 1) cutPoint.addText('plugin:mirrored')
|
||||
|
||||
// if they should be cut on the fold add that, with bias or without
|
||||
if (cutonfold && !ignoreOnFold)
|
||||
cutPoint.addText(bias ? 'plugin:onFoldAndBias' : 'plugin:onFoldLower')
|
||||
// otherwise if they should be on the bias, say so
|
||||
else if (bias) cutPoint.addText('plugin:onBias')
|
||||
|
||||
// add 'from' the material
|
||||
cutPoint.addText('plugin:from').addText('plugin:' + material)
|
||||
|
||||
// save and shift
|
||||
points[`_${prefix}_titleCut_${material}_${c}`] = cutPoint
|
||||
shift += 8
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
let name = store.data?.name || 'No Name'
|
||||
name = name.replace('@freesewing/', '')
|
||||
points[`_${prefix}_titlePattern`] = so.at
|
||||
.shift(-90 - so.rotation, shift * so.scale)
|
||||
.attr('data-text', name)
|
||||
.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)))
|
||||
name += ' v' + (store.data?.version || 'No Version')
|
||||
points[`_${prefix}_titlePattern`] = nextPoint(name, 'fill-note')
|
||||
|
||||
if (store.data.for) {
|
||||
shift += 8
|
||||
points[`_${prefix}_titleFor`] = so.at
|
||||
.shift(-90 - so.rotation, shift * so.scale)
|
||||
.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)))
|
||||
points[`_${prefix}_titleFor`] = nextPoint(`( ${store.data.for} )`, 'fill-current font-bold')
|
||||
}
|
||||
shift += 6
|
||||
const now = new Date()
|
||||
|
@ -65,20 +95,13 @@ const titleMacro = function (so, { points, scale, locale, store }) {
|
|||
let mins = now.getMinutes()
|
||||
if (hours < 10) hours = `0${hours}`
|
||||
if (mins < 10) mins = `0${mins}`
|
||||
points[`_${prefix}_exportDate`] = so.at
|
||||
.shift(-90 - so.rotation, shift * so.scale)
|
||||
.attr(
|
||||
'data-text',
|
||||
now.toLocaleDateString(locale || 'en', {
|
||||
weekday: 'long',
|
||||
year: 'numeric',
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
})
|
||||
)
|
||||
.attr('data-text', `@ ${hours}:${mins}`)
|
||||
.attr('data-text-class', 'text-sm')
|
||||
.attr('data-text-transform', transform(so.at.shift(-90 - so.rotation, shift * so.scale)))
|
||||
const exportDate = now.toLocaleDateString(locale || 'en', {
|
||||
weekday: 'long',
|
||||
year: 'numeric',
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
})
|
||||
points[`_${prefix}_exportDate`] = nextPoint(`${exportDate}@ ${hours}:${mins}`, 'text-sm')
|
||||
}
|
||||
|
||||
// Export macros
|
||||
|
|
|
@ -27,7 +27,7 @@ describe('Banner Plugin Tests', () => {
|
|||
pattern.draft()
|
||||
const c = pattern.parts[0].test.paths.example
|
||||
expect(c.attributes.get('data-text')).to.equal(
|
||||
'            foo            foo            foo            foo            foo            foo            foo            foo            foo            foo            '
|
||||
'             foo              foo              foo              foo              foo              foo              foo              foo              foo              foo             '
|
||||
)
|
||||
expect(c.attributes.get('data-text-class').trim()).to.equal('center')
|
||||
expect(c.attributes.get('data-text-dy')).to.equal('-1')
|
||||
|
@ -56,7 +56,7 @@ describe('Banner Plugin Tests', () => {
|
|||
const pattern = new design()
|
||||
pattern.draft()
|
||||
const c = pattern.parts[0].test.paths.example2
|
||||
expect(c.attributes.get('data-text')).to.equal('  foo  foo  ')
|
||||
expect(c.attributes.get('data-text')).to.equal('   foo    foo   ')
|
||||
})
|
||||
|
||||
it('Number of repetitions should be configurable', () => {
|
||||
|
@ -82,6 +82,8 @@ describe('Banner Plugin Tests', () => {
|
|||
const pattern = new design()
|
||||
pattern.draft()
|
||||
const c = pattern.parts[0].test.paths.example3
|
||||
expect(c.attributes.get('data-text')).to.equal(' foo foo foo foo ')
|
||||
expect(c.attributes.get('data-text')).to.equal(
|
||||
'  foo   foo   foo   foo  '
|
||||
)
|
||||
})
|
||||
})
|
||||
|
|
204
plugins/plugin-annotations/tests/cutlist.test.mjs
Normal file
204
plugins/plugin-annotations/tests/cutlist.test.mjs
Normal file
|
@ -0,0 +1,204 @@
|
|||
import chai from 'chai'
|
||||
import { Design } from '@freesewing/core'
|
||||
import { annotationsPlugin } from '../src/index.mjs'
|
||||
|
||||
const expect = chai.expect
|
||||
|
||||
describe('Cutlist Plugin Tests', () => {
|
||||
it('Draft method should receive added methods', () => {
|
||||
let methods
|
||||
const part = {
|
||||
name: 'example_part',
|
||||
draft: ({ store, part }) => {
|
||||
methods = { ...store.cutlist }
|
||||
|
||||
return part
|
||||
},
|
||||
plugins: [annotationsPlugin],
|
||||
}
|
||||
const Test = new Design({ parts: [part] })
|
||||
const pattern = new Test()
|
||||
pattern.draft()
|
||||
expect(methods.addCut).to.be.a('function')
|
||||
expect(methods.removeCut).to.be.a('function')
|
||||
expect(methods.setGrain).to.be.a('function')
|
||||
expect(methods.setCutOnFold).to.be.a('function')
|
||||
expect(methods.getCutFabrics).to.be.a('function')
|
||||
})
|
||||
|
||||
it('Should handle addCut() with defaults', () => {
|
||||
const part = {
|
||||
name: 'example_part',
|
||||
draft: ({ store, part }) => {
|
||||
store.cutlist.addCut()
|
||||
|
||||
return part
|
||||
},
|
||||
plugins: [annotationsPlugin],
|
||||
}
|
||||
const Test = new Design({ parts: [part] })
|
||||
const pattern = new Test()
|
||||
pattern.draft()
|
||||
expect(pattern.setStores[0].cutlist.example_part.materials.fabric).to.have.lengthOf(1)
|
||||
expect(pattern.setStores[0].cutlist.example_part.materials.fabric[0]).to.deep.equal({
|
||||
cut: 2,
|
||||
identical: false,
|
||||
bias: false,
|
||||
ignoreOnFold: false,
|
||||
})
|
||||
})
|
||||
|
||||
it('Should handle addCut() with non-defaults', () => {
|
||||
const part = {
|
||||
name: 'example_part',
|
||||
draft: ({ store, part }) => {
|
||||
store.cutlist.addCut({ cut: 3, material: 'lining', identical: true })
|
||||
|
||||
return part
|
||||
},
|
||||
plugins: [annotationsPlugin],
|
||||
}
|
||||
const Test = new Design({ parts: [part] })
|
||||
const pattern = new Test()
|
||||
pattern.draft()
|
||||
expect(pattern.setStores[0].cutlist.example_part.materials.lining).to.have.lengthOf(1)
|
||||
expect(pattern.setStores[0].cutlist.example_part.materials.lining[0]).to.deep.equal({
|
||||
cut: 3,
|
||||
identical: true,
|
||||
bias: false,
|
||||
ignoreOnFold: false,
|
||||
})
|
||||
})
|
||||
|
||||
it('Should remove cut info via addCut(false)', () => {
|
||||
const part = {
|
||||
name: 'example_part',
|
||||
draft: ({ store, part }) => {
|
||||
store.cutlist.addCut(2, 'fabric')
|
||||
store.cutlist.addCut(4, 'lining', true)
|
||||
store.cutlist.addCut(false, 'lining')
|
||||
|
||||
return part
|
||||
},
|
||||
plugins: [annotationsPlugin],
|
||||
}
|
||||
const Test = new Design({ parts: [part] })
|
||||
const pattern = new Test()
|
||||
pattern.draft()
|
||||
expect(pattern.setStores[0].cutlist.example_part.materials.lining).to.be.undefined
|
||||
})
|
||||
|
||||
it('Should remove cut info for a material via removeCut()', () => {
|
||||
const part = {
|
||||
name: 'example_part',
|
||||
draft: ({ store, part }) => {
|
||||
store.cutlist.addCut(2, 'fabric')
|
||||
store.cutlist.addCut(4, 'lining', true)
|
||||
store.cutlist.removeCut('lining')
|
||||
|
||||
return part
|
||||
},
|
||||
plugins: [annotationsPlugin],
|
||||
}
|
||||
const Test = new Design({ parts: [part] })
|
||||
const pattern = new Test()
|
||||
pattern.draft()
|
||||
expect(pattern.setStores[0].cutlist.example_part.materials.lining).to.be.undefined
|
||||
expect(pattern.setStores[0].cutlist.example_part.materials.fabric[0].cut).to.equal(2)
|
||||
})
|
||||
|
||||
it('Should remove cut info for all materials via removeCut(true)', () => {
|
||||
const part = {
|
||||
name: 'example_part',
|
||||
draft: ({ store, part }) => {
|
||||
store.cutlist.addCut(2, 'fabric')
|
||||
store.cutlist.addCut(4, 'lining', true)
|
||||
store.cutlist.removeCut()
|
||||
|
||||
return part
|
||||
},
|
||||
plugins: [annotationsPlugin],
|
||||
}
|
||||
const Test = new Design({ parts: [part] })
|
||||
const pattern = new Test()
|
||||
pattern.draft()
|
||||
expect(pattern.setStores[0].cutlist.example_part.materials).to.be.undefined
|
||||
})
|
||||
|
||||
it('Should set the grain via setGrain()', () => {
|
||||
const part = {
|
||||
name: 'example_part',
|
||||
draft: ({ store, part }) => {
|
||||
store.cutlist.setGrain(45)
|
||||
|
||||
return part
|
||||
},
|
||||
plugins: [annotationsPlugin],
|
||||
}
|
||||
const Test = new Design({ parts: [part] })
|
||||
const pattern = new Test()
|
||||
pattern.draft()
|
||||
expect(pattern.setStores[0].cutlist.example_part.grain).to.equal(45)
|
||||
})
|
||||
|
||||
it('Should remove the grain via setGrain(false)', () => {
|
||||
const part = {
|
||||
name: 'example_part',
|
||||
draft: ({ store, part }) => {
|
||||
store.cutlist.setGrain(45)
|
||||
store.cutlist.setGrain(false)
|
||||
|
||||
return part
|
||||
},
|
||||
plugins: [annotationsPlugin],
|
||||
}
|
||||
const Test = new Design({ parts: [part] })
|
||||
const pattern = new Test()
|
||||
pattern.draft()
|
||||
expect(pattern.setStores[0].cutlist.example_part.grain).to.be.undefined
|
||||
})
|
||||
|
||||
it('Should set the cutOnFold via setCutOnFold(p1, p2)', () => {
|
||||
const part = {
|
||||
name: 'example_part',
|
||||
draft: ({ Point, store, part }) => {
|
||||
try {
|
||||
store.cutlist.setCutOnFold(new Point(2, 2), new Point(200, 200))
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
|
||||
return part
|
||||
},
|
||||
plugins: [annotationsPlugin],
|
||||
}
|
||||
const Test = new Design({ parts: [part] })
|
||||
const pattern = new Test()
|
||||
pattern.draft()
|
||||
expect(pattern.setStores[0].cutlist.example_part.cutOnFold[0].x).to.equal(2)
|
||||
expect(pattern.setStores[0].cutlist.example_part.cutOnFold[0].y).to.equal(2)
|
||||
expect(pattern.setStores[0].cutlist.example_part.cutOnFold[1].x).to.equal(200)
|
||||
expect(pattern.setStores[0].cutlist.example_part.cutOnFold[1].y).to.equal(200)
|
||||
})
|
||||
|
||||
it('Should removet the cutOnFold via setCutOnFold(false)', () => {
|
||||
const part = {
|
||||
name: 'example_part',
|
||||
draft: ({ Point, store, part }) => {
|
||||
try {
|
||||
store.cutlist.setCutOnFold(new Point(2, 2), new Point(200, 200))
|
||||
store.cutlist.setCutOnFold(false)
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
|
||||
return part
|
||||
},
|
||||
plugins: [annotationsPlugin],
|
||||
}
|
||||
const Test = new Design({ parts: [part] })
|
||||
const pattern = new Test()
|
||||
pattern.draft()
|
||||
expect(pattern.setStores[0].cutlist.example_part.cutOnFold).to.be.undefined
|
||||
})
|
||||
})
|
Loading…
Add table
Add a link
Reference in a new issue