diff --git a/package-lock.json b/package-lock.json index d719846a466..c9f5db12862 100644 --- a/package-lock.json +++ b/package-lock.json @@ -212,6 +212,217 @@ } } }, + "@freesewing/aaron": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@freesewing/aaron/-/aaron-0.4.0.tgz", + "integrity": "sha512-Y/bGqdaA6lpKlumwxOsCKCR2PZhqk9l+MDiQHS294SDq2Naqx+qHS5qg1FcJRTBK2PX20MZ6ZVu2tqGp+jO01w==", + "requires": { + "@freesewing/brian": "^0.13" + }, + "dependencies": { + "@freesewing/brian": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@freesewing/brian/-/brian-0.13.0.tgz", + "integrity": "sha512-PC9QMqjB2mERfRXqEu9TgFfSJ6xgawTlgwBQQWtZjw98wwiqdpGBjgTch8gkwHjJcn9uOuk9p8YplaOAMgFVpw==", + "requires": { + "@freesewing/plugin-bundle": "^0.3", + "freesewing": "^0.18.3" + } + } + } + }, + "@freesewing/brian": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@freesewing/brian/-/brian-0.14.0.tgz", + "integrity": "sha512-+Wt4t3EZQpSTNYfRBRDvP9fssH3gUHRlI+PFKqgY9pMSTW5r7fZ/C9pl+nFtGKtMxexywY2zTPxM2cqgcG63Qw==", + "requires": { + "@freesewing/plugin-bundle": "^0.5", + "freesewing": "^0.19" + }, + "dependencies": { + "@freesewing/plugin-bundle": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@freesewing/plugin-bundle/-/plugin-bundle-0.5.0.tgz", + "integrity": "sha512-vmjaB/2VnrubfZulAP3naIHkDIjhMSsI/fI1Ca6prP3M8UQMACz2opfgj1uqB4kZ04hrft5fKAjmHmPnYR/3yA==", + "requires": { + "@freesewing/plugin-cutonfold": "^0.10", + "@freesewing/plugin-dimension": "0.7.1", + "@freesewing/plugin-grainline": "^0.2", + "@freesewing/plugin-logo": "^0.5", + "@freesewing/plugin-scalebox": "^0.3", + "@freesewing/plugin-title": "^0.9" + } + }, + "@freesewing/plugin-cutonfold": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@freesewing/plugin-cutonfold/-/plugin-cutonfold-0.10.0.tgz", + "integrity": "sha512-s0/JAyNw0YvkEPrtarJemUJ3vGcpNatxZWnxnJPbbEyOMf3Ry8fDd/EfFe7AZU1lj0Vp7prknzFQDXN7XxsOsQ==" + }, + "@freesewing/plugin-dimension": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@freesewing/plugin-dimension/-/plugin-dimension-0.7.1.tgz", + "integrity": "sha512-O/IVkBXtvs8HOVEFS7GGAQnLlNPvuT8fGPAxEfSz1+pqwhX5oyEjBjoL1GCENPFWamizwcn2143di5OnQIR6cg==" + }, + "@freesewing/plugin-grainline": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@freesewing/plugin-grainline/-/plugin-grainline-0.2.0.tgz", + "integrity": "sha512-hU0nF3sBxG6yvMlDx2BznGTs7NSQs74fb0+2YEjYs6iJ6rpOzg82N0oP8fAiXdAewHaSykOyouapZdxgG8CXEg==" + }, + "@freesewing/plugin-logo": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@freesewing/plugin-logo/-/plugin-logo-0.5.0.tgz", + "integrity": "sha512-yv40lmFUeEziB3lRIitZAwS6cvcOioSm7C2kFW+I191pXvBK8oGRvuVhw7OUQihdYwtyhYtfHwgNAGQqImBsAg==" + }, + "@freesewing/plugin-scalebox": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@freesewing/plugin-scalebox/-/plugin-scalebox-0.3.0.tgz", + "integrity": "sha512-6djCCOsAWQUyzCffLThsENusOcr8bOyE4rYcBC7bXOvUFoucZ0CthbMncreKLWmr456uvMMLYnBOJNG4fk0+Wg==" + }, + "@freesewing/plugin-title": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@freesewing/plugin-title/-/plugin-title-0.9.0.tgz", + "integrity": "sha512-DH2qbABNZrRNBe4/DVPIJmlsRfq12+VtAfG4jlVHrPrL9ZDQ56YLdiLt9I3LuGndNDuW7/KhisHMJs5md5qu/w==" + }, + "freesewing": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/freesewing/-/freesewing-0.19.0.tgz", + "integrity": "sha512-/wSEhF/Z10Pd3IGl3Nq+v/txcOboK21VKdQ1sXuBGp17D6Kq5ah+wbDyBrQRGu0X5sbQo7DazEFZ1kgnxyk5tg==", + "requires": { + "bezier-js": "^2.2.15", + "bin-pack": "1.0.2", + "hooks-fixed": "2.0.2" + } + } + } + }, + "@freesewing/bruce": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@freesewing/bruce/-/bruce-0.3.0.tgz", + "integrity": "sha512-kvtu/Y+wxpyPz1tlOhwJBXs09vo0mz0SEIz7ZhFpmjP3AAb5tPKCpvylL2VKkfMGG89/S3YapCaGQRTNYibMQQ==", + "requires": { + "@freesewing/plugin-bundle": "^0.3", + "freesewing": "^0.17" + }, + "dependencies": { + "freesewing": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/freesewing/-/freesewing-0.17.0.tgz", + "integrity": "sha512-LanZsKfdAan5LQH7HvTlRwF6cFxr64G666OeCY9Ij7NnZ79/+AEuffT0lrLpRa1dNU3SY7BWPlnkA8SMeiB8+Q==", + "requires": { + "bezier-js": "^2.2.13", + "bin-pack": "1.0.2", + "hooks": "^0.3.2" + } + } + } + }, + "@freesewing/cathrin": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@freesewing/cathrin/-/cathrin-0.2.0.tgz", + "integrity": "sha512-HuYLpWunrLrUnBiLc3B4NY2e4EcukIjzLIkPpC2xc2w/FUdDA2Q+FM4sdZLL+VmlkAF7iZjztgI0rh18x1ONBw==", + "requires": { + "@freesewing/plugin-bundle": "^0.3", + "freesewing": "^0.17" + }, + "dependencies": { + "freesewing": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/freesewing/-/freesewing-0.17.0.tgz", + "integrity": "sha512-LanZsKfdAan5LQH7HvTlRwF6cFxr64G666OeCY9Ij7NnZ79/+AEuffT0lrLpRa1dNU3SY7BWPlnkA8SMeiB8+Q==", + "requires": { + "bezier-js": "^2.2.13", + "bin-pack": "1.0.2", + "hooks": "^0.3.2" + } + } + } + }, + "@freesewing/hugo": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@freesewing/hugo/-/hugo-0.1.0.tgz", + "integrity": "sha512-6wx3UD31WQUlH5zGk7C0sIBgJSlTxSren5+oH4ZyYidoygca60dJ/IQDZw21u5bkNkcU2QN4Qd+kNXgl31Lk6Q==", + "requires": { + "@freesewing/brian": "^0.11", + "@freesewing/plugin-bundle": "^0.3", + "freesewing": "^0.17" + }, + "dependencies": { + "@freesewing/brian": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/@freesewing/brian/-/brian-0.11.1.tgz", + "integrity": "sha512-+3xdcBEGKzlGLlmm1z+1C/x77WeByi7O1Q9hQa7Hb9O57mwKK6SmMwUcn6tBx5/fzxOlSpAUUq3WXUf5wK8yXg==", + "requires": { + "@freesewing/plugin-bundle": "^0.3", + "freesewing": "^0.17" + } + }, + "freesewing": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/freesewing/-/freesewing-0.17.0.tgz", + "integrity": "sha512-LanZsKfdAan5LQH7HvTlRwF6cFxr64G666OeCY9Ij7NnZ79/+AEuffT0lrLpRa1dNU3SY7BWPlnkA8SMeiB8+Q==", + "requires": { + "bezier-js": "^2.2.13", + "bin-pack": "1.0.2", + "hooks": "^0.3.2" + } + } + } + }, + "@freesewing/patterns": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@freesewing/patterns/-/patterns-0.3.0.tgz", + "integrity": "sha512-wZwbRKkdCApBVqevd+CHa1SNRqQ1qwAMCfFzvTRoavLOyqAdw1fJXyUS3Qlzu6+e8V+1UiaBGG26ShTFpJLm1A==", + "requires": { + "@freesewing/aaron": "^0.4", + "@freesewing/brian": "^0.14", + "@freesewing/bruce": "^0.3", + "@freesewing/cathrin": "^0.2", + "@freesewing/hugo": "^0.1" + } + }, + "@freesewing/plugin-bundle": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@freesewing/plugin-bundle/-/plugin-bundle-0.3.0.tgz", + "integrity": "sha512-FUZmGgbrqb3md872w3aXQY+3TReoTeV25ak006UfCBzEJ0lm15QrCanqC46k+0Z6Iv98ChkCo1XZl/kWV1FYFQ==", + "requires": { + "@freesewing/plugin-cutonfold": "0.9.0", + "@freesewing/plugin-dimension": "0.6.1", + "@freesewing/plugin-grainline": "0.0.3", + "@freesewing/plugin-logo": "0.3.3", + "@freesewing/plugin-scalebox": "0.2.0", + "@freesewing/plugin-title": "0.7.0" + } + }, + "@freesewing/plugin-cutonfold": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@freesewing/plugin-cutonfold/-/plugin-cutonfold-0.9.0.tgz", + "integrity": "sha512-FZC6bSaDMgXKDzIU5ynByHmiVIVDXKzB9rlxZyldv+q8c0T/xfJ/x15wcey2Bffj/pv37hzLI+CocwGLHjWH7g==" + }, + "@freesewing/plugin-dimension": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@freesewing/plugin-dimension/-/plugin-dimension-0.6.1.tgz", + "integrity": "sha512-OUdF3JyLDIwjHHRyuL0DZnfhykZzozv00AekcVOK3TZ61p+UQO4EK1FbDVczCY5SJx5DpYyuastvZ/FEW3SQMw==" + }, + "@freesewing/plugin-grainline": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@freesewing/plugin-grainline/-/plugin-grainline-0.0.3.tgz", + "integrity": "sha512-Oa+FvjsdDfWxIoXa8bATYwj1Neg6q+gNQWJyX7j1HlJnEflsQtJBB8fqwcGJzeK/QDJauvbAm3sBJP30gMwSTw==" + }, + "@freesewing/plugin-logo": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@freesewing/plugin-logo/-/plugin-logo-0.3.3.tgz", + "integrity": "sha512-t9VBoZvFx0tR83bFQMpc4iH/oJaXVr41zX0N8AogTt+FEjnHnZSmCJGTfpYkPtp1mWJSc4ibS95Gyh9c4YNgGA==" + }, + "@freesewing/plugin-scalebox": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@freesewing/plugin-scalebox/-/plugin-scalebox-0.2.0.tgz", + "integrity": "sha512-SskEtAyvYCpjmCHEgjNzuSsMqOyT/ExQVhEdfoS3vjW4I9/uAqhOcI4EYR+gP1N3Ga6yh99hf9gDtSpTJP78pg==" + }, + "@freesewing/plugin-title": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@freesewing/plugin-title/-/plugin-title-0.7.0.tgz", + "integrity": "sha512-LVnokj+SIYPdxehiqoF+RPdLCaCd/MnTBzRebjPWRxGQnywzNyuwgHN8jmJEQGb6dJ/6J4zFEvAm9pS1ID6cug==" + }, "@samverschueren/stream-to-observable": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", @@ -2498,6 +2709,16 @@ "map-cache": "^0.2.2" } }, + "freesewing": { + "version": "0.18.3", + "resolved": "https://registry.npmjs.org/freesewing/-/freesewing-0.18.3.tgz", + "integrity": "sha512-uXBnN1IRqsH6QhYoM9juNo76GbzO75rSXgWrbMFHZcqSLw4RsCxRLppl5LqOAJ1pEYAWh7W9disxS53j5Eum4Q==", + "requires": { + "bezier-js": "^2.2.15", + "bin-pack": "1.0.2", + "hooks": "^0.3.2" + } + }, "fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -2835,6 +3056,11 @@ "os-tmpdir": "^1.0.1" } }, + "hooks": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/hooks/-/hooks-0.3.2.tgz", + "integrity": "sha1-ox8GDCAmzqbPHKPrF4Qw5xjhxKM=" + }, "hooks-fixed": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hooks-fixed/-/hooks-fixed-2.0.2.tgz", diff --git a/package.json b/package.json index 4ceab4baf98..05d264fe9fb 100644 --- a/package.json +++ b/package.json @@ -27,10 +27,11 @@ "pretty": "npx prettier --write 'src/*.js'", "lint": "eslint --fix 'src/*.js'", "browserbuild": "BABEL_ENV=develop rollup --config rollup.js --file dist/browser.js --format iife --sourcemap true --name freesewing", - "nodebuild": "BABEL_ENV=production rollup --config rollup.js --file dist/index.js --format cjs --sourcemap true", + "nodebuild": "BABEL_ENV=production rollup --config rollup.js --file dist/index.js --format cjs --sourcemap true -e bezier-js,bin-pack", "modulebuild": "BABEL_ENV=develop rollup --config rollup.js --file dist/index.mjs --format esm --sourcemap true", - "testbuild": "BABEL_ENV=test rollup -c rollup.js -o tests/dist/index.js -f cjs", + "testbuild": "BABEL_ENV=test rollup -c rollup.js -o tests/dist/index.js -f cjs -e bezier-js,bin-pack", "build": "npm run clean && npm run browserbuild && npm run nodebuild && npm run modulebuild && npm run testbuild", + "rebuild": "npm run nodebuild && npm run modulebuild", "watch": "rollup -c rollup.js -o dist/index.js -f cjs -m true --watch" }, "nyc": { @@ -51,9 +52,9 @@ ] }, "dependencies": { + "@freesewing/patterns": "0.3.0", "bezier-js": "^2.2.15", - "bin-pack": "1.0.2", - "hooks-fixed": "2.0.2" + "bin-pack": "1.0.2" }, "devDependencies": { "babel-core": "^6.26.3", diff --git a/rollup.js b/rollup.js index 011f358d595..0f8458b939a 100644 --- a/rollup.js +++ b/rollup.js @@ -15,11 +15,11 @@ export default { commonjs(), babel({ exclude: "node_modules/**" - }), - terser({ - output: { - preamble: `/**\n * ${name} | v${version}\n * ${description}\n * (c) ${new Date().getFullYear()} ${author}\n * @license ${license}\n */` - } }) + //terser({ + // output: { + // preamble: `/**\n * ${name} | v${version}\n * ${description}\n * (c) ${new Date().getFullYear()} ${author}\n * @license ${license}\n */` + // } + //}) ] }; diff --git a/src/hooks.js b/src/hooks.js index 78c6abd2fb0..a325ce8762f 100644 --- a/src/hooks.js +++ b/src/hooks.js @@ -1,28 +1,10 @@ -function Hooks() { - this._hooks = {}; - this.all = [ - "preDraft", - "postDraft", - "preSample", - "postSample", - "preRender", - "postRender", - "insertText", - "debug" - ]; -} - -Hooks.prototype.list = function(hook) { - if (typeof this._hooks[hook] === "undefined") { - return false; - } - - return this._hooks[hook]; +export default { + preDraft: [], + postDraft: [], + preSample: [], + postSample: [], + preRender: [], + postRender: [], + insertText: [], + debug: [] }; - -Hooks.prototype.attach = function(hook, obj) { - if (typeof this._hooks[hook] === "undefined") return; - for (let func of this._hooks[hook]) obj.pre(hook, func); -}; - -export default Hooks; diff --git a/src/part.js b/src/part.js index 902ba5fa445..bb183622bfb 100644 --- a/src/part.js +++ b/src/part.js @@ -3,7 +3,6 @@ import Point from "./point"; import Path from "./path"; import Snippet from "./snippet"; import Attributes from "./attributes"; -import * as hooklib from "hooks-fixed"; function Part() { this.attributes = new Attributes(); @@ -17,8 +16,6 @@ function Part() { this.height = false; this.render = true; this.utils = utils; - for (let k in hooklib) this[k] = hooklib[k]; - // Keep track of attached hooks // Constructors so macros can create objects this.Point = Point; @@ -26,7 +23,8 @@ function Part() { this.Snippet = Snippet; let self = this; - this.hooks.attach("debug", self); + + this.context = this.getContext(); return this; } diff --git a/src/pattern.js b/src/pattern.js index ab0f5c9d8bb..558d68321fa 100644 --- a/src/pattern.js +++ b/src/pattern.js @@ -1,25 +1,22 @@ -import { macroName, round, sampleStyle } from "./utils"; +import { macroName, round, sampleStyle, methodHash } from "./utils"; import Part from "./part"; import Point from "./point"; import Path from "./path"; import Snippet from "./snippet"; import Svg from "./svg"; -import Hooks from "./hooks"; import pack from "bin-pack"; import Store from "./store"; -import * as hooklib from "hooks-fixed"; +import hooks from "./hooks"; export default function Pattern(config = false) { // width and height properties this.width = false; this.height = false; - // Hooks and Svg instance - for (let k in hooklib) this[k] = hooklib[k]; - this.hooks = new Hooks(); - Svg.prototype.hooks = this.hooks; + // Hooks + this.hooks = hooks; - // Data containers + // Containers this.settings = { complete: true, idPrefix: "fs-", @@ -31,12 +28,14 @@ export default function Pattern(config = false) { this.store = new Store(); this.parts = {}; - // Merge config with defaults + // Merge config with defaults (FIXME: set defaults) let defaults = { measurements: {}, options: {} }; this.config = { ...defaults, ...config }; + + // Convert options for (let i in config.options) { let option = config.options[i]; if (typeof option === "object") { @@ -53,13 +52,7 @@ export default function Pattern(config = false) { } } - // Constructors - this.Part = Part; - this.Point = Point; - this.Path = Path; - this.Snippet = Snippet; - - // Context object to inject in part prototype + // Context object to inject in part this.context = { parts: this.parts, config: this.config, @@ -67,30 +60,48 @@ export default function Pattern(config = false) { options: this.options, store: this.store }; - this.Part.prototype.context = this.context; - this.Part.prototype.macros = {}; + + // Constructors + this.Part = Part; + this.Point = Point; + this.Path = Path; + this.Snippet = Snippet; + + let self = this; + this.Part.prototype.getContext = function() { + return self.context; + }; + this.Part.prototype.hooks = this.hooks; + this.is = ""; } -/** Method to attach preDraft hooks on */ -Pattern.prototype.preDraft = function() {}; +// FIXME: Still needed? +Pattern.prototype.createPart = function() { + let part = new Part(); + part.context = this.context; -/** Method to attach postDraft hooks on */ -Pattern.prototype.postDraft = function() {}; + return part; +}; -/** Method to attach preSample hooks on */ -Pattern.prototype.preSample = function() {}; - -/** Method to attach postSample hooks on */ -Pattern.prototype.postSample = function() {}; +Pattern.prototype.runHooks = function(hookName, data = false) { + if (data === false) data = this; + let hooks = this.hooks[hookName]; + if (hooks.length > 0) { + for (let hook of hooks) { + hook.method(data, hook.data); + } + } +}; /** * Calls _draft in the method, and pre- and postDraft */ Pattern.prototype.draft = function() { - this.preDraft(); + this.is = "draft"; + this.runHooks("preDraft"); this._draft(); - this.postDraft(); + this.runHooks("postDraft"); return this; }; @@ -173,7 +184,8 @@ Pattern.prototype.sampleRun = function( * Handles option sampling */ Pattern.prototype.sampleOption = function(optionName) { - this.preSample(); + this.is = "sample"; + this.runHooks("preSample"); let step, val; let factor = 1; let anchors = {}; @@ -201,7 +213,7 @@ Pattern.prototype.sampleOption = function(optionName) { val += step; } this.parts = parts; - this.postSample(); + this.runHooks("postSample"); return this; }; @@ -231,7 +243,8 @@ Pattern.prototype.sampleListOption = function(optionName) { * Handles measurement sampling */ Pattern.prototype.sampleMeasurement = function(measurementName) { - this.preSample(); + this.is = "sample"; + this.runHooks("preSample"); let anchors = {}; let parts = this.sampleParts(); let val = this.settings.measurements[measurementName]; @@ -249,7 +262,7 @@ Pattern.prototype.sampleMeasurement = function(measurementName) { val += step; } this.parts = parts; - this.postSample(); + this.runHooks("postSample"); return this; }; @@ -258,7 +271,8 @@ Pattern.prototype.sampleMeasurement = function(measurementName) { * Handles models sampling */ Pattern.prototype.sampleModels = function(models, focus = false) { - this.preSample(); + this.is = "sample"; + this.runHooks("preSample"); let anchors = {}; let parts = this.sampleParts(); let run = 0; @@ -271,59 +285,46 @@ Pattern.prototype.sampleModels = function(models, focus = false) { this.sampleRun(parts, anchors, run, runs, className); } this.parts = parts; - this.postSample(); + this.runHooks("postSample"); return this; }; /** Debug method, exposes debug hook */ -Pattern.prototype.debug = function(data) {}; +Pattern.prototype.debug = function(...data) { + this.runHooks("debug", data); +}; Pattern.prototype.render = function() { this.svg = new Svg(this); + this.svg.hooks = this.hooks; return this.pack().svg.render(this); }; -Pattern.prototype.on = function(hook, method) { - if (typeof this.hooks._hooks[hook] === "undefined") { - this.hooks._hooks[hook] = []; - } - this.hooks._hooks[hook].push(method); - - // Pattern object hooks need to be attached on load - let localHooks = [ - "preDraft", - "postDraft", - "preSample", - "postSample", - "debug" - ]; - if (localHooks.includes(hook)) { - let self = this; - this.hooks.attach(hook, self); - } +Pattern.prototype.on = function(hook, method, data) { + this.hooks[hook].push({ method, data }); }; -Pattern.prototype.with = function(plugin) { +Pattern.prototype.with = function(plugin, data = false) { this.debug( "success", "🔌 Plugin loaded", `${plugin.name} v${plugin.version}` ); - if (plugin.hooks) this.loadPluginHooks(plugin); + if (plugin.hooks) this.loadPluginHooks(plugin, data); if (plugin.macros) this.loadPluginMacros(plugin); return this; }; -Pattern.prototype.loadPluginHooks = function(plugin) { - for (let hook of this.hooks.all) { +Pattern.prototype.loadPluginHooks = function(plugin, data) { + for (let hook of Object.keys(this.hooks)) { if (typeof plugin.hooks[hook] === "function") { - this.on(hook, plugin.hooks[hook]); + this.on(hook, plugin.hooks[hook], data); } else if (typeof plugin.hooks[hook] === "object") { for (let method of plugin.hooks[hook]) { - this.on(hook, method); + this.on(hook, method, data); } } } diff --git a/src/svg.js b/src/svg.js index ff9e39b3ad5..ba3412a6c5d 100644 --- a/src/svg.js +++ b/src/svg.js @@ -1,5 +1,4 @@ import Attributes from "./attributes"; -import * as hooklib from "hooks-fixed"; import { version } from "../package.json"; @@ -24,21 +23,17 @@ function Svg(pattern) { "http://freesewing.org/namespaces/freesewing" ); this.attributes.add("freesewing", version); - for (let k in hooklib) this[k] = hooklib[k]; - - //this.hooks was injected into the prototype by pattern - let self = this; - this.hooks.attach("preRender", self); - this.hooks.attach("postRender", self); - this.hooks.attach("insertText", self); - this.hooks.attach("debug", self); } -/** Method to attach preRender hooks on */ -Svg.prototype.preRender = function() {}; - -/** Method to attach postRender hooks on */ -Svg.prototype.postRender = function() {}; +Svg.prototype.runHooks = function(hookName, data = false) { + if (data === false) data = this; + let hooks = this.hooks[hookName]; + if (hooks.length > 0) { + for (let hook of hooks) { + hook.method(data, hook.data); + } + } +}; /** Method to attach insertText hooks on */ Svg.prototype.insertText = function() {}; @@ -49,7 +44,8 @@ Svg.prototype.debug = function() {}; /** Renders a draft object as SVG */ Svg.prototype.render = function(pattern) { this.idPrefix = pattern.settings.idPrefix; - this.preRender(); + this.runHooks("preRender"); + //this.preRender(); if (!pattern.settings.embed) { this.attributes.add("width", pattern.width + "mm"); this.attributes.add("height", pattern.height + "mm"); @@ -76,7 +72,8 @@ Svg.prototype.render = function(pattern) { this.svg += this.closeGroup(); this.svg += this.nl() + ""; this.svg += this.renderComments(this.footer); - this.postRender(); + this.runHooks("postRender"); + //this.postRender(); return this.svg; }; diff --git a/src/utils.js b/src/utils.js index bbb758f0a3c..fb34d400db7 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,5 +1,14 @@ import Point from "./point"; import Bezier from "bezier-js"; +import crypto from "crypto"; + +/** Generates a hash, do not use this for security */ +export function methodHash(method) { + return crypto + .createHash("sha1") + .update(method.toSource()) + .digest("base64"); +} /** Returns internal hook name for a macro */ export function macroName(name) { diff --git a/tests/attributes.test.js b/tests/attributes.test.js index 3b88e01d2a8..49de8f264e6 100644 --- a/tests/attributes.test.js +++ b/tests/attributes.test.js @@ -38,3 +38,10 @@ it("Should return attributes as array", () => { ); expect(a.getAsArray("nope")).to.equal(false); }); + +it("Should render attributes as CSS", () => { + let a = newAttr() + .set("line-height", 1.2) + .add("border", "1px solid red"); + expect(a.renderAsCss()).to.equal(" line-height:1.2; border:1px solid red;"); +}); diff --git a/tests/hooks.test.js b/tests/hooks.test.js index 5011a7107ab..e65ea326031 100644 --- a/tests/hooks.test.js +++ b/tests/hooks.test.js @@ -1,114 +1,18 @@ let expect = require("chai").expect; let freesewing = require("./dist/index.js"); -let pattern = new freesewing.Pattern(); -let h = pattern.hooks; - it("Should contain all hooks", () => { - let test = [ - "preDraft", - "postDraft", - "preSample", - "postSample", - "preRender", - "postRender", - "insertText", - "debug" - ]; - expect(h.all).to.eql(test); -}); - -it("Should contain no hooks upon creation", () => { - let test = {}; - expect(h._hooks).to.eql(test); -}); - -it("Should return hooks correctly", () => { - h._hooks = { - hookA: "testA", - hookB: "testB" + let pattern = new freesewing.Pattern(); + let h = pattern.hooks; + let test = { + preDraft: [], + postDraft: [], + preSample: [], + postSample: [], + preRender: [], + postRender: [], + insertText: [], + debug: [] }; - expect(h.list("hookA")).to.equal("testA"); - expect(h.list("hookB")).to.equal("testB"); - expect(h.list("hookC")).to.equal(false); -}); - -it("Should not attach a non-existing hook", () => { - let obj = {}; - expect(h.attach("no-such-hook", obj)).to.equal(undefined); -}); - -let count = 0; -let pre = function() { - count += 5; -}; - -it("Should attach the preDraft & postDraft hooks", () => { - count = 0; - let obj = { - draft: function() {}, - pre: pre - }; - h._hooks = { - preDraft: [ - function(next) { - next(); - } - ], - postDraft: [ - function(next) { - next(); - } - ] - }; - expect(h.attach("preDraft", obj)).to.equal(undefined); - obj.draft(); - expect(count).to.equal(5); - expect(h.attach("postDraft", obj)).to.equal(undefined); - obj.draft(); - expect(count).to.equal(10); -}); - -it("Should attach the preSample & postSample hooks", () => { - count = 0; - let obj = { - sampleOption: function() {}, - pre: pre - }; - h._hooks = { - preSample: [ - function(next) { - next(); - } - ], - postSample: [ - function(next) { - next(); - } - ] - }; - expect(h.attach("preSample", obj)).to.equal(undefined); - obj.sampleOption(); - expect(count).to.equal(5); - expect(h.attach("postSample", obj)).to.equal(undefined); - obj.sampleOption(); - expect(count).to.equal(10); -}); - -it("Should attach the debug hook", () => { - count = 0; - let obj = { - debug: function() {}, - pre: pre - }; - h._hooks = { - debug: [ - function(next) { - next(); - } - ] - }; - expect(h.attach("debug", obj)).to.equal(undefined); - obj.debug(); - expect(count).to.equal(5); + expect(h).to.eql(test); }); diff --git a/tests/pattern.test.js b/tests/pattern.test.js index 1f4b7ab5a5e..4713c1edba2 100644 --- a/tests/pattern.test.js +++ b/tests/pattern.test.js @@ -153,6 +153,7 @@ it("Should sample models with focus", () => { let a = pattern.parts.a; a.points.from = new a.Point(0, 0); a.points.to = new a.Point(10, a.context.config.measurements.headToToe); + a.points.anchor = new a.Point(20, 30); a.paths.test = new a.Path().move(a.points.from).line(a.points.to); pattern.parts.b.copy(a); }; @@ -179,9 +180,8 @@ it("Should register a hook via on", () => { let pattern = new freesewing.Pattern(); let count = 0; pattern._draft = () => {}; - pattern.on("preDraft", function(next) { + pattern.on("preDraft", function(pattern) { count++; - next(); }); pattern.draft(); expect(count).to.equal(1); @@ -195,9 +195,8 @@ it("Should register a hook from a plugin", () => { name: "test", version: "0.1-test", hooks: { - preDraft: function(next) { + preDraft: function(pattern) { count++; - next(); } } }; @@ -235,3 +234,9 @@ it("Should check whether a parts is strictly needed", () => { expect(pattern.needs("foo")).to.equal(true); expect(pattern.needs("foo", true)).to.equal(true); }); + +it("Should check whether created parts get the pattern context", () => { + let pattern = new freesewing.Pattern(); + let part = pattern.createPart(); + expect(part.context).to.equal(pattern.context); +});