From 94d8ae4cabbabaf7dc44a4437e7358ae64ea8cf2 Mon Sep 17 00:00:00 2001 From: joostdecock Date: Sat, 11 Mar 2023 19:01:40 +0100 Subject: [PATCH] chore(plugin-annotations): Refactor plugin structure --- plugins/plugin-annotations/src/bartack.mjs | 50 +- plugins/plugin-annotations/src/buttons.mjs | 17 +- plugins/plugin-annotations/src/crossbox.mjs | 107 ++-- plugins/plugin-annotations/src/cutonfold.mjs | 106 ++-- plugins/plugin-annotations/src/grainline.mjs | 77 ++- plugins/plugin-annotations/src/index.mjs | 84 ++- plugins/plugin-annotations/src/logo.mjs | 24 +- plugins/plugin-annotations/src/notches.mjs | 17 +- plugins/plugin-annotations/src/pleat.mjs | 127 ++-- plugins/plugin-annotations/src/scalebox.mjs | 557 +++++++++--------- .../plugin-annotations/src/sewtogether.mjs | 151 +++-- 11 files changed, 611 insertions(+), 706 deletions(-) diff --git a/plugins/plugin-annotations/src/bartack.mjs b/plugins/plugin-annotations/src/bartack.mjs index c840a76432f..08348779166 100644 --- a/plugins/plugin-annotations/src/bartack.mjs +++ b/plugins/plugin-annotations/src/bartack.mjs @@ -1,5 +1,3 @@ -import { version, name } from '../data.mjs' - // Method that draws the actual bartack const drawBartack = (pointList, { Path }) => { let path = new Path().move(pointList.path1[0]) @@ -102,33 +100,25 @@ function createBartack(so, props) { return true } -// The actual plugin -export const bartack = { - name, - version, - macros: { - bartack: function (so, props) { - return createBartack(so, props) - }, - bartackAlong: function (so, props) { - so.bartackFractionAlong = false - so.bartackAlong = true - so.anchor = false - so.from = false - so.to = false - return createBartack(so, props) - }, - bartackFractionAlong: function (so, props) { - so.bartackFractionAlong = true - so.bartackAlong = false - so.anchor = false - so.from = false - so.to = false - return createBartack(so, props) - }, +// Export macros +export const bartackMacros = { + bartack: function (so, props) { + return createBartack(so, props) + }, + bartackAlong: function (so, props) { + so.bartackFractionAlong = false + so.bartackAlong = true + so.anchor = false + so.from = false + so.to = false + return createBartack(so, props) + }, + bartackFractionAlong: function (so, props) { + so.bartackFractionAlong = true + so.bartackAlong = false + so.anchor = false + so.from = false + so.to = false + return createBartack(so, props) }, } - -// More specifically named exports -export const bartackPlugin = bartack -export const pluginBartack = bartack diff --git a/plugins/plugin-annotations/src/buttons.mjs b/plugins/plugin-annotations/src/buttons.mjs index 0186db0bf64..e49f78c36c4 100644 --- a/plugins/plugin-annotations/src/buttons.mjs +++ b/plugins/plugin-annotations/src/buttons.mjs @@ -1,5 +1,3 @@ -import { name, version } from '../data.mjs' - const defs = [ // button ` @@ -65,18 +63,13 @@ const defs = [ `, ] -export const buttons = { - name, - version, - hooks: { - preRender: function (svg) { +// Export hooks +export const buttonsHooks = { + preRender: [ + function (svg) { for (const def of defs) { if (svg.defs.indexOf(def) === -1) svg.defs += def } }, - }, + ], } - -// More specifically named exports -export const buttonsPlugin = buttons -export const pluginButtons = buttons diff --git a/plugins/plugin-annotations/src/crossbox.mjs b/plugins/plugin-annotations/src/crossbox.mjs index 65335bbeb01..1a99225e331 100644 --- a/plugins/plugin-annotations/src/crossbox.mjs +++ b/plugins/plugin-annotations/src/crossbox.mjs @@ -1,62 +1,53 @@ -import { name, version } from '../data.mjs' +// Export macros +export const crossboxMacros = { + crossbox: function (so, { points, Point, paths, Path, getId }) { + let id = getId() + let shiftFraction = 0.1 + 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) -export const crossbox = { - name: 'crossbox', - version, - macros: { - crossbox: function (so, { points, Point, paths, Path, getId }) { - let id = getId() - let shiftFraction = 0.1 - 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) + points[id + '_topCrossTL'] = points[id + '_boxTopLeft'].shiftFractionTowards( + points[id + '_boxBottomRight'], + shiftFraction + ) + points[id + '_topCrossTR'] = points[id + '_boxTopRight'].shiftFractionTowards( + points[id + '_boxBottomLeft'], + shiftFraction + ) + points[id + '_topCrossBL'] = points[id + '_boxBottomLeft'].shiftFractionTowards( + points[id + '_boxTopRight'], + shiftFraction + ) + points[id + '_topCrossBR'] = points[id + '_boxBottomRight'].shiftFractionTowards( + points[id + '_boxTopLeft'], + shiftFraction + ) - points[id + '_topCrossTL'] = points[id + '_boxTopLeft'].shiftFractionTowards( - points[id + '_boxBottomRight'], - shiftFraction - ) - points[id + '_topCrossTR'] = points[id + '_boxTopRight'].shiftFractionTowards( - points[id + '_boxBottomLeft'], - shiftFraction - ) - points[id + '_topCrossBL'] = points[id + '_boxBottomLeft'].shiftFractionTowards( - points[id + '_boxTopRight'], - shiftFraction - ) - points[id + '_topCrossBR'] = points[id + '_boxBottomRight'].shiftFractionTowards( - points[id + '_boxTopLeft'], - shiftFraction - ) - - 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') - 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') { - points.textAnchor = points[id + '_boxTopLeft'] - .shiftFractionTowards(points[id + '_boxBottomRight'], 0.5) - .attr('data-text', so.text) - .attr('data-text-class', 'center') - } - }, + 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') + 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') { + points.textAnchor = points[id + '_boxTopLeft'] + .shiftFractionTowards(points[id + '_boxBottomRight'], 0.5) + .attr('data-text', so.text) + .attr('data-text-class', 'center') + } }, } - -// More specifically named exports -export const crossboxPlugin = crossbox -export const pluginCrossbox = crossbox diff --git a/plugins/plugin-annotations/src/cutonfold.mjs b/plugins/plugin-annotations/src/cutonfold.mjs index 0995f696b88..e98ae2dd818 100644 --- a/plugins/plugin-annotations/src/cutonfold.mjs +++ b/plugins/plugin-annotations/src/cutonfold.mjs @@ -1,5 +1,3 @@ -import { name, version } from '../data.mjs' - const markers = ` @@ -9,63 +7,59 @@ const markers = ` ` -export const cutonfold = { - name, - version, - hooks: { - preRender: (svg) => { +// Export hooks +export const cutonfoldHooks = { + preRender: [ + function (svg) { if (svg.defs.indexOf(markers) === -1) svg.defs += markers }, - }, - macros: { - cutonfold: function (so, { points, paths, Path, complete, setCutOnFold, setGrain, 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 - } - return true - } - so = { - offset: 15, - margin: 5, - prefix: 'cutonfold', - ...so, - } + ], +} +// Export macros +export const cutonfoldMacros = { + cutonfold: function (so, { points, paths, Path, complete, setCutOnFold, setGrain, 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(so.from, so.to) - if (so.grainline) setGrain(so.from.angle(so.to)) + setCutOnFold(false) // Restore default } - 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) - points[so.prefix + 'Via1'] = points[so.prefix + 'From'] - .shiftTowards(so.from, so.offset * scale) - .rotate(-90, points[so.prefix + 'From']) - points[so.prefix + 'Via2'] = points[so.prefix + 'To'] - .shiftTowards(so.to, so.offset * scale) - .rotate(90, points[so.prefix + 'To']) - const text = so.grainline ? 'cutOnFoldAndGrainline' : 'cutOnFold' - paths[so.prefix + 'Cutonfold'] = new Path() - .move(points[so.prefix + 'From']) - .line(points[so.prefix + 'Via1']) - .line(points[so.prefix + 'Via2']) - .line(points[so.prefix + 'To']) - .attr('class', 'note') - .attr('marker-start', 'url(#cutonfoldFrom)') - .attr('marker-end', 'url(#cutonfoldTo)') - .attr('data-text', text) - .attr('data-text-class', 'center fill-note') - } - }, + return true + } + so = { + offset: 15, + margin: 5, + prefix: 'cutonfold', + ...so, + } + if (typeof setCutOnFold === 'function') { + setCutOnFold(so.from, so.to) + if (so.grainline) 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) + points[so.prefix + 'Via1'] = points[so.prefix + 'From'] + .shiftTowards(so.from, so.offset * scale) + .rotate(-90, points[so.prefix + 'From']) + points[so.prefix + 'Via2'] = points[so.prefix + 'To'] + .shiftTowards(so.to, so.offset * scale) + .rotate(90, points[so.prefix + 'To']) + const text = so.grainline ? 'cutOnFoldAndGrainline' : 'cutOnFold' + paths[so.prefix + 'Cutonfold'] = new Path() + .move(points[so.prefix + 'From']) + .line(points[so.prefix + 'Via1']) + .line(points[so.prefix + 'Via2']) + .line(points[so.prefix + 'To']) + .attr('class', 'note') + .attr('marker-start', 'url(#cutonfoldFrom)') + .attr('marker-end', 'url(#cutonfoldTo)') + .attr('data-text', text) + .attr('data-text-class', 'center fill-note') + } }, } - -// More specifically named exports -export const cutonfoldPlugin = cutonfold -export const pluginCutonfold = cutonfold diff --git a/plugins/plugin-annotations/src/grainline.mjs b/plugins/plugin-annotations/src/grainline.mjs index 3a6cc93e1e3..a2203925ae9 100644 --- a/plugins/plugin-annotations/src/grainline.mjs +++ b/plugins/plugin-annotations/src/grainline.mjs @@ -1,5 +1,3 @@ -import { name, version } from '../data.mjs' - const markers = ` @@ -10,47 +8,42 @@ const markers = ` const dflts = { text: 'grainline' } -export const grainline = { - name, - version, - hooks: { - preRender: (svg) => { +// Export hooks and macros +export const grainlineHooks = { + preRender: [ + function (svg) { if (svg.defs.indexOf(markers) === -1) svg.defs += markers }, - }, - macros: { - grainline: function (so = {}, { points, paths, Path, complete, setGrain }) { - if (so === false) { - delete points.grainlineFrom - delete points.grainlineTo - delete paths.grainline - setGrain(90) // Restoring default - return true - } - so = { - ...dflts, - ...so, - } - // setGrain relies on plugin-cutlist - if (typeof setGrain === 'function') { - 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) - paths.grainline = new Path() - .move(points.grainlineFrom) - .line(points.grainlineTo) - .attr('class', 'note') - .attr('marker-start', 'url(#grainlineFrom)') - .attr('marker-end', 'url(#grainlineTo)') - .attr('data-text', so.text) - .attr('data-text-class', 'center fill-note') - } - }, + ], +} +export const grainlineMacros = { + grainline: function (so = {}, { points, paths, Path, complete, setGrain }) { + if (so === false) { + delete points.grainlineFrom + delete points.grainlineTo + delete paths.grainline + setGrain(90) // Restoring default + return true + } + so = { + ...dflts, + ...so, + } + // setGrain relies on plugin-cutlist + if (typeof setGrain === 'function') { + 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) + paths.grainline = new Path() + .move(points.grainlineFrom) + .line(points.grainlineTo) + .attr('class', 'note') + .attr('marker-start', 'url(#grainlineFrom)') + .attr('marker-end', 'url(#grainlineTo)') + .attr('data-text', so.text) + .attr('data-text-class', 'center fill-note') + } }, } - -// More specifically named exports -export const grainlinePlugin = grainline -export const pluginGrainline = grainline diff --git a/plugins/plugin-annotations/src/index.mjs b/plugins/plugin-annotations/src/index.mjs index 23f631c40d3..a6a005e54bb 100644 --- a/plugins/plugin-annotations/src/index.mjs +++ b/plugins/plugin-annotations/src/index.mjs @@ -1,59 +1,41 @@ import { name, version } from '../data.mjs' - -import { bartackPlugin } from './bartack.mjs' -import { buttonsPlugin } from './buttons.mjs' -import { crossboxPlugin } from './crossbox.mjs' -import { cutonfoldPlugin } from './cutonfold.mjs' -import { grainlinePlugin } from './grainline.mjs' -import { logoPlugin } from './logo.mjs' -import { notchesPlugin } from './notches.mjs' -import { pleatPlugin } from './pleat.mjs' -import { scaleboxPlugin } from './scalebox.mjs' -import { sewtogetherPlugin } from './sewtogether.mjs' - -const annotationPlugins = [ - bartackPlugin, - buttonsPlugin, - crossboxPlugin, - cutonfoldPlugin, - grainlinePlugin, - logoPlugin, - notchesPlugin, - pleatPlugin, - scaleboxPlugin, - sewtogetherPlugin, -] - -function annotationHooks() { - const hooks = {} - for (const plugin of annotationPlugins) { - for (const i in plugin.hooks) { - if (typeof hooks[i] === 'undefined') hooks[i] = [] - const hook = plugin.hooks[i] - if (typeof hook === 'function') hooks[i].push(hook) - else if (typeof hook === 'object') { - for (let method of hook) hooks[i].push(method) - } - } - } - - return hooks -} - -function annotationMacros() { - const macros = {} - for (const plugin of annotationPlugins) { - for (const i in plugin.macros) macros[i] = plugin.macros[i] - } - - return macros -} +// Hooks only +import { buttonsHooks } from './buttons.mjs' +import { logoHooks } from './logo.mjs' +import { notchesHooks } from './notches.mjs' +// Macros only +import { bartackMacros } from './bartack.mjs' +import { crossboxMacros } from './crossbox.mjs' +import { scaleboxMacros } from './scalebox.mjs' +// Hooks and Macros +import { cutonfoldMacros, cutonfoldHooks } from './cutonfold.mjs' +import { grainlineMacros, grainlineHooks } from './grainline.mjs' +import { pleatMacros, pleatHooks } from './pleat.mjs' +import { sewtogetherMacros, sewtogetherHooks } from './sewtogether.mjs' export const plugin = { name, version, - hooks: annotationHooks(), - macros: annotationMacros(), + hooks: { + preRender: [ + ...buttonsHooks.preRender, + ...logoHooks.preRender, + ...notchesHooks.preRender, + ...cutonfoldHooks.preRender, + ...grainlineHooks.preRender, + ...pleatHooks.preRender, + ...sewtogetherHooks.preRender, + ], + }, + macros: { + ...bartackMacros, + ...crossboxMacros, + ...scaleboxMacros, + ...cutonfoldMacros, + ...grainlineMacros, + ...pleatMacros, + ...sewtogetherMacros, + }, } export const annotationPlugin = plugin diff --git a/plugins/plugin-annotations/src/logo.mjs b/plugins/plugin-annotations/src/logo.mjs index cb88c41f749..3de4defa5ff 100644 --- a/plugins/plugin-annotations/src/logo.mjs +++ b/plugins/plugin-annotations/src/logo.mjs @@ -1,19 +1,13 @@ -import { name, version } from '../data.mjs' - -const logoFunction = (scale) => +const logo = (scale) => `` -export const logo = { - name, - version, - hooks: { - preRender: (svg) => { - if (svg.defs.indexOf('id="logo"') === -1) - svg.defs += logoFunction(svg.pattern.settings[0].scale) +// Export hooks +export const logoHooks = { + preRender: [ + function (svg) { + if (svg.defs.indexOf('id="logo"') === -1) { + svg.defs += logo(svg.pattern.settings[0].scale) + } }, - }, + ], } - -// More specifically named exports -export const logoPlugin = logo -export const pluginLogo = logo diff --git a/plugins/plugin-annotations/src/notches.mjs b/plugins/plugin-annotations/src/notches.mjs index 375cebea0bb..77764b38aa8 100644 --- a/plugins/plugin-annotations/src/notches.mjs +++ b/plugins/plugin-annotations/src/notches.mjs @@ -1,5 +1,3 @@ -import { name, version } from '../data.mjs' - const markers = ` @@ -10,16 +8,11 @@ const markers = ` ` -export const notches = { - name, - version, - hooks: { - preRender: function (svg) { +// Export hooks +export const notchesHooks = { + preRender: [ + function (svg) { if (svg.defs.indexOf(`id="notch"`) === -1) svg.defs += markers }, - }, + ], } - -// More specifically named exports -export const notchesPlugin = notches -export const pluginNotches = notches diff --git a/plugins/plugin-annotations/src/pleat.mjs b/plugins/plugin-annotations/src/pleat.mjs index e8ca2be9bc5..0e37b1d85c0 100644 --- a/plugins/plugin-annotations/src/pleat.mjs +++ b/plugins/plugin-annotations/src/pleat.mjs @@ -1,76 +1,71 @@ -import { name, version } from '../data.mjs' - const markers = ` ` -export const pleat = { - name, - version, - hooks: { - preRender: (svg) => { +// Export hooks +export const pleatHooks = { + preRender: [ + function (svg) { if (svg.defs.indexOf(markers) === -1) svg.defs += markers }, - }, - macros: { - pleat: function (so, { points, paths, Path, complete, scale }) { - if (so === false) { - delete points.pleatFrom - delete points.pleatFromIn - delete points.pleatTo - delete points.pleatToIn - delete paths.pleatTo - delete paths.pleatFrom - delete paths.pleatArrow - return true - } - so = { - margin: 35, - prefix: 'pleat', - reverse: false, - ...so, - } - if (complete) { - points[so.prefix + 'From'] = so.from - points[so.prefix + 'To'] = so.to - points[so.prefix + 'FromIn'] = points[so.prefix + 'From'].shift( - so.from.shiftTowards(so.to, 0.1).angle(so.from) + 270, - so.margin * scale - ) - points[so.prefix + 'ToIn'] = points[so.prefix + 'To'].shift( - so.from.shiftTowards(so.to, 0.1).angle(so.to) + 90, - so.margin * scale - ) - paths[so.prefix + 'PleatFrom'] = new Path() - .move(points[so.prefix + 'From']) - .line(points[so.prefix + 'FromIn']) - .attr('class', 'note' + (so.reverse ? ' dashed' : '')) - paths[so.prefix + 'PleatTo'] = new Path() - .move(points[so.prefix + 'To']) - .line(points[so.prefix + 'ToIn']) - .attr('class', 'note' + (so.reverse ? '' : ' dashed')) - paths[so.prefix + 'PleatArrow'] = new Path() - .move( - points[so.prefix + (so.reverse ? 'To' : 'From')].shiftFractionTowards( - points[so.prefix + (so.reverse ? 'ToIn' : 'FromIn')], - 0.25 - ) - ) - .line( - points[so.prefix + (so.reverse ? 'From' : 'To')].shiftFractionTowards( - points[so.prefix + (so.reverse ? 'FromIn' : 'ToIn')], - 0.25 - ) - ) - .attr('class', 'note') - .attr('marker-end', 'url(#pleatTo)') - } - }, - }, + ], } -// More specifically named exports -export const pleatPlugin = pleat -export const pluginPleat = pleat +// Export macros +export const pleatMacros = { + pleat: function (so, { points, paths, Path, complete, scale }) { + if (so === false) { + delete points.pleatFrom + delete points.pleatFromIn + delete points.pleatTo + delete points.pleatToIn + delete paths.pleatTo + delete paths.pleatFrom + delete paths.pleatArrow + return true + } + so = { + margin: 35, + prefix: 'pleat', + reverse: false, + ...so, + } + if (complete) { + points[so.prefix + 'From'] = so.from + points[so.prefix + 'To'] = so.to + points[so.prefix + 'FromIn'] = points[so.prefix + 'From'].shift( + so.from.shiftTowards(so.to, 0.1).angle(so.from) + 270, + so.margin * scale + ) + points[so.prefix + 'ToIn'] = points[so.prefix + 'To'].shift( + so.from.shiftTowards(so.to, 0.1).angle(so.to) + 90, + so.margin * scale + ) + paths[so.prefix + 'PleatFrom'] = new Path() + .move(points[so.prefix + 'From']) + .line(points[so.prefix + 'FromIn']) + .attr('class', 'note' + (so.reverse ? ' dashed' : '')) + paths[so.prefix + 'PleatTo'] = new Path() + .move(points[so.prefix + 'To']) + .line(points[so.prefix + 'ToIn']) + .attr('class', 'note' + (so.reverse ? '' : ' dashed')) + paths[so.prefix + 'PleatArrow'] = new Path() + .move( + points[so.prefix + (so.reverse ? 'To' : 'From')].shiftFractionTowards( + points[so.prefix + (so.reverse ? 'ToIn' : 'FromIn')], + 0.25 + ) + ) + .line( + points[so.prefix + (so.reverse ? 'From' : 'To')].shiftFractionTowards( + points[so.prefix + (so.reverse ? 'FromIn' : 'ToIn')], + 0.25 + ) + ) + .attr('class', 'note') + .attr('marker-end', 'url(#pleatTo)') + } + }, +} diff --git a/plugins/plugin-annotations/src/scalebox.mjs b/plugins/plugin-annotations/src/scalebox.mjs index bb917a01670..53130ce42f1 100644 --- a/plugins/plugin-annotations/src/scalebox.mjs +++ b/plugins/plugin-annotations/src/scalebox.mjs @@ -1,297 +1,282 @@ -import { name, version } from '../data.mjs' +// Export macros +export const scaleboxMacros = { + scalebox: function (so, { store, points, paths, scale, Point, Path }) { + // Passing `false` will remove the scalebox + if (so === false) { + for (let id of [ + '__scaleboxMetricTopLeft', + '__scaleboxMetricTopRight', + '__scaleboxMetricBottomRight', + '__scaleboxMetricBottomLeft', + '__scaleboxImperialTopLeft', + '__scaleboxImperialTopRight', + '__scaleboxImperialBottomRight', + '__scaleboxImperialBottomLeft', + '__scaleboxLead', + '__scaleboxTitle', + '__scaleboxText', + '__scaleboxLink', + '__scaleboxMetric', + '__scaleboxImperial', + ]) + delete points[id] + for (let id of ['__scaleboxMetric', '__scaleboxImperial']) delete paths[id] + return true + } -const markers = ` - - - -` + // Convert scale to a value between 0 and 9, inclusive. + const scaleIndex = Math.round(10 * Math.max(0.1, Math.min(1, scale))) - 1 -export const scalebox = { - name, - version, - macros: { - scalebox: function (so, { store, points, paths, scale, Point, Path }) { - // Passing `false` will remove the scalebox - if (so === false) { - for (let id of [ - '__scaleboxMetricTopLeft', - '__scaleboxMetricTopRight', - '__scaleboxMetricBottomRight', - '__scaleboxMetricBottomLeft', - '__scaleboxImperialTopLeft', - '__scaleboxImperialTopRight', - '__scaleboxImperialBottomRight', - '__scaleboxImperialBottomLeft', - '__scaleboxLead', - '__scaleboxTitle', - '__scaleboxText', - '__scaleboxLink', - '__scaleboxMetric', - '__scaleboxImperial', - ]) - delete points[id] - for (let id of ['__scaleboxMetric', '__scaleboxImperial']) delete paths[id] - return true - } + // Metric width and height in mm and display width and height for each scale index. + const metricSizes = [ + [10, 5, '1cm', '0.5cm'], + [20, 10, '2cm', '1cm'], + [30, 15, '3cm', '1.5cm'], + [40, 20, '4cm', '2cm'], + [50, 25, '5cm', '2.5cm'], + [60, 30, '6cm', '3cm'], + [70, 35, '7cm', '3.5cm'], + [80, 40, '8cm', '4cm'], + [90, 45, '9cm', '4.5cm'], + [100, 50, '10cm', '5cm'], + ] - // Convert scale to a value between 0 and 9, inclusive. - const scaleIndex = Math.round(10 * Math.max(0.1, Math.min(1, scale))) - 1 + const metricWidth = metricSizes[scaleIndex][0] + const metricHeight = metricSizes[scaleIndex][1] + const metricDisplayWidth = metricSizes[scaleIndex][2] + const metricDisplayHeight = metricSizes[scaleIndex][3] - // Metric width and height in mm and display width and height for each scale index. - const metricSizes = [ - [10, 5, '1cm', '0.5cm'], - [20, 10, '2cm', '1cm'], - [30, 15, '3cm', '1.5cm'], - [40, 20, '4cm', '2cm'], - [50, 25, '5cm', '2.5cm'], - [60, 30, '6cm', '3cm'], - [70, 35, '7cm', '3.5cm'], - [80, 40, '8cm', '4cm'], - [90, 45, '9cm', '4.5cm'], - [100, 50, '10cm', '5cm'], + // Imperial width and height in mm and display width and heigth for each scale index. + const imperialSizes = [ + [25.4 * 0.5, 25.4 * 0.25, '½″', '¼″'], + [25.4 * 0.875, 25.4 * 0.5, '⅞″', '½″'], + [25.4 * 1.25, 25.4 * 0.625, '1 ¼″', '⅝″'], + [25.4 * 1.625, 25.4 * 0.875, '1 ⅝″', '⅞″'], + [25.4 * 2, 25.4 * 1, '2″', '1″'], + [25.4 * 2.375, 25.4 * 1.25, '2 ⅜″', '1 ¼″'], + [25.4 * 2.875, 25.4 * 1.5, '2 ⅞″', '1 ½″'], + [25.4 * 3.25, 25.4 * 1.625, '3 ¼″', '1 ⅝″'], + [25.4 * 3.625, 25.4 * 1.875, '3 ⅝″', '1 ⅞″'], + [25.4 * 4, 25.4 * 2, '4″', '2″'], + ] + + const imperialWidth = imperialSizes[scaleIndex][0] + const imperialHeight = imperialSizes[scaleIndex][1] + const imperialDisplayWidth = imperialSizes[scaleIndex][2] + const imperialDisplayHeight = imperialSizes[scaleIndex][3] + + // Box points + 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 + ) + points.__scaleboxMetricBottomRight = new Point( + so.at.x + metricWidth / 2, + so.at.y + metricHeight / 2 + ) + points.__scaleboxImperialTopLeft = new Point( + so.at.x - imperialWidth / 2, + so.at.y - imperialHeight / 2 + ) + points.__scaleboxImperialTopRight = new Point( + so.at.x + imperialWidth / 2, + so.at.y - imperialHeight / 2 + ) + points.__scaleboxImperialBottomLeft = new Point( + so.at.x - imperialWidth / 2, + so.at.y + imperialHeight / 2 + ) + points.__scaleboxImperialBottomRight = new Point( + so.at.x + imperialWidth / 2, + so.at.y + imperialHeight / 2 + ) + // Text anchor points + 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) { + so.rotate = Number(so.rotate) + let toRotate = [ + '__scaleboxMetricTopLeft', + '__scaleboxMetricTopRight', + '__scaleboxMetricBottomLeft', + '__scaleboxMetricBottomRight', + '__scaleboxImperialTopLeft', + '__scaleboxImperialTopRight', + '__scaleboxImperialBottomLeft', + '__scaleboxImperialBottomRight', + '__scaleboxLead', + '__scaleboxTitle', + '__scaleboxText', + '__scaleboxLink', + '__scaleboxMetric', + '__scaleboxImperial', ] + 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}, ${points[pid].x}, ${points[pid].y})` + ) + } + } + // Paths + paths.__scaleboxImperial = new Path() + .attr('class', 'scalebox imperial fill-current') + .move(points.__scaleboxImperialTopLeft) + .line(points.__scaleboxImperialBottomLeft) + .line(points.__scaleboxImperialBottomRight) + .line(points.__scaleboxImperialTopRight) + .close() + paths.__scaleboxMetric = new Path() + .attr('class', 'scalebox metric fill-bg') + .move(points.__scaleboxMetricTopLeft) + .line(points.__scaleboxMetricBottomLeft) + .line(points.__scaleboxMetricBottomRight) + .line(points.__scaleboxMetricTopRight) + .close() + // Lead + points.__scaleboxLead = points.__scaleboxLead + .attr('data-text', so.lead || 'FreeSewing') + .attr('data-text-class', 'text-sm') + // Title + if (so.title) points.__scaleboxTitle.attributes.set('data-text', so.title) + else { + let name = store.data?.name || 'No Name' + if (name.indexOf('@freesewing/') !== -1) name = name.replace('@freesewing/', '') + points.__scaleboxTitle = points.__scaleboxTitle + .attr('data-text', name) + .attr('data-text', 'v' + (store.data?.version || 'No Version')) + } + points.__scaleboxTitle.attributes.add('data-text-class', 'text-lg') + // Text + if (typeof so.text === 'string') { + points.__scaleboxText.attr('data-text', so.text) + } else { + 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') + } + points.__scaleboxText.attr('data-text-class', 'text-xs').attr('data-text-lineheight', 4) + // Instructions + 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') + points.__scaleboxImperial = points.__scaleboxImperial + .attr('data-text', 'theBlackOutsideOfThisBoxShouldMeasure') + .attr('data-text', `${imperialDisplayWidth}`) + .attr('data-text', 'x') + .attr('data-text', `${imperialDisplayHeight}`) + .attr('data-text-class', 'text-xs center ') + }, + miniscale(so, { store, points, paths, scale, Point, Path }) { + // Passing `false` will remove the miniscale + if (so === false) { + for (const id of [ + '__miniscaleMetricTopLeft', + '__miniscaleMetricTopRight', + '__miniscaleMetricBottomRight', + '__miniscaleMetricBottomLeft', + '__miniscaleImperialTopLeft', + '__miniscaleImperialTopRight', + '__miniscaleImperialBottomRight', + '__miniscaleImperialBottomLeft', + '__miniscaleMetric', + '__miniscaleImperial', + ]) + delete points[id] + for (const id of ['__miniscaleMetric', '__miniscaleImperial']) delete paths[id] + return true + } - const metricWidth = metricSizes[scaleIndex][0] - const metricHeight = metricSizes[scaleIndex][1] - const metricDisplayWidth = metricSizes[scaleIndex][2] - const metricDisplayHeight = metricSizes[scaleIndex][3] + // Convert scale to a value between 0 and 5, inclusive. + const scaleIndex = Math.ceil(6 * Math.max(0.1, Math.min(1, scale))) - 1 - // Imperial width and height in mm and display width and heigth for each scale index. - const imperialSizes = [ - [25.4 * 0.5, 25.4 * 0.25, '½″', '¼″'], - [25.4 * 0.875, 25.4 * 0.5, '⅞″', '½″'], - [25.4 * 1.25, 25.4 * 0.625, '1 ¼″', '⅝″'], - [25.4 * 1.625, 25.4 * 0.875, '1 ⅝″', '⅞″'], - [25.4 * 2, 25.4 * 1, '2″', '1″'], - [25.4 * 2.375, 25.4 * 1.25, '2 ⅜″', '1 ¼″'], - [25.4 * 2.875, 25.4 * 1.5, '2 ⅞″', '1 ½″'], - [25.4 * 3.25, 25.4 * 1.625, '3 ¼″', '1 ⅝″'], - [25.4 * 3.625, 25.4 * 1.875, '3 ⅝″', '1 ⅞″'], - [25.4 * 4, 25.4 * 2, '4″', '2″'], + // Metric size in mm / display value and imperial size in mm / display value for each scale index. + const sizes = [ + [10, '1cm', 25.4 * 0.375, '⅜″'], + [13, '1.3cm', 25.4 * 0.5, '½″'], + [16, '1.6cm', 25.4 * 0.625, '⅝″'], + [19, '1.9cm', 25.4 * 0.75, '¾″'], + [22, '2.2cm', 25.4 * 0.875, '⅞″'], + [25, '2.5cm', 25.4 * 1, '1″'], + ] + const m = sizes[scaleIndex][0] / 2 + const i = sizes[scaleIndex][2] / 2 + const metricDisplaySize = sizes[scaleIndex][1] + const imperialDisplaySize = sizes[scaleIndex][3] + // Box points + 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 + 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) { + so.rotate = Number(so.rotate) + let toRotate = [ + '__miniscaleMetricTopLeft', + '__miniscaleMetricTopRight', + '__miniscaleMetricBottomLeft', + '__miniscaleMetricBottomRight', + '__miniscaleImperialTopLeft', + '__miniscaleImperialTopRight', + '__miniscaleImperialBottomLeft', + '__miniscaleImperialBottomRight', + '__miniscaleMetric', + '__miniscaleImperial', ] - - const imperialWidth = imperialSizes[scaleIndex][0] - const imperialHeight = imperialSizes[scaleIndex][1] - const imperialDisplayWidth = imperialSizes[scaleIndex][2] - const imperialDisplayHeight = imperialSizes[scaleIndex][3] - - // Box points - 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 - ) - points.__scaleboxMetricBottomRight = new Point( - so.at.x + metricWidth / 2, - so.at.y + metricHeight / 2 - ) - points.__scaleboxImperialTopLeft = new Point( - so.at.x - imperialWidth / 2, - so.at.y - imperialHeight / 2 - ) - points.__scaleboxImperialTopRight = new Point( - so.at.x + imperialWidth / 2, - so.at.y - imperialHeight / 2 - ) - points.__scaleboxImperialBottomLeft = new Point( - so.at.x - imperialWidth / 2, - so.at.y + imperialHeight / 2 - ) - points.__scaleboxImperialBottomRight = new Point( - so.at.x + imperialWidth / 2, - so.at.y + imperialHeight / 2 - ) - // Text anchor points - 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) { - so.rotate = Number(so.rotate) - let toRotate = [ - '__scaleboxMetricTopLeft', - '__scaleboxMetricTopRight', - '__scaleboxMetricBottomLeft', - '__scaleboxMetricBottomRight', - '__scaleboxImperialTopLeft', - '__scaleboxImperialTopRight', - '__scaleboxImperialBottomLeft', - '__scaleboxImperialBottomRight', - '__scaleboxLead', - '__scaleboxTitle', - '__scaleboxText', - '__scaleboxLink', - '__scaleboxMetric', - '__scaleboxImperial', - ] - 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}, ${points[pid].x}, ${points[pid].y})` - ) - } + 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}, ${points[pid].x}, ${points[pid].y})` + ) } - // Paths - paths.__scaleboxImperial = new Path() - .attr('class', 'scalebox imperial fill-current') - .move(points.__scaleboxImperialTopLeft) - .line(points.__scaleboxImperialBottomLeft) - .line(points.__scaleboxImperialBottomRight) - .line(points.__scaleboxImperialTopRight) - .close() - paths.__scaleboxMetric = new Path() - .attr('class', 'scalebox metric fill-bg') - .move(points.__scaleboxMetricTopLeft) - .line(points.__scaleboxMetricBottomLeft) - .line(points.__scaleboxMetricBottomRight) - .line(points.__scaleboxMetricTopRight) - .close() - // Lead - points.__scaleboxLead = points.__scaleboxLead - .attr('data-text', so.lead || 'FreeSewing') - .attr('data-text-class', 'text-sm') - // Title - if (so.title) points.__scaleboxTitle.attributes.set('data-text', so.title) - else { - let name = store.data?.name || 'No Name' - if (name.indexOf('@freesewing/') !== -1) name = name.replace('@freesewing/', '') - points.__scaleboxTitle = points.__scaleboxTitle - .attr('data-text', name) - .attr('data-text', 'v' + (store.data?.version || 'No Version')) - } - points.__scaleboxTitle.attributes.add('data-text-class', 'text-lg') - // Text - if (typeof so.text === 'string') { - points.__scaleboxText.attr('data-text', so.text) - } else { - 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') - } - points.__scaleboxText.attr('data-text-class', 'text-xs').attr('data-text-lineheight', 4) - // Instructions - 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') - points.__scaleboxImperial = points.__scaleboxImperial - .attr('data-text', 'theBlackOutsideOfThisBoxShouldMeasure') - .attr('data-text', `${imperialDisplayWidth}`) - .attr('data-text', 'x') - .attr('data-text', `${imperialDisplayHeight}`) - .attr('data-text-class', 'text-xs center ') - }, - miniscale(so, { store, points, paths, scale, Point, Path }) { - // Passing `false` will remove the miniscale - if (so === false) { - for (const id of [ - '__miniscaleMetricTopLeft', - '__miniscaleMetricTopRight', - '__miniscaleMetricBottomRight', - '__miniscaleMetricBottomLeft', - '__miniscaleImperialTopLeft', - '__miniscaleImperialTopRight', - '__miniscaleImperialBottomRight', - '__miniscaleImperialBottomLeft', - '__miniscaleMetric', - '__miniscaleImperial', - ]) - delete points[id] - for (const id of ['__miniscaleMetric', '__miniscaleImperial']) delete paths[id] - return true - } - - // Convert scale to a value between 0 and 5, inclusive. - 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 = [ - [10, '1cm', 25.4 * 0.375, '⅜″'], - [13, '1.3cm', 25.4 * 0.5, '½″'], - [16, '1.6cm', 25.4 * 0.625, '⅝″'], - [19, '1.9cm', 25.4 * 0.75, '¾″'], - [22, '2.2cm', 25.4 * 0.875, '⅞″'], - [25, '2.5cm', 25.4 * 1, '1″'], - ] - const m = sizes[scaleIndex][0] / 2 - const i = sizes[scaleIndex][2] / 2 - const metricDisplaySize = sizes[scaleIndex][1] - const imperialDisplaySize = sizes[scaleIndex][3] - // Box points - 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 - 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) { - so.rotate = Number(so.rotate) - let toRotate = [ - '__miniscaleMetricTopLeft', - '__miniscaleMetricTopRight', - '__miniscaleMetricBottomLeft', - '__miniscaleMetricBottomRight', - '__miniscaleImperialTopLeft', - '__miniscaleImperialTopRight', - '__miniscaleImperialBottomLeft', - '__miniscaleImperialBottomRight', - '__miniscaleMetric', - '__miniscaleImperial', - ] - 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}, ${points[pid].x}, ${points[pid].y})` - ) - } - } - // Paths - paths.__miniscaleImperial = new Path() - .attr('class', 'scalebox imperial fill-current') - .move(points.__miniscaleImperialTopLeft) - .line(points.__miniscaleImperialBottomLeft) - .line(points.__miniscaleImperialBottomRight) - .line(points.__miniscaleImperialTopRight) - .close() - paths.__miniscaleMetric = new Path() - .attr('class', 'scalebox metric fill-bg') - .move(points.__miniscaleMetricTopLeft) - .line(points.__miniscaleMetricBottomLeft) - .line(points.__miniscaleMetricBottomRight) - .line(points.__miniscaleMetricTopRight) - .close() - // Text - points.__miniscaleMetric = points.__miniscaleMetric - .attr('data-text', `${metricDisplaySize} x ${metricDisplaySize}`) - .attr('data-text-class', 'text-xs center') - points.__miniscaleImperial = points.__miniscaleImperial - .attr('data-text', `${imperialDisplaySize} x ${imperialDisplaySize}`) - .attr('data-text-class', 'text-xs center ') - }, + } + // Paths + paths.__miniscaleImperial = new Path() + .attr('class', 'scalebox imperial fill-current') + .move(points.__miniscaleImperialTopLeft) + .line(points.__miniscaleImperialBottomLeft) + .line(points.__miniscaleImperialBottomRight) + .line(points.__miniscaleImperialTopRight) + .close() + paths.__miniscaleMetric = new Path() + .attr('class', 'scalebox metric fill-bg') + .move(points.__miniscaleMetricTopLeft) + .line(points.__miniscaleMetricBottomLeft) + .line(points.__miniscaleMetricBottomRight) + .line(points.__miniscaleMetricTopRight) + .close() + // Text + points.__miniscaleMetric = points.__miniscaleMetric + .attr('data-text', `${metricDisplaySize} x ${metricDisplaySize}`) + .attr('data-text-class', 'text-xs center') + points.__miniscaleImperial = points.__miniscaleImperial + .attr('data-text', `${imperialDisplaySize} x ${imperialDisplaySize}`) + .attr('data-text-class', 'text-xs center ') }, } - -// More specifically named exports -export const scaleboxPlugin = scalebox -export const pluginScalebox = scalebox diff --git a/plugins/plugin-annotations/src/sewtogether.mjs b/plugins/plugin-annotations/src/sewtogether.mjs index 3c289b17ae4..eac510bbf07 100644 --- a/plugins/plugin-annotations/src/sewtogether.mjs +++ b/plugins/plugin-annotations/src/sewtogether.mjs @@ -1,5 +1,3 @@ -import { name, version } from '../data.mjs' - const markers = ` @@ -12,83 +10,80 @@ const markers = ` ` -export const sewtogether = { - name, - version, - hooks: { - preRender: (svg) => { +// Export hooks +export const sewtogetherHooks = { + preRender: [ + function (svg) { if (svg.defs.indexOf(markers) === -1) svg.defs += markers }, - }, - macros: { - sewtogether: function (so, { points, paths, Path, complete, scale, sa }) { - if (so === false) { - delete points.sewtogetherFrom - delete points.sewtogetherFromCp - delete points.sewtogetherMiddle - delete points.sewtogetherTo - delete points.sewtogetherHinge - delete points.sewtogetherToCp - delete paths.sewtogetherSewTogetherHinge - delete paths.sewtogetherSewTogether - return true - } - so = { - prefix: 'sewtogether', - ...so, - } - if (complete) { - if (null == so.middle) { - so.middle = so.from.shiftFractionTowards(so.to, 0.5) - } - points[so.prefix + 'From'] = so.from - points[so.prefix + 'Middle'] = so.middle - points[so.prefix + 'To'] = so.to - - points[so.prefix + 'FromCp'] = points[so.prefix + 'From'].shift( - points[so.prefix + 'From'].angle(points[so.prefix + 'Middle']) + 90, - points[so.prefix + 'From'].dist(points[so.prefix + 'Middle']) / 1.5 - ) - points[so.prefix + 'ToCp'] = points[so.prefix + 'To'].shift( - points[so.prefix + 'To'].angle(points[so.prefix + 'Middle']) - 90, - points[so.prefix + 'To'].dist(points[so.prefix + 'Middle']) / 1.5 - ) - - if (so.hinge) { - points[so.prefix + 'Hinge'] = points[so.prefix + 'Middle'].shift( - points[so.prefix + 'Middle'].angle(points[so.prefix + 'To']) + - Math.abs( - points[so.prefix + 'Middle'].angle(points[so.prefix + 'From']) - - points[so.prefix + 'Middle'].angle(points[so.prefix + 'To']) - ) / - 2 + - (sa ? 180 : 0), - sa - ? sa - : Math.min( - points[so.prefix + 'From'].dist(points[so.prefix + 'Middle']), - points[so.prefix + 'From'].dist(points[so.prefix + 'Middle']) - ) / 4 - ) - paths[so.prefix + 'SewTogetherHinge'] = new Path() - .move(points[so.prefix + 'Middle']) - .line(points[so.prefix + 'Hinge']) - .attr('marker-start', 'url(#sewTogetherCross)') - .attr('class', 'dotted note stroke-sm') - } - paths[so.prefix + 'SewTogether'] = new Path() - .move(points[so.prefix + 'From']) - .curve(points[so.prefix + 'FromCp'], points[so.prefix + 'ToCp'], points[so.prefix + 'To']) - .attr('class', 'dotted note stroke-sm') - .attr('marker-start', 'url(#sewTogetherStart)') - .attr('marker-end', 'url(#sewTogetherEnd)') - .attr('data-text', 'sewTogether') - .attr('data-text-class', 'center fill-note text-xs') - } - }, - }, + ], } -// More specifically named exports -export const sewtogetherPlugin = sewtogether -export const pluginSewtogether = sewtogether +// Export macros +export const sewtogetherMacros = { + sewtogether: function (so, { points, paths, Path, complete, scale, sa }) { + if (so === false) { + delete points.sewtogetherFrom + delete points.sewtogetherFromCp + delete points.sewtogetherMiddle + delete points.sewtogetherTo + delete points.sewtogetherHinge + delete points.sewtogetherToCp + delete paths.sewtogetherSewTogetherHinge + delete paths.sewtogetherSewTogether + return true + } + so = { + prefix: 'sewtogether', + ...so, + } + if (complete) { + if (null == so.middle) { + so.middle = so.from.shiftFractionTowards(so.to, 0.5) + } + points[so.prefix + 'From'] = so.from + points[so.prefix + 'Middle'] = so.middle + points[so.prefix + 'To'] = so.to + + points[so.prefix + 'FromCp'] = points[so.prefix + 'From'].shift( + points[so.prefix + 'From'].angle(points[so.prefix + 'Middle']) + 90, + points[so.prefix + 'From'].dist(points[so.prefix + 'Middle']) / 1.5 + ) + points[so.prefix + 'ToCp'] = points[so.prefix + 'To'].shift( + points[so.prefix + 'To'].angle(points[so.prefix + 'Middle']) - 90, + points[so.prefix + 'To'].dist(points[so.prefix + 'Middle']) / 1.5 + ) + + if (so.hinge) { + points[so.prefix + 'Hinge'] = points[so.prefix + 'Middle'].shift( + points[so.prefix + 'Middle'].angle(points[so.prefix + 'To']) + + Math.abs( + points[so.prefix + 'Middle'].angle(points[so.prefix + 'From']) - + points[so.prefix + 'Middle'].angle(points[so.prefix + 'To']) + ) / + 2 + + (sa ? 180 : 0), + sa + ? sa + : Math.min( + points[so.prefix + 'From'].dist(points[so.prefix + 'Middle']), + points[so.prefix + 'From'].dist(points[so.prefix + 'Middle']) + ) / 4 + ) + paths[so.prefix + 'SewTogetherHinge'] = new Path() + .move(points[so.prefix + 'Middle']) + .line(points[so.prefix + 'Hinge']) + .attr('marker-start', 'url(#sewTogetherCross)') + .attr('class', 'dotted note stroke-sm') + } + paths[so.prefix + 'SewTogether'] = new Path() + .move(points[so.prefix + 'From']) + .curve(points[so.prefix + 'FromCp'], points[so.prefix + 'ToCp'], points[so.prefix + 'To']) + .attr('class', 'dotted note stroke-sm') + .attr('marker-start', 'url(#sewTogetherStart)') + .attr('marker-end', 'url(#sewTogetherEnd)') + .attr('data-text', 'sewTogether') + .attr('data-text-class', 'center fill-note text-xs') + } + }, +}