From 8a74a366977e257bff7b8cda4b2f5ea0d2ef30dc Mon Sep 17 00:00:00 2001 From: Joost De Cock Date: Wed, 31 Aug 2022 17:52:39 +0200 Subject: [PATCH] feat(core): Move plugins to part-level config --- packages/core/src/design.mjs | 17 +-- packages/core/src/pattern.mjs | 11 ++ packages/core/src/utils.mjs | 13 ++ packages/core/tests/design.test.mjs | 93 -------------- packages/core/tests/pattern.test.mjs | 186 ++++++++++++++------------- 5 files changed, 124 insertions(+), 196 deletions(-) diff --git a/packages/core/src/design.mjs b/packages/core/src/design.mjs index ec059016df5..cc5a4b7e10f 100644 --- a/packages/core/src/design.mjs +++ b/packages/core/src/design.mjs @@ -8,12 +8,12 @@ import { addPartConfig } from './utils.mjs' */ export function Design(config) { - // Merge config with defaults + // Initialize config with defaults config = { - parts: [], - options: {}, measurements: [], optionalMeasurements: [], + options: {}, + parts: [], plugins: [], ...config } @@ -37,16 +37,7 @@ export function Design(config) { const pattern = function (settings) { Pattern.call(this, config) - // Load plugins - if (!Array.isArray(config.plugins)) config.plugins = [ config.plugins ] - for (const plugin of config.plugins) { - if (plugin.plugin && plugin.condition) this.useIf(plugin, settings) - else this.use(plugin) - } - - this.apply(settings) - - return this + return this.init().apply(settings) } // Set up inheritance diff --git a/packages/core/src/pattern.mjs b/packages/core/src/pattern.mjs index 8639acf969e..e7e3eebba06 100644 --- a/packages/core/src/pattern.mjs +++ b/packages/core/src/pattern.mjs @@ -173,6 +173,10 @@ Pattern.prototype.getPartList = function () { */ Pattern.prototype.init = function () { this.initialized++ + // Load plugins + if (this.config.plugins) { + for (const plugin of Object.values(this.config.plugins)) this.use(plugin) + } // Resolve all dependencies this.dependencies = this.config.dependencies this.inject = this.config.inject @@ -522,12 +526,19 @@ Pattern.prototype.render = function () { } Pattern.prototype.on = function (hook, method, data) { + for (const added of this.hooks[hook]) { + // Don't add it twice + if (added.method === method) return this + } this.hooks[hook].push({ method, data }) return this } Pattern.prototype.use = function (plugin, data) { + // Conditional plugin? + if (plugin.plugin && plugin.condition) return this.useIf(plugin, data) + // Regular plugin this.raise.info(`Loaded plugin \`${plugin.name}:${plugin.version}\``) if (plugin.hooks) this.loadPluginHooks(plugin, data) if (plugin.macros) this.loadPluginMacros(plugin) diff --git a/packages/core/src/utils.mjs b/packages/core/src/utils.mjs index 067f736c887..a43801672e0 100644 --- a/packages/core/src/utils.mjs +++ b/packages/core/src/utils.mjs @@ -567,12 +567,25 @@ export const addPartDependencies = (part, config) => { return config } +// Add part-level plugins +export const addPartPlugins = (part, config) => { + if (!part.plugins) return config + if (!Array.isArray(part.plugins)) part.plugins = [ part.plugins ] + for (const plugin of part.plugins) { + if (plugin.plugin && plugin.condition) config.plugins[plugin.plugin.name] = plugin + else config.plugins[plugin.name] = plugin + } + + return config +} + export const addPartConfig = (part, config) => { config = addPartOptions(part, config) config = addPartMeasurements(part, config) config = addPartOptionalMeasurements(part, config) config = addPartDependencies(part, config) config = addPartOptionGroups(part, config) + config = addPartPlugins(part, config) return config } diff --git a/packages/core/tests/design.test.mjs b/packages/core/tests/design.test.mjs index 7501fe6f0f1..71ca9caf3f5 100644 --- a/packages/core/tests/design.test.mjs +++ b/packages/core/tests/design.test.mjs @@ -24,99 +24,6 @@ describe('Design', () => { expect(pattern.settings.options.percentage).to.equal(0.3); }); - it("Design constructor should load single plugin", () => { - let plugin = { - name: "example", - version: 1, - hooks: { - preRender: function(svg, attributes) { - svg.attributes.add("freesewing:plugin-example", version); - } - } - }; - - let design = new Design({plugins: plugin}); - let pattern = new design(); - expect(pattern.hooks.preRender.length).to.equal(1); - }); - - it("Design constructor should load array of plugins", () => { - let plugin1 = { - name: "example1", - version: 1, - hooks: { - preRender: function(svg, attributes) { - svg.attributes.add("freesewing:plugin-example1", version); - } - } - }; - let plugin2 = { - name: "example2", - version: 2, - hooks: { - preRender: function(svg, attributes) { - svg.attributes.add("freesewing:plugin-example2", version); - } - } - }; - - let design = new Design( { plugins: [plugin1, plugin2] }); - let pattern = new design(); - expect(pattern.hooks.preRender.length).to.equal(2); - }); - - it("Design constructor should load conditional plugin", () => { - const plugin = { - name: "example", - version: 1, - hooks: { - preRender: function(svg, attributes) { - svg.attributes.add("freesewing:plugin-example", version); - } - } - }; - const condition = () => true - const design = new Design({ plugins: { plugin, condition } }); - const pattern = new design(); - expect(pattern.hooks.preRender.length).to.equal(1); - }); - - it("Design constructor should not load conditional plugin", () => { - const plugin = { - name: "example", - version: 1, - hooks: { - preRender: function(svg, attributes) { - svg.attributes.add("freesewing:plugin-example", version); - } - } - }; - const condition = () => false - const design = new Design({ plugins: { plugin, condition } }); - const pattern = new design(); - expect(pattern.hooks.preRender.length).to.equal(0); - }); - - it("Design constructor should load multiple conditional plugins", () => { - const plugin = { - name: "example", - version: 1, - hooks: { - preRender: function(svg, attributes) { - svg.attributes.add("freesewing:plugin-example", version); - } - } - }; - const condition1 = () => true - const condition2 = () => false - const design = new Design({ plugins: [ - { plugin, condition: condition1 }, - { plugin, condition: condition2 }, - ]}); - const pattern = new design(); - expect(pattern.hooks.preRender.length).to.equal(1); - }); - /* it("Design constructor should not require depencies for injected parts", () => { let design = new freesewing.Design({ diff --git a/packages/core/tests/pattern.test.mjs b/packages/core/tests/pattern.test.mjs index ce6224bcf8b..4edb1822a6b 100644 --- a/packages/core/tests/pattern.test.mjs +++ b/packages/core/tests/pattern.test.mjs @@ -1059,98 +1059,104 @@ describe('Pattern', () => { 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) }) - 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' ], - } - ] - } - ] + + it("Pattern should load single plugin", () => { + const plugin = { + name: "example", + version: 1, + hooks: { + preRender: function(svg, attributes) { + svg.attributes.add("freesewing:plugin-example", version); } - }, - draft: part => part, + } + }; + + const part = { + name: 'test.part', + plugins: plugin, + 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' ], - } - ] - } - ] + const design = new Design({ parts: [ part ] }) + const pattern = new design(); + pattern.init() + console.log(pattern) + expect(pattern.hooks.preRender.length).to.equal(1); + }); +/* + it("Design constructor should load array of plugins", () => { + let plugin1 = { + name: "example1", + version: 1, + hooks: { + preRender: function(svg, attributes) { + svg.attributes.add("freesewing:plugin-example1", version); } - }, - draft: part => part, - } - let design, pattern - try { - design = new 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 - }) + } + }; + let plugin2 = { + name: "example2", + version: 2, + hooks: { + preRender: function(svg, attributes) { + svg.attributes.add("freesewing:plugin-example2", version); + } + } + }; + + let design = new Design( { plugins: [plugin1, plugin2] }); + let pattern = new design(); + expect(pattern.hooks.preRender.length).to.equal(2); + }); + it("Design constructor should load conditional plugin", () => { + const plugin = { + name: "example", + version: 1, + hooks: { + preRender: function(svg, attributes) { + svg.attributes.add("freesewing:plugin-example", version); + } + } + }; + const condition = () => true + const design = new Design({ plugins: { plugin, condition } }); + const pattern = new design(); + expect(pattern.hooks.preRender.length).to.equal(1); + }); + + it("Design constructor should not load conditional plugin", () => { + const plugin = { + name: "example", + version: 1, + hooks: { + preRender: function(svg, attributes) { + svg.attributes.add("freesewing:plugin-example", version); + } + } + }; + const condition = () => false + const design = new Design({ plugins: { plugin, condition } }); + const pattern = new design(); + expect(pattern.hooks.preRender.length).to.equal(0); + }); + + it("Design constructor should load multiple conditional plugins", () => { + const plugin = { + name: "example", + version: 1, + hooks: { + preRender: function(svg, attributes) { + svg.attributes.add("freesewing:plugin-example", version); + } + } + }; + const condition1 = () => true + const condition2 = () => false + const design = new Design({ plugins: [ + { plugin, condition: condition1 }, + { plugin, condition: condition2 }, + ]}); + const pattern = new design(); + expect(pattern.hooks.preRender.length).to.equal(1); +*/ })