wip(core): Added support for (part-level) optionGroups
This needs some work when merging deeply nested options, but it's a start
This commit is contained in:
parent
681a1fc657
commit
62fae66d25
3 changed files with 177 additions and 3 deletions
|
@ -48,8 +48,8 @@ let result
|
||||||
...options,
|
...options,
|
||||||
minify: false,
|
minify: false,
|
||||||
sourcemap: false,
|
sourcemap: false,
|
||||||
outfile: 'tests/dist/index.mjs',
|
outfile: 'tests/dist/index.js',
|
||||||
format: 'esm',
|
format: 'cjs',
|
||||||
external: [],
|
external: [],
|
||||||
})
|
})
|
||||||
.catch(() => process.exit(1))
|
.catch(() => process.exit(1))
|
||||||
|
|
|
@ -397,6 +397,75 @@ const addPartOptions = (part, config) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (part.from) addPartOptions(part.from, config)
|
if (part.from) addPartOptions(part.from, config)
|
||||||
|
if (part.after) {
|
||||||
|
if (Array.isArray(part.after)) {
|
||||||
|
for (const dep of part.after) addPartOptions(dep, config)
|
||||||
|
} else addPartOptions(part.after, config)
|
||||||
|
}
|
||||||
|
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper method for detecting a array with only strings
|
||||||
|
const isStringArray = val => (Array.isArray(val) && val.length > 0)
|
||||||
|
? val.reduce((prev=true, cur) => (prev && typeof cur === 'string'))
|
||||||
|
: false
|
||||||
|
// Helper method for detecting an object
|
||||||
|
const isObject = obj => obj && typeof obj === 'object'
|
||||||
|
|
||||||
|
// Hat-tip to jhildenbiddle => https://stackoverflow.com/a/48218209
|
||||||
|
const mergeOptionSubgroup = (...objects) => objects.reduce((prev, obj) => {
|
||||||
|
Object.keys(obj).forEach(key => {
|
||||||
|
const pVal = prev[key];
|
||||||
|
const oVal = obj[key];
|
||||||
|
|
||||||
|
if (Array.isArray(pVal) && Array.isArray(oVal)) {
|
||||||
|
prev[key] = pVal.concat(...oVal);
|
||||||
|
}
|
||||||
|
else if (isObject(pVal) && isObject(oVal)) {
|
||||||
|
prev[key] = mergeOptionSubgroup(pVal, oVal);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
prev[key] = oVal;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return prev
|
||||||
|
}, {})
|
||||||
|
|
||||||
|
const mergeOptionGroups = (cur, add) => {
|
||||||
|
if (isStringArray(cur) && isStringArray(add)) return [...new Set([...cur, ...add])]
|
||||||
|
else if (!Array.isArray(cur) && !Array.isArray(add)) return mergeOptionSubgroup(cur, add)
|
||||||
|
else {
|
||||||
|
const all = [...cur]
|
||||||
|
for (const entry of add) {
|
||||||
|
if (typeof add === 'string' && all.indexOf(entry) === -1) all.push(entry)
|
||||||
|
else all.push(entry)
|
||||||
|
}
|
||||||
|
return all
|
||||||
|
}
|
||||||
|
|
||||||
|
return cur
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add part-level optionGroups
|
||||||
|
const addPartOptionGroups = (part, config) => {
|
||||||
|
if (typeof config.optionGroups === 'undefined') {
|
||||||
|
if (part.optionGroups) config.optionGroups = part.optionGroups
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
if (part.optionGroups) {
|
||||||
|
for (const group in part.optionGroups) {
|
||||||
|
if (typeof config.optionGroups[group] === 'undefined') config.optionGroups[group] = part.optionGroups[group]
|
||||||
|
else config.optionGroups[group] = mergeOptionGroups(config.optionGroups[group], part.optionGroups[group])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (part.from) addPartOptionGroups(part.from, config)
|
||||||
|
if (part.after) {
|
||||||
|
if (Array.isArray(part.after)) {
|
||||||
|
for (const dep of part.after) addPartOptionGroups(dep, config)
|
||||||
|
} else addPartOptionGroups(part.after, config)
|
||||||
|
}
|
||||||
|
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
@ -410,6 +479,11 @@ const addPartMeasurements = (part, config, list=false) => {
|
||||||
for (const m of part.measurements) list.push(m)
|
for (const m of part.measurements) list.push(m)
|
||||||
}
|
}
|
||||||
if (part.from) addPartMeasurements(part.from, config, list)
|
if (part.from) addPartMeasurements(part.from, config, list)
|
||||||
|
if (part.after) {
|
||||||
|
if (Array.isArray(part.after)) {
|
||||||
|
for (const dep of part.after) addPartMeasurements(dep, config, list)
|
||||||
|
} else addPartMeasurements(part.after, config, list)
|
||||||
|
}
|
||||||
|
|
||||||
// Weed out duplicates
|
// Weed out duplicates
|
||||||
config.measurements = [...new Set(list)]
|
config.measurements = [...new Set(list)]
|
||||||
|
@ -429,6 +503,11 @@ const addPartOptionalMeasurements = (part, config, list=false) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (part.from) addPartOptionalMeasurements(part.from, config, list)
|
if (part.from) addPartOptionalMeasurements(part.from, config, list)
|
||||||
|
if (part.after) {
|
||||||
|
if (Array.isArray(part.after)) {
|
||||||
|
for (const dep of part.after) addPartOptionalMeasurements(dep, config, list)
|
||||||
|
} else addPartOptionalMeasurements(part.after, config, list)
|
||||||
|
}
|
||||||
|
|
||||||
// Weed out duplicates
|
// Weed out duplicates
|
||||||
config.optionalMeasurements = [...new Set(list)]
|
config.optionalMeasurements = [...new Set(list)]
|
||||||
|
@ -471,6 +550,7 @@ export const addPartConfig = (part, config) => {
|
||||||
config = addPartMeasurements(part, config)
|
config = addPartMeasurements(part, config)
|
||||||
config = addPartOptionalMeasurements(part, config)
|
config = addPartOptionalMeasurements(part, config)
|
||||||
config = addPartDependencies(part, config)
|
config = addPartDependencies(part, config)
|
||||||
|
config = addPartOptionGroups(part, config)
|
||||||
|
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
let expect = require("chai").expect;
|
let expect = require("chai").expect;
|
||||||
let freesewing = require("../dist/index.js");
|
let freesewing = require("./dist/index.js");
|
||||||
it("Pattern constructor should initialize object", () => {
|
it("Pattern constructor should initialize object", () => {
|
||||||
let pattern = new freesewing.Pattern({
|
let pattern = new freesewing.Pattern({
|
||||||
foo: "bar",
|
foo: "bar",
|
||||||
|
@ -1023,3 +1023,97 @@ it("Design constructor should resolve nested dependencies (2022)", () => {
|
||||||
expect(pattern.parts.partD.paths.d.ops[1].to.x).to.equal(44)
|
expect(pattern.parts.partD.paths.d.ops[1].to.x).to.equal(44)
|
||||||
expect(pattern.parts.partD.paths.d.ops[1].to.y).to.equal(44)
|
expect(pattern.parts.partD.paths.d.ops[1].to.y).to.equal(44)
|
||||||
})
|
})
|
||||||
|
it("Pattern should merge optiongroups", () => {
|
||||||
|
const partA = {
|
||||||
|
name: "partA",
|
||||||
|
options: { optionA: { bool: true } },
|
||||||
|
measurements: [ 'measieA' ],
|
||||||
|
optionalMeasurements: [ 'optmeasieA' ],
|
||||||
|
optionGroups: {
|
||||||
|
simple: ['simplea1', 'simplea2', 'simplea3'],
|
||||||
|
nested: {
|
||||||
|
nested1: [ 'nested1a1', 'nested1a2', 'nested1a3' ],
|
||||||
|
},
|
||||||
|
subnested: {
|
||||||
|
subnested1: [
|
||||||
|
'subnested1a1',
|
||||||
|
'subnested1a2',
|
||||||
|
'subnested1a3',
|
||||||
|
{
|
||||||
|
subsubgroup: [
|
||||||
|
'subsuba1',
|
||||||
|
'subsuba2',
|
||||||
|
{
|
||||||
|
subsubsubgroup: [ 'subsubsub1', 'simplea1' ],
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
draft: part => part,
|
||||||
|
}
|
||||||
|
const partB = {
|
||||||
|
name: "partB",
|
||||||
|
from: partA,
|
||||||
|
options: { optionB: { pct: 12, min: 2, max: 20 } },
|
||||||
|
measurements: [ 'measieB' ],
|
||||||
|
optionalMeasurements: [ 'optmeasieB', 'measieA' ],
|
||||||
|
optionGroups: {
|
||||||
|
simple: ['simpleb1', 'simpleb2', 'simpleb3'],
|
||||||
|
bsimple: ['bsimpleb1', 'bsimpleb2', 'bsimpleb3'],
|
||||||
|
nested: {
|
||||||
|
nested2: [ 'nested2b1', 'nested2b2', 'nested2b3' ],
|
||||||
|
},
|
||||||
|
subnested: {
|
||||||
|
subnested1: [
|
||||||
|
'subnested1b1',
|
||||||
|
'subnested1b2',
|
||||||
|
'subnested1b3',
|
||||||
|
{
|
||||||
|
subsubgroup: [
|
||||||
|
'subsubb1',
|
||||||
|
'subsubb2',
|
||||||
|
{
|
||||||
|
subsubsubgroup: [ 'bsubsubsub1', 'simplea1' ],
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
draft: part => part,
|
||||||
|
}
|
||||||
|
let Design, pattern
|
||||||
|
try {
|
||||||
|
Design = new freesewing.Design({ parts: [ partB ] });
|
||||||
|
pattern = new Design().init()
|
||||||
|
} catch(err) {
|
||||||
|
console.log(err)
|
||||||
|
}
|
||||||
|
const og = pattern.config.optionGroups
|
||||||
|
expect(og.simple.length).to.equal(6)
|
||||||
|
expect(og.simple.indexOf('simplea1') === -1).to.equal(false)
|
||||||
|
expect(og.simple.indexOf('simplea2') === -1).to.equal(false)
|
||||||
|
expect(og.simple.indexOf('simplea3') === -1).to.equal(false)
|
||||||
|
expect(og.simple.indexOf('simpleb1') === -1).to.equal(false)
|
||||||
|
expect(og.simple.indexOf('simpleb2') === -1).to.equal(false)
|
||||||
|
expect(og.simple.indexOf('simpleb3') === -1).to.equal(false)
|
||||||
|
expect(og.nested.nested1.length).to.equal(3)
|
||||||
|
expect(og.nested.nested1.indexOf('nested1a1') === -1).to.equal(false)
|
||||||
|
expect(og.nested.nested1.indexOf('nested1a2') === -1).to.equal(false)
|
||||||
|
expect(og.nested.nested1.indexOf('nested1a3') === -1).to.equal(false)
|
||||||
|
expect(og.nested.nested2.length).to.equal(3)
|
||||||
|
expect(og.nested.nested2.indexOf('nested2b1') === -1).to.equal(false)
|
||||||
|
expect(og.nested.nested2.indexOf('nested2b2') === -1).to.equal(false)
|
||||||
|
expect(og.nested.nested2.indexOf('nested2b3') === -1).to.equal(false)
|
||||||
|
expect(og.subnested.subnested1.length).to.equal(8)
|
||||||
|
expect(og.subnested.subnested1.indexOf('subnested1a1') === -1).to.equal(false)
|
||||||
|
expect(og.subnested.subnested1.indexOf('subnested1a2') === -1).to.equal(false)
|
||||||
|
expect(og.subnested.subnested1.indexOf('subnested1a3') === -1).to.equal(false)
|
||||||
|
expect(og.subnested.subnested1.indexOf('subnested1b1') === -1).to.equal(false)
|
||||||
|
expect(og.subnested.subnested1.indexOf('subnested1b2') === -1).to.equal(false)
|
||||||
|
expect(og.subnested.subnested1.indexOf('subnested1b3') === -1).to.equal(false)
|
||||||
|
// FIXME: Some work to be done still with deep-nesting of groups with the same name
|
||||||
|
})
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue