diff --git a/.eslintignore b/.eslintignore index 563df111ab7..f8ea09c9779 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,5 @@ .git coverage node_modules +yarn.lock +package.json diff --git a/.eslintrc.yml b/.eslintrc.yml new file mode 100644 index 00000000000..b39fd0463e8 --- /dev/null +++ b/.eslintrc.yml @@ -0,0 +1,18 @@ +env: + browser: true + es2021: true +extends: eslint:recommended +overrides: + - files: ["*.yaml", "*.yml"] + plugins: ["yaml"] + extends: ["plugin:yaml/recommended"] +parserOptions: + ecmaVersion: latest + sourceType: module +rules: {} +globals: + it: readonly + describe: readonly + process: readonly + __dirname: readonly + diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 00000000000..5a182ef106d --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +yarn lint-staged diff --git a/.prettierignore b/.prettierignore index ec967556865..45663b6a19e 100644 --- a/.prettierignore +++ b/.prettierignore @@ -3,4 +3,8 @@ # So let's not *.yml *.md - +yarn.lock +.husky/pre-commit +.prettierignore +.gitignore +.eslintignore diff --git a/config/scripts.yaml b/config/scripts.yaml index 196a0ad1dc0..0ac37b74cb8 100644 --- a/config/scripts.yaml +++ b/config/scripts.yaml @@ -3,16 +3,16 @@ _: clean: 'rimraf dist' mbuild: 'NO_MINIFY=1 node build.mjs' symlink: 'mkdir -p ./node_modules/@freesewing && cd ./node_modules/@freesewing && ln -s -f ../../../* . && cd -' - test: ¬ests 'echo "{{name}}: No tests configured. Perhaps you''d like to do this?" && exit 0' + test: 'echo "{{name}}: No tests configured. Perhaps you could write some?" && exit 0' vbuild: 'VERBOSE=1 node build.mjs' - lab: "cd ../../sites/lab && yarn start" - tips: "node ../../scripts/help.mjs" + lab: 'cd ../../sites/lab && yarn start' + tips: 'node ../../scripts/help.mjs' lint: "npx eslint 'src/**' 'tests/*.mjs'" _types: design: prettier: "npx prettier --write 'src/*.mjs' 'tests/*.mjs'" test: &test 'npx mocha tests/*.test.mjs' - testci: &testci "npx mocha tests/*.test.mjs --reporter ../../tests/reporters/terse.js" + testci: &testci 'npx mocha tests/*.test.mjs --reporter ../../tests/reporters/terse.js' plugin: prettier: "npx prettier --write 'src/*.mjs' 'tests/*.mjs'" test: *test @@ -20,17 +20,15 @@ _types: core: report: 'c8 report' test: 'c8 mocha tests/*.test.mjs' - testci: "mocha tests/*.test.mjs" + testci: 'mocha tests/*.test.mjs' prettier: "npx prettier --write 'src/*.mjs' 'tests/*.mjs'" lint: "npx eslint 'src/*.mjs' 'tests/*.mjs'" i18n: prebuild: 'node scripts/prebuilder.mjs' - test: *test - testci: *testci models: - test: "npx mocha tests/*.test.mjs" + test: 'npx mocha tests/*.test.mjs' new-design: - build: "SITE=new-design/shared node ../../sites/shared/prebuild/i18n-only.mjs && cp ../../scripts/banner.mjs ./lib && node build.mjs" + build: 'SITE=new-design/shared node ../../sites/shared/prebuild/i18n-only.mjs && cp ../../scripts/banner.mjs ./lib && node build.mjs' lint: "npx eslint 'lib/*.mjs'" mbuild: '!' test: '!' @@ -41,5 +39,4 @@ rehype-jargon: snapseries: lint: "npx eslint 'src/*.mjs'" backend: - lint: "!" - + lint: '!' diff --git a/designs/brian/src/back.mjs b/designs/brian/src/back.mjs index 20cbd53ab47..74b8e05980e 100644 --- a/designs/brian/src/back.mjs +++ b/designs/brian/src/back.mjs @@ -184,5 +184,5 @@ export const back = { } return part - } + }, } diff --git a/designs/brian/src/base.mjs b/designs/brian/src/base.mjs index 78c63f91e4a..48bfd141ac3 100644 --- a/designs/brian/src/base.mjs +++ b/designs/brian/src/base.mjs @@ -13,7 +13,7 @@ export const base = { 'shoulderSlope', 'waistToHips', ], - optionalMeasurements: [ 'highBust' ], + optionalMeasurements: ['highBust'], options: { // Static brianFitSleeve: true, @@ -37,7 +37,7 @@ export const base = { frontArmholeDeeper: { pct: 0.2, min: 0, max: 0.5, menu: 'advanced' }, shoulderSlopeReduction: { pct: 0, min: 0, max: 80, menu: 'advanced' }, }, - plugins: [ pluginBundle, bustPlugin ], + plugins: [pluginBundle, bustPlugin], draft: ({ measurements, options, @@ -53,7 +53,6 @@ export const base = { macro, part, }) => { - store.set('shoulderEase', (measurements.shoulderToShoulder * options.shoulderEase) / 2) // Center back (cb) vertical axis @@ -63,7 +62,10 @@ export const base = { points.cbHips = new Point(0, points.cbWaist.y + measurements.waistToHips) // Shoulder line - points.neck = new Point((measurements.neck * (1 + options.collarEase)) / options.collarFactor, 0) + points.neck = new Point( + (measurements.neck * (1 + options.collarEase)) / options.collarFactor, + 0 + ) points.hps = points.neck.clone() // We started using HPS in many measurements // Shoulder point using shoulderSlope degree measurement points.shoulder = utils.beamsIntersect( @@ -76,7 +78,8 @@ export const base = { points.cbShoulder = new Point(0, points.shoulder.y) points.cbArmhole = new Point( 0, - points.shoulder.y + measurements.biceps * (1 + options.bicepsEase) * options.armholeDepthFactor + points.shoulder.y + + measurements.biceps * (1 + options.bicepsEase) * options.armholeDepthFactor ) // Now take shoulder slope reduction into account @@ -87,7 +90,10 @@ export const base = { points.cbHem = new Point(0, points.cbHips.y * (1 + options.lengthBonus)) // Side back (cb) vertical axis - points.armhole = new Point((measurements.chest * (1 + options.chestEase)) / 4, points.cbArmhole.y) + points.armhole = new Point( + (measurements.chest * (1 + options.chestEase)) / 4, + points.cbArmhole.y + ) points.waist = new Point(points.armhole.x, points.cbWaist.y) points.hips = new Point(points.armhole.x, points.cbHips.y) points.hem = new Point(points.armhole.x, points.cbHem.y) @@ -170,10 +176,10 @@ export const base = { points.gridAnchor = points.cbHem /* - * People would like to have the option to shift the shoulder seam - * See https://github.com/freesewing/freesewing/issues/642 - * So let's make the people happy - */ + * People would like to have the option to shift the shoulder seam + * See https://github.com/freesewing/freesewing/issues/642 + * So let's make the people happy + */ // Front armhole is a bit deeper, add those points let deeper = measurements.chest * options.frontArmholeDeeper for (const p of ['', 'Cp1', 'Cp2']) { @@ -210,6 +216,5 @@ export const base = { } return part - } + }, } - diff --git a/designs/brian/src/front.mjs b/designs/brian/src/front.mjs index 3183b8ad7bf..d274f4ed1fb 100644 --- a/designs/brian/src/front.mjs +++ b/designs/brian/src/front.mjs @@ -20,7 +20,6 @@ export const front = { utils, part, }) => { - // Re-use points for deeper armhole at the front points.armholePitchCp1 = points.frontArmholePitchCp1 points.armholePitch = points.frontArmholePitch @@ -62,7 +61,9 @@ export const front = { .curve_(points.mirroredNeckCp2, points.mirroredCbNeck) .split(points.s3CollarSplit)[0] .reverse() - .join(new Path().move(points.hps).curve(points.neckCp2Front, points.cfNeckCp1, points.cfNeck)) + .join( + new Path().move(points.hps).curve(points.neckCp2Front, points.cfNeckCp1, points.cfNeck) + ) .setRender(false) } if (options.s3Armhole < 0.1 && options.s3Armhole > -0.1) { @@ -194,5 +195,5 @@ export const front = { } return part - } + }, } diff --git a/designs/brian/src/index.mjs b/designs/brian/src/index.mjs index 167d3b52ba2..6e454756f9b 100644 --- a/designs/brian/src/index.mjs +++ b/designs/brian/src/index.mjs @@ -10,7 +10,7 @@ import { sleevecap } from './sleevecap.mjs' // Setup our new design const Brian = new Design({ data, - parts: [ back, front, sleeve ] + parts: [back, front, sleeve], }) // Named exports diff --git a/designs/brian/src/sleeve.mjs b/designs/brian/src/sleeve.mjs index d848829be54..5de02cfd6af 100644 --- a/designs/brian/src/sleeve.mjs +++ b/designs/brian/src/sleeve.mjs @@ -4,12 +4,9 @@ export const sleeve = { from: sleevecap, name: 'brian.sleeve', options: { - sleeveLengthBonus: { pct: 0, min: -40, max: 10, menu: 'style' } + sleeveLengthBonus: { pct: 0, min: -40, max: 10, menu: 'style' }, }, - measurements: [ - 'shoulderToWrist', - 'wrist', - ], + measurements: ['shoulderToWrist', 'wrist'], draft: ({ store, sa, @@ -26,7 +23,6 @@ export const sleeve = { macro, part, }) => { - // Remove things inherited macro('cutonfold', false) macro('rmad') @@ -40,7 +36,10 @@ export const sleeve = { // Wrist points.centerWrist = points.sleeveTop.shift(-90, store.get('sleeveLength')) - points.wristRight = points.centerWrist.shift(0, (measurements.wrist * (1 + options.cuffEase)) / 2) + points.wristRight = points.centerWrist.shift( + 0, + (measurements.wrist * (1 + options.cuffEase)) / 2 + ) points.wristLeft = points.wristRight.rotate(180, points.centerWrist) // Paths @@ -70,7 +69,9 @@ export const sleeve = { macro('scalebox', { at: points.scalebox }) points.frontNotch = paths.sleevecap.shiftAlong(store.get('frontArmholeToArmholePitch')) - points.backNotch = paths.sleevecap.reverse().shiftAlong(store.get('backArmholeToArmholePitch')) + points.backNotch = paths.sleevecap + .reverse() + .shiftAlong(store.get('backArmholeToArmholePitch')) snippets.frontNotch = new Snippet('notch', points.frontNotch) snippets.backNotch = new Snippet('bnotch', points.backNotch) if (sa) paths.sa = paths.seam.offset(sa).attr('class', 'fabric sa') @@ -104,5 +105,5 @@ export const sleeve = { }) } return part - } + }, } diff --git a/designs/brian/src/sleevecap.mjs b/designs/brian/src/sleevecap.mjs index 23cd27ad52e..00d8d54ec14 100644 --- a/designs/brian/src/sleevecap.mjs +++ b/designs/brian/src/sleevecap.mjs @@ -166,7 +166,6 @@ export const sleevecap = { sleeveWidthGuarantee: { pct: 90, min: 25, max: 100, menu: 'advanced' }, }, draft: ({ store, units, options, Point, points, paths, log, snippets, macro, part }) => { - // Clean up from fron for (const path in paths) delete paths[path] delete snippets.logo @@ -190,5 +189,5 @@ export const sleevecap = { points.gridAnchor = new Point(0, 0) return part - } + }, } diff --git a/designs/examples/src/index.mjs b/designs/examples/src/index.mjs index 30941af59d5..50cdfa2a04f 100644 --- a/designs/examples/src/index.mjs +++ b/designs/examples/src/index.mjs @@ -359,6 +359,5 @@ export { // Docs docs_coords, docs_overview, - Examples, } diff --git a/designs/examples/src/stacks.mjs b/designs/examples/src/stacks.mjs index 17e3970184d..8b0cd0255f6 100644 --- a/designs/examples/src/stacks.mjs +++ b/designs/examples/src/stacks.mjs @@ -69,7 +69,10 @@ export const stacks_leftEye = { stack, after: stacks_top, draft: ({ store, Point, points, part }) => { - points.leftEye = new Point(store.get('x') + store.get('size') * 0.35, store.get('y') + store.get('size') * 0.4) + points.leftEye = new Point( + store.get('x') + store.get('size') * 0.35, + store.get('y') + store.get('size') * 0.4 + ) .attr('data-circle', store.get('size') * 0.1) .attr('data-circle-class', 'stroke-6xl') @@ -82,7 +85,10 @@ export const stacks_rightEye = { stack, after: stacks_top, draft: ({ store, Point, points, part }) => { - points.rightEye = new Point(store.get('x') + store.get('size') * 0.65, store.get('y') + store.get('size') * 0.4) + points.rightEye = new Point( + store.get('x') + store.get('size') * 0.65, + store.get('y') + store.get('size') * 0.4 + ) .attr('data-circle', store.get('size') * 0.08) .attr('data-circle-class', 'stroke-7xl') @@ -95,10 +101,22 @@ export const stacks_mouth = { stack, after: stacks_top, draft: ({ store, Point, points, paths, Path, part }) => { - points.left = new Point(store.get('x') + store.get('size') * 0.15, store.get('y') + store.get('size') * 0.5) - points.right = new Point(store.get('x') + store.get('size') * 0.85, store.get('y') + store.get('size') * 0.5) - points.leftCp = new Point(store.get('x') + store.get('size') * 0.35, store.get('y') + store.get('size') * 0.8) - points.rightCp = new Point(store.get('x') + store.get('size') * 0.65, store.get('y') + store.get('size') * 0.8) + points.left = new Point( + store.get('x') + store.get('size') * 0.15, + store.get('y') + store.get('size') * 0.5 + ) + points.right = new Point( + store.get('x') + store.get('size') * 0.85, + store.get('y') + store.get('size') * 0.5 + ) + points.leftCp = new Point( + store.get('x') + store.get('size') * 0.35, + store.get('y') + store.get('size') * 0.8 + ) + points.rightCp = new Point( + store.get('x') + store.get('size') * 0.65, + store.get('y') + store.get('size') * 0.8 + ) paths.mouth = new Path() .move(points.left) diff --git a/designs/hugo/src/front.mjs b/designs/hugo/src/front.mjs index 8f90a97e5cb..f0033445328 100644 --- a/designs/hugo/src/front.mjs +++ b/designs/hugo/src/front.mjs @@ -30,7 +30,6 @@ function hugoFront({ macro, part, }) { - // Remove clutter for (const key in paths) { if (key !== 'seam') delete paths[key] diff --git a/designs/hugo/src/pocket.mjs b/designs/hugo/src/pocket.mjs index 4e1650cecb8..299374ce790 100644 --- a/designs/hugo/src/pocket.mjs +++ b/designs/hugo/src/pocket.mjs @@ -1,7 +1,18 @@ import { front } from './front.mjs' -function hugoPocket({ utils, store, sa, points, Path, paths, complete, paperless, macro, snippets, part }) { - +function hugoPocket({ + utils, + store, + sa, + points, + Path, + paths, + complete, + paperless, + macro, + snippets, + part, +}) { // Remove clutter for (const key in paths) { if (key !== 'pocket') delete paths[key] diff --git a/designs/hugo/src/pocketfacing.mjs b/designs/hugo/src/pocketfacing.mjs index 718ea3c519d..e8f5388e608 100644 --- a/designs/hugo/src/pocketfacing.mjs +++ b/designs/hugo/src/pocketfacing.mjs @@ -1,7 +1,6 @@ import { pocket } from './pocket.mjs' function hugoPocketFacing({ sa, points, Path, paths, complete, paperless, macro, store, part }) { - // Remove clutter for (const key in paths) { if (key !== 'facing') delete paths[key] diff --git a/designs/sven/src/waistband.mjs b/designs/sven/src/waistband.mjs index 6d830a4e298..a04898a28ee 100644 --- a/designs/sven/src/waistband.mjs +++ b/designs/sven/src/waistband.mjs @@ -19,7 +19,6 @@ function svenWaistband(params) { }) } - return part } diff --git a/designs/tutorial/src/bib.mjs b/designs/tutorial/src/bib.mjs index 1777302f6ee..454513f84c9 100644 --- a/designs/tutorial/src/bib.mjs +++ b/designs/tutorial/src/bib.mjs @@ -17,7 +17,6 @@ export const bib = { paperless, part, }) => { - // Construct the neck opening let tweak = 1 let target = (measurements.head * options.neckRatio) / 4 @@ -230,5 +229,5 @@ export const bib = { } return part - } + }, } diff --git a/designs/tutorial/src/configpart.mjs b/designs/tutorial/src/configpart.mjs index 224a88f74a3..8d2bc0cf751 100644 --- a/designs/tutorial/src/configpart.mjs +++ b/designs/tutorial/src/configpart.mjs @@ -5,7 +5,7 @@ import { pluginBundle } from '@freesewing/plugin-bundle' export const configpart = { name: 'tutorial.configpart', measurements: ['head'], - plugins: [ pluginBundle ], + plugins: [pluginBundle], options: { size: { pct: 50, min: 10, max: 100 }, neckRatio: { pct: 80, min: 70, max: 90 }, @@ -13,6 +13,5 @@ export const configpart = { lengthRatio: { pct: 75, min: 55, max: 85 }, }, hide: true, - draft: ({part}) => part + draft: ({ part }) => part, } - diff --git a/designs/tutorial/src/index.mjs b/designs/tutorial/src/index.mjs index ec94a399899..314a78eec1d 100644 --- a/designs/tutorial/src/index.mjs +++ b/designs/tutorial/src/index.mjs @@ -8,20 +8,7 @@ import { bib } from './bib.mjs' // Setup our new design const Tutorial = new Design({ data, - parts: [ - step1, - step2, - step3, - step4, - step5, - step6, - step7, - step8, - step9, - step10, - step11, - bib, - ] + parts: [step1, step2, step3, step4, step5, step6, step7, step8, step9, step10, step11, bib], }) // Named exports @@ -38,6 +25,5 @@ export { step10, step11, bib, - Tutorial + Tutorial, } - diff --git a/designs/tutorial/src/step1-4.mjs b/designs/tutorial/src/step1-4.mjs index 877ad0fd7b1..dd73e6e29a8 100644 --- a/designs/tutorial/src/step1-4.mjs +++ b/designs/tutorial/src/step1-4.mjs @@ -17,7 +17,6 @@ export const step1 = { macro, part, }) => { - let w = 500 * options.size points.topLeft = new Point(0, 0) points.topRight = new Point(w, 0) @@ -62,46 +61,31 @@ export const step1 = { } return part - } + }, } export const step2 = { name: 'tutorial.step2', after: configpart, - draft: ({ - Point, - points, - Path, - paths, - measurements, - part, - }) => { - + draft: ({ Point, points, Path, paths, measurements, part }) => { points.right = new Point(measurements.head / 10, 0) points.bottom = new Point(0, measurements.head / 12) points.rightCp1 = points.right.shift(90, points.bottom.dy(points.right) / 2) points.bottomCp2 = points.bottom.shift(0, points.bottom.dx(points.right) / 2) - paths.neck = new Path().move(points.right).curve(points.rightCp1, points.bottomCp2, points.bottom) + paths.neck = new Path() + .move(points.right) + .curve(points.rightCp1, points.bottomCp2, points.bottom) return part - } + }, } export const step3 = { name: 'tutorial.step3', after: configpart, - draft: ({ - Point, - points, - Path, - paths, - measurements, - options, - part, - }) => { - + draft: ({ Point, points, Path, paths, measurements, options, part }) => { let tweak = 1 let target = (measurements.head * options.neckRatio) / 4 let delta @@ -122,19 +106,13 @@ export const step3 = { } while (Math.abs(delta) > 1) return part - } + }, } export const step4 = { name: 'tutorial.step4', from: step3, - draft: ({ - points, - Path, - paths, - part, - }) => { - + draft: ({ points, Path, paths, part }) => { points.rightCp2 = points.rightCp1.flipY() points.bottomCp1 = points.bottomCp2.flipX() @@ -155,6 +133,5 @@ export const step4 = { .close() return part - } + }, } - diff --git a/designs/tutorial/src/step5-8.mjs b/designs/tutorial/src/step5-8.mjs index 23cd5726b10..18926631d00 100644 --- a/designs/tutorial/src/step5-8.mjs +++ b/designs/tutorial/src/step5-8.mjs @@ -3,16 +3,7 @@ import { step4 } from './step1-4.mjs' export const step5 = { name: 'tutorial.step5', from: step4, - draft: ({ - Point, - points, - Path, - paths, - measurements, - options, - part, - }) => { - + draft: ({ Point, points, Path, paths, measurements, options, part }) => { const width = measurements.head * options.widthRatio const length = measurements.head * options.lengthRatio @@ -30,20 +21,13 @@ export const step5 = { .close() return part - } + }, } export const step6 = { name: 'tutorial.step6', from: step5, - draft: ({ - Point, - points, - Path, - paths, - part, - }) => { - + draft: ({ Point, points, Path, paths, part }) => { points.edgeLeft = new Point(points.topLeft.x, points.left.y) points.edgeRight = new Point(points.topRight.x, points.right.y) points.edgeTop = new Point(0, points.topLeft.y) @@ -63,19 +47,13 @@ export const step6 = { .close() return part - } + }, } export const step7 = { name: 'tutorial.step7', from: step6, - draft: ({ - Point, - points, - macro, - part, - }) => { - + draft: ({ Point, points, macro, part }) => { const strap = points.edgeTop.dy(points.top) points.tipRight = points.edgeTop.translate(strap / 2, strap / 2) @@ -98,20 +76,13 @@ export const step7 = { }) return part - } + }, } export const step8 = { name: 'tutorial.step8', from: step7, - draft: ({ - points, - Path, - paths, - macro, - part, - }) => { - + draft: ({ points, Path, paths, macro, part }) => { const rotateThese = [ 'edgeTopLeftCp', 'edgeTop', @@ -160,6 +131,5 @@ export const step8 = { .close() return part - } + }, } - diff --git a/designs/tutorial/src/step9-11.mjs b/designs/tutorial/src/step9-11.mjs index 5b2ae8c1bbd..e5cc05629b4 100644 --- a/designs/tutorial/src/step9-11.mjs +++ b/designs/tutorial/src/step9-11.mjs @@ -3,13 +3,7 @@ import { step8 } from './step5-8.mjs' export const step9 = { name: 'tutorial.step9', from: step8, - draft: ({ - points, - Path, - paths, - part, - }) => { - + draft: ({ points, Path, paths, part }) => { points.edgeTopRightCp = points.edgeTopLeftCp.flipX() points.topCp1 = points.topCp2.flipX() points.tipLeftTopStart = points.tipRightTopStart.flipX() @@ -44,20 +38,13 @@ export const step9 = { delete paths.rect return part - } + }, } export const step10 = { name: 'tutorial.step10', from: step9, - draft: ({ - points, - Path, - paths, - macro, - part, - }) => { - + draft: ({ points, Path, paths, macro, part }) => { macro('round', { from: points.topLeft, to: points.bottomRight, @@ -95,23 +82,13 @@ export const step10 = { .close() return part - } + }, } export const step11 = { name: 'tutorial.step11', from: step10, - draft: ({ - Point, - points, - paths, - macro, - complete, - snippets, - Snippet, - part, - }) => { - + draft: ({ Point, points, paths, macro, complete, snippets, Snippet, part }) => { // Complete? if (complete) { snippets.snapStud = new Snippet('snap-stud', points.snapLeft) @@ -138,6 +115,5 @@ export const step11 = { } return part - } + }, } - diff --git a/designs/ursula/src/back.mjs b/designs/ursula/src/back.mjs index 80e95ac2155..57e755673de 100644 --- a/designs/ursula/src/back.mjs +++ b/designs/ursula/src/back.mjs @@ -17,7 +17,6 @@ function ursulaBack({ macro, part, }) { - // Design pattern here // Create points diff --git a/designs/ursula/src/elastic.mjs b/designs/ursula/src/elastic.mjs index 692bdc12389..22f1cdd2aff 100644 --- a/designs/ursula/src/elastic.mjs +++ b/designs/ursula/src/elastic.mjs @@ -12,7 +12,6 @@ function ursulaElastic({ macro, part, }) { - // Stretch utility method store.set('elasticScale', utils.stretchToScale(options.elasticStretch)) diff --git a/designs/ursula/src/front.mjs b/designs/ursula/src/front.mjs index 95151e09065..57152e43d1f 100644 --- a/designs/ursula/src/front.mjs +++ b/designs/ursula/src/front.mjs @@ -17,7 +17,6 @@ function ursulaFront({ macro, part, }) { - // Stretch utility method store.set('xScale', utils.stretchToScale(options.fabricStretch)) @@ -217,6 +216,6 @@ export const front = { frontDip: { pct: 5.0, min: -5, max: 15, menu: 'style' }, taperToGusset: { pct: 70, min: 5, max: 100, menu: 'style' }, }, - plugins: [ pluginBundle ], + plugins: [pluginBundle], draft: ursulaFront, } diff --git a/designs/ursula/src/gusset.mjs b/designs/ursula/src/gusset.mjs index c33f3869c7c..6a23601efe3 100644 --- a/designs/ursula/src/gusset.mjs +++ b/designs/ursula/src/gusset.mjs @@ -14,7 +14,6 @@ function ursulaGusset({ macro, part, }) { - // Create points points.frontGussetLeft = new Point(store.get('frontGussetLeft').x, 0) points.backGussetLeft = new Point( diff --git a/designs/wahid/src/back.mjs b/designs/wahid/src/back.mjs index 87ad04c5c8d..2483f8c394d 100644 --- a/designs/wahid/src/back.mjs +++ b/designs/wahid/src/back.mjs @@ -16,7 +16,6 @@ function wahidBack({ snippets, part, }) { - // Cleanup from Brian for (let i of Object.keys(paths)) delete paths[i] delete snippets.armholePitchNotch diff --git a/designs/wahid/src/front.mjs b/designs/wahid/src/front.mjs index 544f70d07de..5d8b0fdf138 100644 --- a/designs/wahid/src/front.mjs +++ b/designs/wahid/src/front.mjs @@ -35,7 +35,6 @@ function wahidFront({ store, part, }) { - // Cleanup from Brian for (let i of Object.keys(paths)) delete paths[i] delete snippets.armholePitchNotch diff --git a/designs/wahid/src/frontfacing.mjs b/designs/wahid/src/frontfacing.mjs index abe31374acb..50c3350c031 100644 --- a/designs/wahid/src/frontfacing.mjs +++ b/designs/wahid/src/frontfacing.mjs @@ -13,7 +13,6 @@ function wahidFrontFacing({ sa, part, }) { - // Cleanup from front part for (let i of Object.keys(paths).filter((name) => name !== 'grainline')) delete paths[i] for (let i of Object.keys(snippets)) delete snippets[i] diff --git a/designs/wahid/src/frontlining.mjs b/designs/wahid/src/frontlining.mjs index c6580b19753..a36a8285675 100644 --- a/designs/wahid/src/frontlining.mjs +++ b/designs/wahid/src/frontlining.mjs @@ -13,7 +13,6 @@ function wahidFrontLining({ sa, part, }) { - // Cleanup from Brian for (let i of Object.keys(paths)) delete paths[i] for (let i of Object.keys(snippets)) delete snippets[i] diff --git a/designs/wahid/src/pocketbag.mjs b/designs/wahid/src/pocketbag.mjs index 12fa4b7700d..cd17afeee0a 100644 --- a/designs/wahid/src/pocketbag.mjs +++ b/designs/wahid/src/pocketbag.mjs @@ -13,7 +13,6 @@ function wahidPocketbag({ store, part, }) { - let pw = measurements.hips * options.pocketWidth // Pocket width let ph = store.get('pocketBagLength') // Pocket height points.topLeft = new Point(0, 0) diff --git a/designs/wahid/src/pocketfacing.mjs b/designs/wahid/src/pocketfacing.mjs index 1228a022b3e..4d4eda64245 100644 --- a/designs/wahid/src/pocketfacing.mjs +++ b/designs/wahid/src/pocketfacing.mjs @@ -13,7 +13,6 @@ function wahidPocketFacing({ store, part, }) { - const pw = measurements.hips * options.pocketWidth // Pocket width const pwh = pw * options.weltHeight // Pocket welt height const ph = store.get('pocketBagLength') + pwh // Pocket height diff --git a/designs/wahid/src/pocketinterfacing.mjs b/designs/wahid/src/pocketinterfacing.mjs index 4f9ccb11aea..d2bb0a61c9b 100644 --- a/designs/wahid/src/pocketinterfacing.mjs +++ b/designs/wahid/src/pocketinterfacing.mjs @@ -12,7 +12,6 @@ function wahidPocketInterfacing({ paperless, part, }) { - const pw = measurements.hips * options.pocketWidth // Pocket width const pwh = pw * options.weltHeight // Pocket welt height points.topLeft = new Point(0, 0) diff --git a/designs/wahid/src/pocketwelt.mjs b/designs/wahid/src/pocketwelt.mjs index 0858ca38d48..2802861dd46 100644 --- a/designs/wahid/src/pocketwelt.mjs +++ b/designs/wahid/src/pocketwelt.mjs @@ -12,7 +12,6 @@ function wahidPocketWelt({ paperless, part, }) { - const pw = measurements.hips * options.pocketWidth // Pocket width const pwh = pw * options.weltHeight // Pocket welt height points.topLeft = new Point(0, 0) diff --git a/designs/walburga/src/back.mjs b/designs/walburga/src/back.mjs index 7898324a1a0..3f192cd8d11 100644 --- a/designs/walburga/src/back.mjs +++ b/designs/walburga/src/back.mjs @@ -1,14 +1,6 @@ import { base } from './base.mjs' -function walburgaBack({ - points, - macro, - complete, - snippets, - Snippet, - part, -}) { - +function walburgaBack({ points, macro, complete, snippets, Snippet, part }) { // Complete? if (complete) { // logo & title diff --git a/designs/walburga/src/base.mjs b/designs/walburga/src/base.mjs index 3294f1af65b..76602909c63 100644 --- a/designs/walburga/src/base.mjs +++ b/designs/walburga/src/base.mjs @@ -17,7 +17,6 @@ function walburgaBase({ utils, part, }) { - // define some variables const hem_pos = options.length === 'toKnee' diff --git a/designs/walburga/src/front.mjs b/designs/walburga/src/front.mjs index b867ae35966..6f85c6d718b 100644 --- a/designs/walburga/src/front.mjs +++ b/designs/walburga/src/front.mjs @@ -16,7 +16,6 @@ function walburgaFront({ utils, part, }) { - const head = store.get('hhead') * 2 const goldenRatio = store.get('goldenRatio') const ratio = goldenRatio * options.neckoRatio diff --git a/designs/waralee/src/backpocket.mjs b/designs/waralee/src/backpocket.mjs index 040742d3de6..fc9b926ce2a 100644 --- a/designs/waralee/src/backpocket.mjs +++ b/designs/waralee/src/backpocket.mjs @@ -15,7 +15,6 @@ function waraleeBackPocket({ sa, part, }) { - if (false == options.backPocket) { return part } diff --git a/designs/waralee/src/cutout.mjs b/designs/waralee/src/cutout.mjs index 14120c94657..afe2906a1a6 100644 --- a/designs/waralee/src/cutout.mjs +++ b/designs/waralee/src/cutout.mjs @@ -13,7 +13,6 @@ function waraleeCutout({ macro, part, }) { - let separateWaistband = options.separateWaistband if ('waistband' == options.frontPocketStyle) { separateWaistband = true diff --git a/designs/waralee/src/facings.mjs b/designs/waralee/src/facings.mjs index c92269a6e65..fc322ceb76a 100644 --- a/designs/waralee/src/facings.mjs +++ b/designs/waralee/src/facings.mjs @@ -15,7 +15,6 @@ function waraleeFacings({ sa, part, }) { - let frontPocketSize = options.frontPocketSize * measurements.crotchDepth /*- measurements.waistToHips*/ let backPocketSize = diff --git a/designs/waralee/src/mini.mjs b/designs/waralee/src/mini.mjs index 3489c3b933f..bb959c1671a 100644 --- a/designs/waralee/src/mini.mjs +++ b/designs/waralee/src/mini.mjs @@ -4,18 +4,7 @@ import { pantsProto } from './pantsproto.mjs' // To keep you from printing it completely, you could print this part in paperless mode // and only have a single sheet with all the dimensions on it. -function waraleeMini({ - options, - Path, - points, - paths, - complete, - sa, - macro, - store, - part, -}) { - +function waraleeMini({ options, Path, points, paths, complete, sa, macro, store, part }) { let mini = options.minimizer let separateWaistband = options.separateWaistband if ('waistband' == options.frontPocketStyle) { diff --git a/designs/waralee/src/pants.mjs b/designs/waralee/src/pants.mjs index 864e8e24aa8..4880f855322 100644 --- a/designs/waralee/src/pants.mjs +++ b/designs/waralee/src/pants.mjs @@ -14,7 +14,6 @@ function waraleePants({ store, part, }) { - let separateWaistband = options.separateWaistband if ('waistband' == options.frontPocketStyle) { separateWaistband = true diff --git a/designs/waralee/src/pantsproto.mjs b/designs/waralee/src/pantsproto.mjs index 96fd58ba2bf..3389ceed47d 100644 --- a/designs/waralee/src/pantsproto.mjs +++ b/designs/waralee/src/pantsproto.mjs @@ -1,17 +1,7 @@ import { pluginBundle } from '@freesewing/plugin-bundle' import * as options from './options.mjs' -function waraleePantsProto({ - options, - measurements, - Point, - Path, - points, - paths, - store, - part, -}) { - +function waraleePantsProto({ options, measurements, Point, Path, points, paths, store, part }) { let seatDepth = measurements.crotchDepth /* - measurements.waistToHips */ * (1 + options.waistRaise) * diff --git a/designs/waralee/src/pocket.mjs b/designs/waralee/src/pocket.mjs index cd00dd15ca4..a86b0ebc926 100644 --- a/designs/waralee/src/pocket.mjs +++ b/designs/waralee/src/pocket.mjs @@ -15,7 +15,6 @@ function waraleePocket({ macro, part, }) { - if (false == options.frontPocket) { return part } diff --git a/designs/waralee/src/waistband.mjs b/designs/waralee/src/waistband.mjs index 97f4c5816e7..c53998b68c3 100644 --- a/designs/waralee/src/waistband.mjs +++ b/designs/waralee/src/waistband.mjs @@ -1,22 +1,24 @@ import { pantsProto } from './pantsproto.mjs' -function waraleeWaistband(type, { - options, - measurements, - Point, - Path, - points, - paths, - Snippet, - snippets, - complete, - paperless, - macro, - sa, - store, - part, -}) { - +function waraleeWaistband( + type, + { + options, + measurements, + Point, + Path, + points, + paths, + Snippet, + snippets, + complete, + paperless, + macro, + sa, + store, + part, + } +) { const WidthReduction = 6 let waistBand = store.get('waistBand') let waistBandLengthFront = points.fWaistSideHem.dist(points.fWaistFrontOverlapHem) diff --git a/designs/yuri/src/back.mjs b/designs/yuri/src/back.mjs index 38eddff5de3..8008a9d0f57 100644 --- a/designs/yuri/src/back.mjs +++ b/designs/yuri/src/back.mjs @@ -15,7 +15,6 @@ function yuriBack({ measurements, part, }) { - // Clear paths from Brian for (const i in paths) { if (['backArmhole', 'backCollar'].indexOf(i) === -1) delete paths[i] diff --git a/designs/yuri/src/front.mjs b/designs/yuri/src/front.mjs index d526fd14284..b8bb1649e17 100644 --- a/designs/yuri/src/front.mjs +++ b/designs/yuri/src/front.mjs @@ -17,7 +17,6 @@ function yuriFront({ Snippet, part, }) { - // Clear paths from Brian for (const i in paths) { if (['frontArmhole', 'frontCollar'].indexOf(i) === -1) delete paths[i] diff --git a/designs/yuri/src/gusset.mjs b/designs/yuri/src/gusset.mjs index 20a6c14bc3a..2e833038604 100644 --- a/designs/yuri/src/gusset.mjs +++ b/designs/yuri/src/gusset.mjs @@ -14,7 +14,6 @@ function yuriGusset({ store, part, }) { - const w = store.get('gussetLength') points.top = new Point(0, 0) points.bottom = new Point(0, w) diff --git a/designs/yuri/src/hoodcenter.mjs b/designs/yuri/src/hoodcenter.mjs index e0593460896..4c9051525fb 100644 --- a/designs/yuri/src/hoodcenter.mjs +++ b/designs/yuri/src/hoodcenter.mjs @@ -13,7 +13,6 @@ function yuriHoodCenter({ units, part, }) { - const width = store.get('hoodCenterWidth') const length = complete ? width * 2.5 : store.get('hoodCenterLength') points.topLeft = new Point(0, 0) diff --git a/designs/yuri/src/hoodside.mjs b/designs/yuri/src/hoodside.mjs index 07773132a74..76f24256c68 100644 --- a/designs/yuri/src/hoodside.mjs +++ b/designs/yuri/src/hoodside.mjs @@ -16,7 +16,6 @@ function yuriHoodSide({ macro, part, }) { - const neckOpening = store.get('frontNeckSeamLength') + store.get('backNeckSeamLength') const hoodOpening = measurements.head const neckCutoutDelta = store.get('neckCutoutFront') - store.get('neckCutoutBack') diff --git a/designs/yuri/src/sleeve.mjs b/designs/yuri/src/sleeve.mjs index 14a3d1d7a3e..0264a1181d5 100644 --- a/designs/yuri/src/sleeve.mjs +++ b/designs/yuri/src/sleeve.mjs @@ -1,17 +1,6 @@ import { sleeve as brianSleeve } from '@freesewing/brian' -function yuriSleeve({ - Point, - Path, - points, - paths, - complete, - sa, - paperless, - macro, - part, -}) { - +function yuriSleeve({ Point, Path, points, paths, complete, sa, paperless, macro, part }) { // Clear paths from Brian, but keep sleevecap for (let p of Object.keys(paths)) { if (p !== 'sleevecap') delete paths[p] diff --git a/package.json b/package.json index 6f7d45c219b..4f30048d92c 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "?": "node scripts/help.mjs", "tips": "node scripts/help.mjs", "lab": "cd sites/lab && yarn start", - "kickstart": "npx lerna bootstrap && yarn buildall && yarn tips", + "kickstart": "npx lerna bootstrap && yarn buildall && yarn prepare && yarn tips", "cleanall": "lerna run clean", "test": "lerna run test", "prettier": "npx prettier --write 'packages/**/src/*.mjs' 'packages/**/src/*.js' 'packages/i18n/src/locales/**/*.*' 'packages/**/tests/*.mjs'", @@ -24,7 +24,10 @@ "buildall": "lerna run cibuild_step0 && lerna run cibuild_step1 && lerna run cibuild_step2 && lerna run cibuild_step3 && lerna run cibuild_step4 && lerna run cibuild_step5 && lerna run cibuild_step6 && lerna run cibuild_step7", "build": "yarn buildall", "testall": "node scripts/testall.js", - "lint": "lerna run lint", + "lint": "lerna run lint -- ", + "qa": "yarn qa:prettier && yarn qa:lint", + "qa:prettier": "npx prettier", + "qa:lint": "npx eslint", "release": "lerna exec --no-bail -- npm publish", "postrelease": "git add . && git commit -m ':bookmark: v$npm_package_version' && git tag -a v$npm_package_version -m ':bookmark: FreeSewing v$npm_package_version'", "ship": "lerna exec --no-bail -- npm publish", @@ -35,7 +38,8 @@ "famgen": "all-contributors generate", "checkdocs": "remark markdown --quiet --frail", "strapi:translate": "node scripts/strapi-en-to-other.mjs", - "fixdocs": "remark markdown --quiet --frail --output" + "fixdocs": "remark markdown --quiet --frail --output", + "prepare": "husky install" }, "repository": { "type": "git", @@ -45,10 +49,11 @@ "url": "https://github.com/freesewing/freesewing/issues" }, "prettier": "@freesewing/prettier-config", - "husky": { - "hooks": { - "pre-commit": "pretty-quick --staged" - } + "lint-staged": { + "*": [ + "npx prettier --write", + "npx eslint" + ] }, "devDependencies": { "@commitlint/cli": "^17.0.2", @@ -67,16 +72,18 @@ "cross-env": "^7.0.2", "esbuild": "^0.15.3", "esbuild-plugin-yaml": "^0.0.1", + "eslint": "^8.23.1", "eslint-plugin-yaml": "^0.5.0", "esm": "^3.2.25", "handlebars": "^4.7.7", "husky": "^8.0.1", "js-yaml": "^4.0.0", "lerna": "^5.1.4", + "lint-staged": "^13.0.3", "mocha": "^10.0.0", "mustache": "^4.0.1", "nyc": "^15.1.0", - "prettier": "^2.3.0", + "prettier": "^2.7.1", "pretty-quick": "^3.0.0", "prop-types": "^15.7.2", "react": "^17.0.2", diff --git a/packages/core/tests/pattern-draft.test.mjs b/packages/core/tests/pattern-draft.test.mjs index 8d4850f6444..2005d901098 100644 --- a/packages/core/tests/pattern-draft.test.mjs +++ b/packages/core/tests/pattern-draft.test.mjs @@ -5,7 +5,6 @@ const expect = chai.expect describe('Pattern', () => { describe('Pattern.draft()', () => { - it('Pattern.draft() should draft according to settings', () => { let count = 0 const back = { diff --git a/packages/i18n/package.json b/packages/i18n/package.json index 2b764058c6c..c1a45709827 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -31,13 +31,12 @@ "clean": "rimraf dist", "mbuild": "NO_MINIFY=1 node build.mjs", "symlink": "mkdir -p ./node_modules/@freesewing && cd ./node_modules/@freesewing && ln -s -f ../../../* . && cd -", - "test": "npx mocha tests/*.test.mjs", + "test": "echo \"i18n: No tests configured. Perhaps you'd like to do this?\" && exit 0", "vbuild": "VERBOSE=1 node build.mjs", "lab": "cd ../../sites/lab && yarn start", "tips": "node ../../scripts/help.mjs", "lint": "npx eslint 'src/**' 'tests/*.mjs'", "prebuild": "node scripts/prebuilder.mjs", - "testci": "npx mocha tests/*.test.mjs --reporter ../../tests/reporters/terse.js", "precibuild_step7": "node scripts/prebuilder.mjs", "cibuild_step7": "node build.mjs" }, diff --git a/packages/i18n/tests/i18n.test.mjs b/packages/i18n/tests/i18n.test.mjs index f86a03585a7..22207019b47 100644 --- a/packages/i18n/tests/i18n.test.mjs +++ b/packages/i18n/tests/i18n.test.mjs @@ -1,5 +1,5 @@ import chai from 'chai' -import { strings as i18n } from './dist/index.mjs' +import * as i18n from '../prebuild/strings.js' const expect = chai.expect @@ -27,13 +27,12 @@ const languages = [ ] function checkTranslations(from, to) { - const originals = Object.keys(from.strings) const translated = to.strings - for (let string of originals) { + for (const string in from.strings) { if (typeof translated[string] === 'undefined') { console.log(`String ${string} in ${from.name} is not available in ${to.name}`) - expect(typeof translated[string]).to.equal('string') } + expect(typeof translated[string]).to.equal('string') } } diff --git a/plugins/plugin-banner/tests/plugin.test.mjs b/plugins/plugin-banner/tests/plugin.test.mjs index 732093f8dc9..c3385bdeff9 100644 --- a/plugins/plugin-banner/tests/plugin.test.mjs +++ b/plugins/plugin-banner/tests/plugin.test.mjs @@ -1,6 +1,6 @@ import chai from 'chai' import { Design } from '@freesewing/core' -import { bannerPlugin } from './dist/index.mjs' +import { bannerPlugin } from '../src/index.mjs' const expect = chai.expect diff --git a/plugins/plugin-bundle/src/index.mjs b/plugins/plugin-bundle/src/index.mjs index d383f1f1ab4..663bf22d309 100644 --- a/plugins/plugin-bundle/src/index.mjs +++ b/plugins/plugin-bundle/src/index.mjs @@ -1,15 +1,15 @@ -import { bannerPlugin } from '../../plugin-banner/src/index.mjs' -import { bartackPlugin } from '../../plugin-bartack/src/index.mjs' -import { buttonsPlugin } from '../../plugin-buttons/src/index.mjs' +import { bannerPlugin } from '../../plugin-banner/src/index.mjs' +import { bartackPlugin } from '../../plugin-bartack/src/index.mjs' +import { buttonsPlugin } from '../../plugin-buttons/src/index.mjs' import { cutonfoldPlugin } from '../../plugin-cutonfold/src/index.mjs' import { dimensionPlugin } from '../../plugin-dimension/src/index.mjs' import { grainlinePlugin } from '../../plugin-grainline/src/index.mjs' -import { logoPlugin } from '../../plugin-logo/src/index.mjs' -import { mirrorPlugin } from '../../plugin-mirror/src/index.mjs' -import { notchesPlugin } from '../../plugin-notches/src/index.mjs' -import { titlePlugin } from '../../plugin-title/src/index.mjs' -import { scaleboxPlugin } from '../../plugin-scalebox/src/index.mjs' -import { roundPlugin } from '../../plugin-round/src/index.mjs' +import { logoPlugin } from '../../plugin-logo/src/index.mjs' +import { mirrorPlugin } from '../../plugin-mirror/src/index.mjs' +import { notchesPlugin } from '../../plugin-notches/src/index.mjs' +import { titlePlugin } from '../../plugin-title/src/index.mjs' +import { scaleboxPlugin } from '../../plugin-scalebox/src/index.mjs' +import { roundPlugin } from '../../plugin-round/src/index.mjs' import { sprinklePlugin } from '../../plugin-sprinkle/src/index.mjs' import { measurementsPlugin } from '../../plugin-measurements/src/index.mjs' import { name, version } from '../data.mjs' @@ -66,4 +66,3 @@ export const plugin = { // More specifically named exports export const bundlePlugin = plugin export const pluginBundle = plugin - diff --git a/plugins/plugin-bundle/tests/plugin.test.mjs b/plugins/plugin-bundle/tests/plugin.test.mjs index c30064b22c8..369d11c19d8 100644 --- a/plugins/plugin-bundle/tests/plugin.test.mjs +++ b/plugins/plugin-bundle/tests/plugin.test.mjs @@ -3,7 +3,7 @@ import chai from 'chai' const expect = chai.expect describe('Round Plugin Tests', () => { - it("FIXME: No plugin tests configured", () => { + it('FIXME: No plugin tests configured', () => { expect(1).to.equal(1) }) }) diff --git a/plugins/plugin-bust/tests/plugin.test.mjs b/plugins/plugin-bust/tests/plugin.test.mjs index 6179ab164a6..b143f303049 100644 --- a/plugins/plugin-bust/tests/plugin.test.mjs +++ b/plugins/plugin-bust/tests/plugin.test.mjs @@ -1,6 +1,6 @@ import chai from 'chai' import { Design } from '@freesewing/core' -import { plugin } from './dist/index.mjs' +import { plugin } from '../src/index.mjs' const expect = chai.expect diff --git a/plugins/plugin-buttons/tests/plugin.test.mjs b/plugins/plugin-buttons/tests/plugin.test.mjs index 84c241ba70d..84a0306d0dd 100644 --- a/plugins/plugin-buttons/tests/plugin.test.mjs +++ b/plugins/plugin-buttons/tests/plugin.test.mjs @@ -1,6 +1,6 @@ import chai from 'chai' import { Design } from '@freesewing/core' -import { plugin } from './dist/index.mjs' +import { plugin } from '../src/index.mjs' const expect = chai.expect diff --git a/plugins/plugin-cutlist/tests/plugin.test.mjs b/plugins/plugin-cutlist/tests/plugin.test.mjs index fcee17d38e3..ed9a3aaeb9a 100644 --- a/plugins/plugin-cutlist/tests/plugin.test.mjs +++ b/plugins/plugin-cutlist/tests/plugin.test.mjs @@ -1,6 +1,6 @@ import chai from 'chai' import { Design } from '@freesewing/core' -import { plugin } from '../dist/index.mjs' +import { plugin } from '../src/index.mjs' const expect = chai.expect diff --git a/plugins/plugin-cutonfold/tests/plugin.test.mjs b/plugins/plugin-cutonfold/tests/plugin.test.mjs index 11daad05eb2..b8502c1d7a2 100644 --- a/plugins/plugin-cutonfold/tests/plugin.test.mjs +++ b/plugins/plugin-cutonfold/tests/plugin.test.mjs @@ -1,6 +1,6 @@ import chai from 'chai' import { Design, round } from '@freesewing/core' -import { plugin } from './dist/index.mjs' +import { plugin } from '../src/index.mjs' const expect = chai.expect diff --git a/plugins/plugin-dimension/tests/plugin.test.mjs b/plugins/plugin-dimension/tests/plugin.test.mjs index a43013ce762..3553909c138 100644 --- a/plugins/plugin-dimension/tests/plugin.test.mjs +++ b/plugins/plugin-dimension/tests/plugin.test.mjs @@ -1,6 +1,6 @@ import chai from 'chai' import { Design, round } from '@freesewing/core' -import { plugin } from './dist/index.mjs' +import { plugin } from '../src/index.mjs' const expect = chai.expect diff --git a/plugins/plugin-flip/tests/plugin.test.mjs b/plugins/plugin-flip/tests/plugin.test.mjs index fcba5409423..3e8963f242a 100644 --- a/plugins/plugin-flip/tests/plugin.test.mjs +++ b/plugins/plugin-flip/tests/plugin.test.mjs @@ -1,6 +1,6 @@ import chai from 'chai' import { Design } from '@freesewing/core' -import { plugin } from './dist/index.mjs' +import { plugin } from '../src/index.mjs' const expect = chai.expect diff --git a/plugins/plugin-logo/src/index.mjs b/plugins/plugin-logo/src/index.mjs index 572f6a80049..8c96eb26b04 100644 --- a/plugins/plugin-logo/src/index.mjs +++ b/plugins/plugin-logo/src/index.mjs @@ -1,6 +1,7 @@ import { name, version } from '../data.mjs' -const logo = '' +const logo = + '' export const plugin = { name, diff --git a/plugins/plugin-logo/tests/plugin.test.mjs b/plugins/plugin-logo/tests/plugin.test.mjs index 89a54129c73..b4b01f5c647 100644 --- a/plugins/plugin-logo/tests/plugin.test.mjs +++ b/plugins/plugin-logo/tests/plugin.test.mjs @@ -1,6 +1,6 @@ import chai from 'chai' import { Design } from '@freesewing/core' -import { plugin } from '../dist/index.mjs' +import { plugin } from '../src/index.mjs' const expect = chai.expect diff --git a/plugins/plugin-measurements/tests/plugin.test.mjs b/plugins/plugin-measurements/tests/plugin.test.mjs index 299b6e70243..2d558136917 100644 --- a/plugins/plugin-measurements/tests/plugin.test.mjs +++ b/plugins/plugin-measurements/tests/plugin.test.mjs @@ -1,6 +1,6 @@ import chai from 'chai' import { Design } from '@freesewing/core' -import { plugin } from './dist/index.mjs' +import { plugin } from '../src/index.mjs' const expect = chai.expect diff --git a/plugins/plugin-mirror/tests/plugin.test.mjs b/plugins/plugin-mirror/tests/plugin.test.mjs index 1b158d30ca3..1a6b755410a 100644 --- a/plugins/plugin-mirror/tests/plugin.test.mjs +++ b/plugins/plugin-mirror/tests/plugin.test.mjs @@ -1,6 +1,6 @@ import chai from 'chai' import { Design } from '@freesewing/core' -import { plugin } from '../dist/index.mjs' +import { plugin } from '../src/index.mjs' const expect = chai.expect diff --git a/plugins/plugin-notches/tests/plugin.test.mjs b/plugins/plugin-notches/tests/plugin.test.mjs index bb6ec6f768a..2a6c27d1bde 100644 --- a/plugins/plugin-notches/tests/plugin.test.mjs +++ b/plugins/plugin-notches/tests/plugin.test.mjs @@ -1,6 +1,6 @@ import chai from 'chai' import { Design } from '@freesewing/core' -import { plugin } from '../dist/index.mjs' +import { plugin } from '../src/index.mjs' const expect = chai.expect diff --git a/plugins/plugin-round/src/index.mjs b/plugins/plugin-round/src/index.mjs index ed56c24eb7b..83053a05431 100644 --- a/plugins/plugin-round/src/index.mjs +++ b/plugins/plugin-round/src/index.mjs @@ -41,4 +41,3 @@ export const plugin = { // More specifically named exports export const roundPlugin = plugin export const pluginRound = plugin - diff --git a/plugins/plugin-round/tests/plugin.test.mjs b/plugins/plugin-round/tests/plugin.test.mjs index c30064b22c8..369d11c19d8 100644 --- a/plugins/plugin-round/tests/plugin.test.mjs +++ b/plugins/plugin-round/tests/plugin.test.mjs @@ -3,7 +3,7 @@ import chai from 'chai' const expect = chai.expect describe('Round Plugin Tests', () => { - it("FIXME: No plugin tests configured", () => { + it('FIXME: No plugin tests configured', () => { expect(1).to.equal(1) }) }) diff --git a/plugins/plugin-scalebox/tests/plugin.test.mjs b/plugins/plugin-scalebox/tests/plugin.test.mjs index 3e8d4e7c730..1c77708efa4 100644 --- a/plugins/plugin-scalebox/tests/plugin.test.mjs +++ b/plugins/plugin-scalebox/tests/plugin.test.mjs @@ -1,6 +1,6 @@ import chai from 'chai' import { Design, round } from '@freesewing/core' -import { plugin } from '../dist/index.mjs' +import { plugin } from '../src/index.mjs' const expect = chai.expect diff --git a/plugins/plugin-sprinkle/tests/plugin.test.mjs b/plugins/plugin-sprinkle/tests/plugin.test.mjs index d8014524af6..8f7b2632fe6 100644 --- a/plugins/plugin-sprinkle/tests/plugin.test.mjs +++ b/plugins/plugin-sprinkle/tests/plugin.test.mjs @@ -1,6 +1,6 @@ import chai from 'chai' //import freesewing from '@freesewing/core' -//import plugin from '../dist/index.mjs' +//import { plugin } from '../src/index.mjs' const expect = chai.expect diff --git a/plugins/plugin-svgattr/src/index.mjs b/plugins/plugin-svgattr/src/index.mjs index c4074db30d4..5be3d2902eb 100644 --- a/plugins/plugin-svgattr/src/index.mjs +++ b/plugins/plugin-svgattr/src/index.mjs @@ -15,4 +15,3 @@ export const svgAttrPlugin = plugin export const svgattrPlugin = plugin export const pluginSvgAttr = plugin export const pluginSvgattr = plugin - diff --git a/plugins/plugin-svgattr/tests/plugin.test.mjs b/plugins/plugin-svgattr/tests/plugin.test.mjs index ea337fafa1d..55d3d85e1ab 100644 --- a/plugins/plugin-svgattr/tests/plugin.test.mjs +++ b/plugins/plugin-svgattr/tests/plugin.test.mjs @@ -1,9 +1,9 @@ import chai from 'chai' -const expect = chai.expect; +const expect = chai.expect describe('SVG Attributed Plugin Tests', () => { - it("FIXME: No plugin tests defined", () => { + it('FIXME: No plugin tests defined', () => { expect(1).to.equal(1) }) }) diff --git a/plugins/plugin-theme/tests/plugin.test.mjs b/plugins/plugin-theme/tests/plugin.test.mjs index cc5db4b6fbd..5dfdbe63148 100644 --- a/plugins/plugin-theme/tests/plugin.test.mjs +++ b/plugins/plugin-theme/tests/plugin.test.mjs @@ -1,6 +1,6 @@ import chai from 'chai' import { Design } from '@freesewing/core' -import { plugin } from '../dist/index.mjs' +import { plugin } from '../src/index.mjs' const expect = chai.expect diff --git a/plugins/plugin-versionfree-svg/src/index.mjs b/plugins/plugin-versionfree-svg/src/index.mjs index 7d06037c559..ccfcc67e68b 100644 --- a/plugins/plugin-versionfree-svg/src/index.mjs +++ b/plugins/plugin-versionfree-svg/src/index.mjs @@ -15,4 +15,3 @@ export const plugin = { // More specifically named exports export const versionfreeSvgPlugin = plugin export const pluginVersionfreeSvg = plugin - diff --git a/plugins/plugin-versionfree-svg/tests/plugin.test.mjs b/plugins/plugin-versionfree-svg/tests/plugin.test.mjs index a9aae599349..6a9d4171b95 100644 --- a/plugins/plugin-versionfree-svg/tests/plugin.test.mjs +++ b/plugins/plugin-versionfree-svg/tests/plugin.test.mjs @@ -1,6 +1,6 @@ import chai from 'chai' import { Design } from '@freesewing/core' -import { plugin } from '../dist/index.mjs' +import { plugin } from '../src/index.mjs' const expect = chai.expect diff --git a/sites/backend/src/cli/data.js b/sites/backend/src/cli/data.js index 9dc7d21c756..b0aa71e102b 100644 --- a/sites/backend/src/cli/data.js +++ b/sites/backend/src/cli/data.js @@ -1,4 +1,4 @@ -import { withBreasts, withoutBreasts } from '@freesewing/models'; +import { withBreasts, withoutBreasts } from '@freesewing/models' export default { users: [ @@ -10,15 +10,15 @@ export default { role: 'user', settings: { language: 'nl', - units: 'imperial' + units: 'imperial', }, patron: 2, consent: { profile: true, measurements: true, - openData: true + openData: true, }, - status: 'active' + status: 'active', }, { email: 'test@freesewing.org', @@ -28,15 +28,15 @@ export default { role: 'user', settings: { language: 'nl', - units: 'imperial' + units: 'imperial', }, patron: 4, consent: { profile: true, measurements: true, - openData: true + openData: true, }, - status: 'active' + status: 'active', }, { email: 'admin@freesewing.org', @@ -52,16 +52,16 @@ export default { patron: 8, settings: { language: 'en', - units: 'metric' + units: 'metric', }, consent: { profile: true, measurements: true, - openData: true + openData: true, }, newsletter: true, - status: 'active' - } + status: 'active', + }, ], people: [ { @@ -72,7 +72,7 @@ export default { breasts: false, units: 'metric', notes: 'This is an example person', - measurements: withoutBreasts.size42 + measurements: withoutBreasts.size42, }, { handle: 'persb', @@ -84,37 +84,37 @@ export default { notes: 'This is an example person', measurements: { ...withBreasts.size36, - doesNotExist: 234 - } + doesNotExist: 234, + }, }, ], patterns: [ { - handle: "recip", - name: "Example pattern", - notes: "These are the pattern notes", + handle: 'recip', + name: 'Example pattern', + notes: 'These are the pattern notes', data: { settings: { sa: 10, complete: true, paperless: false, - units: "imperial", + units: 'imperial', measurements: { biceps: 335, hpsToWaist: 520, chest: 1080, waistToHips: 145, neck: 420, - shoulderSlope: 13, + shoulderSlope: 13, shoulderToShoulder: 465, - hips: 990 - } + hips: 990, + }, }, - design: "aaron", + design: 'aaron', }, - created: "2019-08-14T09:47:27.163Z", + created: '2019-08-14T09:47:27.163Z', user: 'tuser', - person:"persa" - } - ] + person: 'persa', + }, + ], } diff --git a/sites/backend/src/cli/index.js b/sites/backend/src/cli/index.js index c70e88644a5..b5eceedbc50 100644 --- a/sites/backend/src/cli/index.js +++ b/sites/backend/src/cli/index.js @@ -20,7 +20,7 @@ verifyConfig(config, chalk) mongoose.Promise = global.Promise mongoose .connect(config.db.uri, { - useNewUrlParser: true + useNewUrlParser: true, }) .then(() => { console.log(chalk.green('Successfully connected to the database')) @@ -37,7 +37,7 @@ mongoose } }) }) - .catch(err => { + .catch((err) => { console.log(chalk.red('Could not connect to the database. Exiting now...'), err) process.exit() }) diff --git a/sites/backend/src/cli/lib.js b/sites/backend/src/cli/lib.js index 83222574381..67d21da982d 100644 --- a/sites/backend/src/cli/lib.js +++ b/sites/backend/src/cli/lib.js @@ -9,7 +9,11 @@ export const showHelp = () => { console.log() console.log(' ', chalk.bold.blue('npm run clear:users'), '👉 Truncate the users collection') console.log(' ', chalk.bold.blue('npm run clear:people'), '👉 Truncate the people collection') - console.log(' ', chalk.bold.blue('npm run clear:patterns'), '👉 Truncate the patterns collection') + console.log( + ' ', + chalk.bold.blue('npm run clear:patterns'), + '👉 Truncate the patterns collection' + ) console.log( ' ', chalk.bold.blue('npm run clear:confirmations'), @@ -26,33 +30,33 @@ export const showHelp = () => { } export const clearUsers = async () => { - await User.deleteMany().then(result => { - if (result.ok) console.log('🔥 Users deleted') - else console.log('🚨 Could not remove users', result) + await User.deleteMany().then((result) => { + if (result.ok) console.log('🔥 Users deleted') + else console.log('🚨 Could not remove users', result) }) } export const clearPeople = async () => { - await Person.deleteMany().then(result => { - if (result.ok) console.log('🔥 People removed') - else console.log('🚨 Could not remove people', result) + await Person.deleteMany().then((result) => { + if (result.ok) console.log('🔥 People removed') + else console.log('🚨 Could not remove people', result) }) } export const clearPatterns = async () => { - await Pattern.deleteMany().then(result => { - if (result.ok) console.log('🔥 Patterns deleted') - else console.log('🚨 Could not remove patterns', result) + await Pattern.deleteMany().then((result) => { + if (result.ok) console.log('🔥 Patterns deleted') + else console.log('🚨 Could not remove patterns', result) }) } export const clearConfirmations = async () => { - await Confirmation.deleteMany().then(result => { - if (result.ok) console.log('🔥 Confirmations deleted') - else console.log('🚨 Could not remove confirmations', result) + await Confirmation.deleteMany().then((result) => { + if (result.ok) console.log('🔥 Confirmations deleted') + else console.log('🚨 Could not remove confirmations', result) }) } export const clearNewsletterSubscribers = async () => { - await Newsletter.deleteMany().then(result => { - if (result.ok) console.log('🔥 Newsletter subscriptions deleted') - else console.log('🚨 Could not remove newsletter subscriptions', result) + await Newsletter.deleteMany().then((result) => { + if (result.ok) console.log('🔥 Newsletter subscriptions deleted') + else console.log('🚨 Could not remove newsletter subscriptions', result) }) } @@ -65,8 +69,8 @@ export const loadSampleData = async () => { ehash: ehash(sample.email), picture: sample.handle + '.svg', time: { - created: new Date() - } + created: new Date(), + }, }) user.createAvatar() promises.push(user.save()) @@ -83,7 +87,7 @@ export const loadSampleData = async () => { return Promise.all(promises) } -export const runTasks = options => { +export const runTasks = (options) => { let promises = [] if (options.clearAll || options.reboot || options.clearUsers) promises.push(clearUsers()) if (options.clearAll || options.reboot || options.clearPeople) promises.push(clearPeople()) diff --git a/sites/backend/src/cli/options.js b/sites/backend/src/cli/options.js index 24a8c85da74..8e5bbcde0b7 100644 --- a/sites/backend/src/cli/options.js +++ b/sites/backend/src/cli/options.js @@ -1,34 +1,34 @@ export default [ { name: 'clearUsers', - type: Boolean + type: Boolean, }, { name: 'clearModels', - type: Boolean + type: Boolean, }, { name: 'clearPatterns', - type: Boolean + type: Boolean, }, { name: 'clearConfirmations', - type: Boolean + type: Boolean, }, { name: 'clearNewsletterSubscribers', - type: Boolean + type: Boolean, }, { name: 'clearAll', - type: Boolean + type: Boolean, }, { name: 'reboot', - type: Boolean + type: Boolean, }, { name: 'help', - type: Boolean - } + type: Boolean, + }, ] diff --git a/sites/backend/src/controllers/admin.js b/sites/backend/src/controllers/admin.js index e0022e705d5..047be91bf87 100644 --- a/sites/backend/src/controllers/admin.js +++ b/sites/backend/src/controllers/admin.js @@ -5,8 +5,7 @@ import { ehash } from '../utils' function AdminController() {} - -AdminController.prototype.search = function(req, res) { +AdminController.prototype.search = function (req, res) { if (!req.user._id) return res.sendStatus(400) User.findById(req.user._id, (err, admin) => { if (err || admin === null) return res.sendStatus(400) @@ -16,26 +15,26 @@ AdminController.prototype.search = function(req, res) { { handle: { $regex: `.*${req.body.query}.*` } }, { username: { $regex: `.*${req.body.query}.*` } }, { ehash: ehash(req.body.query) }, - ] + ], }) - .sort('username') - .exec((err, users) => { - if (err) return res.sendStatus(400) - Person.find({ handle: { $regex: `.*${req.body.query}.*` } }) - .sort('handle') - .exec((err, people) => { + .sort('username') + .exec((err, users) => { if (err) return res.sendStatus(400) - if (users === null && people === null) return res.sendStatus(404) - return res.send({ - users: users.map(user => user.adminProfile()), - people: people.map(person => person.info()), - }) + Person.find({ handle: { $regex: `.*${req.body.query}.*` } }) + .sort('handle') + .exec((err, people) => { + if (err) return res.sendStatus(400) + if (users === null && people === null) return res.sendStatus(404) + return res.send({ + users: users.map((user) => user.adminProfile()), + people: people.map((person) => person.info()), + }) + }) }) - }) }) } -AdminController.prototype.setPatronStatus = function(req, res) { +AdminController.prototype.setPatronStatus = function (req, res) { if (!req.user._id) return res.sendStatus(400) User.findById(req.user._id, (err, admin) => { if (err || admin === null) return res.sendStatus(400) @@ -49,7 +48,7 @@ AdminController.prototype.setPatronStatus = function(req, res) { }) } -AdminController.prototype.setRole = function(req, res) { +AdminController.prototype.setRole = function (req, res) { if (!req.user._id) return res.sendStatus(400) User.findById(req.user._id, (err, admin) => { if (err || admin === null) return res.sendStatus(400) @@ -63,7 +62,7 @@ AdminController.prototype.setRole = function(req, res) { }) } -AdminController.prototype.unfreeze = function(req, res) { +AdminController.prototype.unfreeze = function (req, res) { if (!req.user._id) return res.sendStatus(400) User.findById(req.user._id, (err, admin) => { if (err || admin === null) return res.sendStatus(400) @@ -77,7 +76,7 @@ AdminController.prototype.unfreeze = function(req, res) { }) } -AdminController.prototype.impersonate = function(req, res) { +AdminController.prototype.impersonate = function (req, res) { if (!req.user._id) return res.sendStatus(400) User.findById(req.user._id, (err, admin) => { if (err || admin === null) return res.sendStatus(400) @@ -95,16 +94,14 @@ AdminController.prototype.impersonate = function(req, res) { Pattern.find({ user: user.handle }, (err, patternList) => { if (err) return res.sendStatus(400) for (let pattern of patternList) patterns[pattern.handle] = pattern - return user.updateLoginTime(() => - res.send({ account, people, patterns, token }) - ) + return user.updateLoginTime(() => res.send({ account, people, patterns, token })) }) }) }) }) } -AdminController.prototype.patronList = function(req, res) { +AdminController.prototype.patronList = function (req, res) { if (!req.user._id) return res.sendStatus(400) User.findById(req.user._id, (err, admin) => { if (err || admin === null) return res.sendStatus(400) @@ -116,16 +113,16 @@ AdminController.prototype.patronList = function(req, res) { }) } -AdminController.prototype.subscriberList = function(req, res) { +AdminController.prototype.subscriberList = function (req, res) { if (!req.user._id) return res.sendStatus(400) User.findById(req.user._id, (err, admin) => { if (err || admin === null) return res.sendStatus(400) if (admin.role !== 'admin') return res.sendStatus(403) - User.find({newsletter: true}, (err, subscribedUsers) => { + User.find({ newsletter: true }, (err, subscribedUsers) => { if (err) return res.sendStatus(500) - let subscribers = subscribedUsers.map(user => ({ + let subscribers = subscribedUsers.map((user) => ({ ehash: user.ehash, - email: user.email + email: user.email, })) Newsletter.find({}, (err, subs) => { if (err) return res.sendStatus(500) @@ -135,12 +132,12 @@ AdminController.prototype.subscriberList = function(req, res) { }) } -AdminController.prototype.stats = function(req, res) { +AdminController.prototype.stats = function (req, res) { if (!req.user._id) return res.sendStatus(400) User.findById(req.user._id, (err, admin) => { if (err || admin === null) return res.sendStatus(400) if (admin.role !== 'admin') return res.sendStatus(403) - User.find({ "consent.profile": true }, (err, users) => { + User.find({ 'consent.profile': true }, (err, users) => { if (err) return res.sendStatus(500) Person.find({}, (err, people) => { if (err) return res.sendStatus(500) @@ -157,21 +154,21 @@ AdminController.prototype.stats = function(req, res) { } function saveAndReturnAccount(res, user) { - user.save(function(err, updatedUser) { + user.save(function (err, updatedUser) { if (err) { return res.sendStatus(500) } else return res.send({ account: updatedUser.account() }) }) } -const getToken = account => { +const getToken = (account) => { return jwt.sign( { _id: account._id, handle: account.handle, role: account.role, aud: config.jwt.audience, - iss: config.jwt.issuer + iss: config.jwt.issuer, }, config.jwt.secretOrKey ) diff --git a/sites/backend/src/controllers/auth.js b/sites/backend/src/controllers/auth.js index ff16bff8fe7..79c7dcbff19 100644 --- a/sites/backend/src/controllers/auth.js +++ b/sites/backend/src/controllers/auth.js @@ -6,7 +6,7 @@ import { getHandle, createHandle, imageType, - saveAvatarFromBase64 + saveAvatarFromBase64, } from '../utils' import config from '../config' import queryString from 'query-string' @@ -19,22 +19,22 @@ import axios from 'axios' function AuthController() {} -AuthController.prototype.initOauth = function(req, res) { +AuthController.prototype.initOauth = function (req, res) { if (!req.body) return res.sendStatus(400) let confirmation = new Confirmation({ type: 'oauth', data: { language: req.body.language, - provider: req.body.provider - } + provider: req.body.provider, + }, }) - confirmation.save(function(err) { + confirmation.save(function (err) { if (err) return res.sendStatus(500) return res.send({ state: confirmation._id }) }) } -AuthController.prototype.loginOauth = function(req, res) { +AuthController.prototype.loginOauth = function (req, res) { if (!req.body) return res.sendStatus(400) Confirmation.findById(req.body.confirmation, (err, confirmation) => { if (err) return res.sendStatus(400) @@ -57,7 +57,7 @@ AuthController.prototype.loginOauth = function(req, res) { Pattern.find({ user: user.handle }, (err, patternList) => { if (err) return res.sendStatus(400) for (let pattern of patternList) patterns[pattern.handle] = pattern - confirmation.remove(err => { + confirmation.remove((err) => { if (err !== null) return res.sendStatus(500) user.updateLoginTime(() => res.send({ account, people, token, signup })) }) @@ -67,7 +67,7 @@ AuthController.prototype.loginOauth = function(req, res) { }) } -AuthController.prototype.providerCallback = function(req, res) { +AuthController.prototype.providerCallback = function (req, res) { let language, token, email, avatarUri, username let provider = req.params.provider let conf = config.oauth[provider] @@ -89,19 +89,19 @@ AuthController.prototype.providerCallback = function(req, res) { code: req.query.code, accept: 'json', grant_type: 'authorization_code', - redirect_uri: config.api + '/oauth/callback/from/' + provider + redirect_uri: config.api + '/oauth/callback/from/' + provider, }) - .then(result => { + .then((result) => { if (result.status !== 200) return res.sendStatus(401) if (provider === 'github') token = queryString.parse(result.data).access_token else if (provider === 'google') token = result.data.access_token // Contact API for user info - const headers = token => ({ headers: { Authorization: 'Bearer ' + token } }) + const headers = (token) => ({ headers: { Authorization: 'Bearer ' + token } }) go.get(conf.dataUri, headers(token)) - .then(async result => { + .then(async (result) => { if (provider === 'github') { - email = await getGithubEmail(result.data.email, go, conf.emailUri, headers(token)), - avatarUri = result.data.avatar_url + ;(email = await getGithubEmail(result.data.email, go, conf.emailUri, headers(token))), + (avatarUri = result.data.avatar_url) username = result.data.login } else if (provider === 'google') { for (let address of result.data.emailAddresses) { @@ -120,7 +120,7 @@ AuthController.prototype.providerCallback = function(req, res) { // New user: signup signup = true let handle = getHandle() - go.get(avatarUri, { responseType: 'arraybuffer' }).then(avatar => { + go.get(avatarUri, { responseType: 'arraybuffer' }).then((avatar) => { let type = imageType(avatar.headers['content-type']) saveAvatarFromBase64( new Buffer(avatar.data, 'binary').toString('base64'), @@ -142,21 +142,21 @@ AuthController.prototype.providerCallback = function(req, res) { }, time: { created: new Date(), - login: new Date() - } + login: new Date(), + }, } if (provider === 'github') { userData.social.github = result.data.login userData.bio = result.data.bio } let user = new User(userData) - user.save(function(err) { + user.save(function (err) { if (err) return res.sendStatus(500) let validation = createHandle(20) confirmation.data.handle = user.handle confirmation.data.validation = validation confirmation.data.signup = true - confirmation.save(function(err) { + confirmation.save(function (err) { if (err) return res.sendStatus(500) return res.redirect( createUrl( @@ -175,18 +175,20 @@ AuthController.prototype.providerCallback = function(req, res) { if (user.bio === '') user.bio = result.data.bio user.social.github = result.data.login } - user.save(function(err) { + user.save(function (err) { let validation = createHandle(20) confirmation.data.handle = user.handle confirmation.data.validation = validation confirmation.data.signup = false - confirmation.save(function(err) { + confirmation.save(function (err) { if (err) return res.sendStatus(500) return res.redirect( // Watch out for pending users - createUrl(language, (user.status === 'pending') - ? '/confirm/signup/' + req.query.state + '/' - : '/login/callback/' + confirmation._id + '/' + validation + createUrl( + language, + user.status === 'pending' + ? '/confirm/signup/' + req.query.state + '/' + : '/login/callback/' + confirmation._id + '/' + validation ) ) }) @@ -194,12 +196,12 @@ AuthController.prototype.providerCallback = function(req, res) { } }) }) - .catch(err => { + .catch((err) => { console.log('api token error', err) res.sendStatus(401) }) }) - .catch(err => { + .catch((err) => { console.log('post token error', err) res.sendStatus(401) }) @@ -207,20 +209,17 @@ AuthController.prototype.providerCallback = function(req, res) { } /* -* Github does not always return the email address -* See https://github.com/freesewing/backend/issues/162 -*/ + * Github does not always return the email address + * See https://github.com/freesewing/backend/issues/162 + */ const getGithubEmail = async (email, client, uri, headers) => { if (email === null) { - return client.get(uri, headers) - .then(result => { - for (let e of result.data) { - if (e.primary) return e.email - } - }) - } - else return email + return client.get(uri, headers).then((result) => { + for (let e of result.data) { + if (e.primary) return e.email + } + }) + } else return email } - export default AuthController diff --git a/sites/backend/src/controllers/github.js b/sites/backend/src/controllers/github.js index ad02df85bad..349b38792d4 100644 --- a/sites/backend/src/controllers/github.js +++ b/sites/backend/src/controllers/github.js @@ -4,95 +4,100 @@ import config from '../config' function GithubController() {} // Create a gist -GithubController.prototype.createGist = function(req, res) { +GithubController.prototype.createGist = function (req, res) { if (!req.body.data) return res.sendStatus(400) let client = GithubClient() - client.post('/gists', { - public: true, - description: `An open source sewing pattern from freesewing.org`, - files: { - 'pattern.yaml': { content: req.body.data } - } - }) - .then(result => { - let id = result.data.id - client.post(`/gists/${id}/comments`, { - body: `👉 https://freesewing.org/recreate/gist/${id} 👀` + client + .post('/gists', { + public: true, + description: `An open source sewing pattern from freesewing.org`, + files: { + 'pattern.yaml': { content: req.body.data }, + }, }) - .then(result => res.send({id})) - .catch(err => res.sendStatus(500)) - }) - .catch(err => res.sendStatus(500)) + .then((result) => { + let id = result.data.id + client + .post(`/gists/${id}/comments`, { + body: `👉 https://freesewing.org/recreate/gist/${id} 👀`, + }) + .then((result) => res.send({ id })) + .catch((err) => res.sendStatus(500)) + }) + .catch((err) => res.sendStatus(500)) } -GithubController.prototype.createIssue = function(req, res) { +GithubController.prototype.createIssue = function (req, res) { if (!req.body.data) return res.sendStatus(400) if (!req.body.design) return res.sendStatus(400) let client = GithubClient() - client.post('/gists', { - public: true, - description: `A FreeSewing crash report`, - files: { - 'pattern.yaml': { content: req.body.data }, - 'settings.yaml': { content: req.body.patternProps.settings }, - 'events.yaml': { content: req.body.patternProps.events }, - 'errors.md': { content: req.body.traces }, - 'parts.json': { content: req.body.patternProps.parts }, - } - }) - .then(gist => { - client.post('/repos/freesewing/freesewing/issues', { - title: `Error while drafting ${req.body.design}`, - body: `An error occured while drafting ${req.body.design} and a [crash report](https://gist.github.com/${gist.data.id}) was generated.`, - labels: [ - `:package: ${req.body.design}`, - ':robot: robot' - ] + client + .post('/gists', { + public: true, + description: `A FreeSewing crash report`, + files: { + 'pattern.yaml': { content: req.body.data }, + 'settings.yaml': { content: req.body.patternProps.settings }, + 'events.yaml': { content: req.body.patternProps.events }, + 'errors.md': { content: req.body.traces }, + 'parts.json': { content: req.body.patternProps.parts }, + }, }) - .then(issue => { - let notify = (typeof config.github.notify.specific[req.body.design] === 'undefined') - ? config.github.notify.dflt - : config.github.notify.specific[req.body.design] - let id = issue.data.number - let path = `/recreate/gist/${gist.data.id}` - let body = 'Ping ' - for (const user of notify) body += `@${user} ` - if (req.body.userGithub) body += `@${req.body.userGithub} ` - body += " 👋 \nRecreate this:\n\n" - body += `- **Lab**: 👉 https://lab.freesewing.dev/v/next/` + - `${req.body.design}?from=github&preload=${gist.data.id}` - body += "\n\n" - body += `- **Production**: 👉 https://freesewing.org${path}` - body += "\n\n" - if (req.body.userHandle) body += `(user handle: ${req.body.userHandle})` - client.post(`/repos/freesewing/freesewing/issues/${id}/comments`, { body }) - .then(result => res.send({id})) - .catch(err => { - console.log(err) - res.sendStatus(500) - }) + .then((gist) => { + client + .post('/repos/freesewing/freesewing/issues', { + title: `Error while drafting ${req.body.design}`, + body: `An error occured while drafting ${req.body.design} and a [crash report](https://gist.github.com/${gist.data.id}) was generated.`, + labels: [`:package: ${req.body.design}`, ':robot: robot'], + }) + .then((issue) => { + let notify = + typeof config.github.notify.specific[req.body.design] === 'undefined' + ? config.github.notify.dflt + : config.github.notify.specific[req.body.design] + let id = issue.data.number + let path = `/recreate/gist/${gist.data.id}` + let body = 'Ping ' + for (const user of notify) body += `@${user} ` + if (req.body.userGithub) body += `@${req.body.userGithub} ` + body += ' 👋 \nRecreate this:\n\n' + body += + `- **Lab**: 👉 https://lab.freesewing.dev/v/next/` + + `${req.body.design}?from=github&preload=${gist.data.id}` + body += '\n\n' + body += `- **Production**: 👉 https://freesewing.org${path}` + body += '\n\n' + if (req.body.userHandle) body += `(user handle: ${req.body.userHandle})` + client + .post(`/repos/freesewing/freesewing/issues/${id}/comments`, { body }) + .then((result) => res.send({ id })) + .catch((err) => { + console.log(err) + res.sendStatus(500) + }) + }) + .catch((err) => { + console.log(err) + res.sendStatus(500) + }) }) - .catch(err => { - console.log(err) + .catch((err) => { + console.log(err) res.sendStatus(500) }) - }) - .catch(err => { - console.log(err) - res.sendStatus(500) - }) } -const GithubClient = () => axios.create({ - baseURL: config.github.api, - timeout: 5000, - auth: { - username: config.github.bot.user, - password: config.github.token - }, - headers: { - Accept: 'application/vnd.github.v3+json' - } -}) +const GithubClient = () => + axios.create({ + baseURL: config.github.api, + timeout: 5000, + auth: { + username: config.github.bot.user, + password: config.github.token, + }, + headers: { + Accept: 'application/vnd.github.v3+json', + }, + }) export default GithubController diff --git a/sites/backend/src/controllers/newsletter.js b/sites/backend/src/controllers/newsletter.js index 364c9c42694..0f4fe57dd1c 100644 --- a/sites/backend/src/controllers/newsletter.js +++ b/sites/backend/src/controllers/newsletter.js @@ -1,40 +1,37 @@ import { Newsletter, Confirmation, User } from '../models' -import { - log, - email, - ehash, -} from '../utils' +import { log, email, ehash } from '../utils' import path from 'path' -const bail = (res, page='index') => res.sendFile(path.resolve(__dirname, '..', 'landing', `${page}.html`)) +const bail = (res, page = 'index') => + res.sendFile(path.resolve(__dirname, '..', 'landing', `${page}.html`)) function NewsletterController() {} -NewsletterController.prototype.subscribe = function(req, res, subscribe=true) { +NewsletterController.prototype.subscribe = function (req, res, subscribe = true) { if (!req.body || !req.body.email) return res.sendStatus(400) let confirmation = new Confirmation({ type: 'newsletter', - data: { email: req.body.email } + data: { email: req.body.email }, }) - confirmation.save(function(err) { + confirmation.save(function (err) { if (err) return res.sendStatus(500) log.info('newsletterSubscription', { email: req.body.email, - confirmation: confirmation._id + confirmation: confirmation._id, }) email.subscribe(req.body.email, confirmation._id) - return res.send({status: 'subscribed'}) + return res.send({ status: 'subscribed' }) }) } -NewsletterController.prototype.confirm = function(req, res, subscribe=true) { +NewsletterController.prototype.confirm = function (req, res, subscribe = true) { if (!req.params.token) return bail(res, 'invalid') Confirmation.findById(req.params.token, (err, confirmation) => { if (err) return bail(res) if (confirmation === null) return bail(res) Newsletter.findOne( { - ehash: ehash(confirmation.data.email) + ehash: ehash(confirmation.data.email), }, (err, reader) => { if (err) return bail(res) @@ -46,10 +43,10 @@ NewsletterController.prototype.confirm = function(req, res, subscribe=true) { email: confirmation.data.email, ehash: hash, time: { - created: new Date() - } + created: new Date(), + }, }) - sub.save(function(err) { + sub.save(function (err) { if (err) { log.error('newsletterSubscriptionFailed', sub) console.log(err) @@ -61,34 +58,33 @@ NewsletterController.prototype.confirm = function(req, res, subscribe=true) { return bail(res, 'subscribe') } }) - }) + } + ) }) } -NewsletterController.prototype.unsubscribe = function(req, res) { +NewsletterController.prototype.unsubscribe = function (req, res) { if (!req.params.ehash) return bail(res, 'invalid') Newsletter.findOne({ ehash: req.params.ehash }, (err, reader) => { if (reader) { - Newsletter.deleteOne({id: reader.id}, (err, result) => { + Newsletter.deleteOne({ id: reader.id }, (err, result) => { if (!err) { console.log(`Unsubscribed ${reader.email} from the newsletter`) return bail(res, 'unsubscribe') - } - else return bail(res, 'oops') + } else return bail(res, 'oops') }) } else { User.findOne({ ehash: req.params.ehash }, (err, user) => { if (user) { user.newsletter = false - user.save(function(err, updatedUser) { + user.save(function (err, updatedUser) { if (err) { log.error('accountUpdateFailed', err) return res.sendStatus(500) } else return bail(res, 'unsubscribe') }) - } - else return bail(res, 'oops') + } else return bail(res, 'oops') }) } }) diff --git a/sites/backend/src/controllers/og.js b/sites/backend/src/controllers/og.js index 0d113d9d869..ced08fae27e 100644 --- a/sites/backend/src/controllers/og.js +++ b/sites/backend/src/controllers/og.js @@ -1,8 +1,8 @@ -import config from "../config"; -import { capitalize } from "../utils"; -import sharp from 'sharp'; -import fs from "fs"; -import path from "path"; +import config from '../config' +import { capitalize } from '../utils' +import sharp from 'sharp' +import fs from 'fs' +import path from 'path' import axios from 'axios' import remark from 'remark' import remarkParse from 'remark-parse' @@ -14,13 +14,10 @@ import yaml from 'yaml' // Sites for which we generate images const sites = ['dev', 'org'] // Langauges for which we generate images -const languages = ['en', 'fr', 'de', 'es', 'nl' ] +const languages = ['en', 'fr', 'de', 'es', 'nl'] // Load template once at startup -const template = fs.readFileSync( - path.resolve(...config.og.template), - 'utf-8' -) +const template = fs.readFileSync(path.resolve(...config.og.template), 'utf-8') /* Helper method to extract intro from strapi markdown */ const introFromStrapiMarkdown = async (md, slug) => { @@ -33,17 +30,15 @@ const introFromStrapiMarkdown = async (md, slug) => { /* Helper method to extract title from markdown frontmatter */ const titleAndIntroFromLocalMarkdown = async (md, slug) => { - const tree = await remark() - .use(remarkParse) - .use(remarkFrontmatter, ['yaml']) - .parse(md) + const tree = await remark().use(remarkParse).use(remarkFrontmatter, ['yaml']).parse(md) if (tree.children[0].type !== 'yaml') console.log('Markdown does not start with frontmatter', slug) - else return { - title: titleAsLines(yaml.parse(tree.children[0].value).title), - intro: introAsLines(toString(tree.children.slice(1, 2))) - } + else + return { + title: titleAsLines(yaml.parse(tree.children[0].value).title), + intro: introAsLines(toString(tree.children.slice(1, 2))), + } return false } @@ -53,41 +48,40 @@ const loadDevBlogPost = async (slug) => { const result = await axios.get( `${config.strapi}/blogposts?_locale=en&dev_eq=true&slug_eq=${slug}` ) - if (result.data) return { - title: titleAsLines(result.data[0].title), - intro: introAsLines(await introFromStrapiMarkdown(result.data[0].body, slug)), - sub: [ - result.data[0].author.displayname, - new Date(result.data[0].published_at).toString().split(' ').slice(0,4).join(' '), - ], - lead: 'Developer Blog', - } + if (result.data) + return { + title: titleAsLines(result.data[0].title), + intro: introAsLines(await introFromStrapiMarkdown(result.data[0].body, slug)), + sub: [ + result.data[0].author.displayname, + new Date(result.data[0].published_at).toString().split(' ').slice(0, 4).join(' '), + ], + lead: 'Developer Blog', + } return false } /* Helper method to load markdown file from disk */ -const loadMarkdownFile = async (page, site, lang) => fs.promises.readFile( - path.resolve('..', '..', 'markdown', site, ...page.split('/'), `${lang}.md`), - 'utf-8' -).then(async (md) => md - ? { - ...(await titleAndIntroFromLocalMarkdown(md, page)), - sub: [ - 'freesewing.dev/', - page - ], - lead: capitalize(page.split('/').shift()) - } - : false -) +const loadMarkdownFile = async (page, site, lang) => + fs.promises + .readFile(path.resolve('..', '..', 'markdown', site, ...page.split('/'), `${lang}.md`), 'utf-8') + .then(async (md) => + md + ? { + ...(await titleAndIntroFromLocalMarkdown(md, page)), + sub: ['freesewing.dev/', page], + lead: capitalize(page.split('/').shift()), + } + : false + ) /* Find longest possible place to split a string */ const splitLine = (line, chars) => { const words = line.split(' ') if (words[0].length > chars) { // Force a word break - return [ line.slice(0, chars-1)+'-', line.slice(chars-1) ] + return [line.slice(0, chars - 1) + '-', line.slice(chars - 1)] } // Glue chunks together until it's too long let firstLine = '' @@ -97,22 +91,22 @@ const splitLine = (line, chars) => { else max = true } - return [ firstLine, words.join(' ').slice(firstLine.length) ] + return [firstLine, words.join(' ').slice(firstLine.length)] } /* Divide title into lines to fit on image */ -const titleAsLines = title => { +const titleAsLines = (title) => { // Does it fit on one line? if (title.length <= config.og.chars.title_1) return [title] // Does it fit on two lines? let lines = splitLine(title, config.og.chars.title_1) if (lines[1].length <= config.og.chars.title_2) return lines // Three lines it is - return [ lines[0], ...splitLine(lines[1], config.og.chars.title_2) ] + return [lines[0], ...splitLine(lines[1], config.og.chars.title_2)] } /* Divive intro into lines to fit on image */ -const introAsLines = intro => { +const introAsLines = (intro) => { // Does it fit on one line? if (intro.length <= config.og.chars.intro) return [intro] // Two lines it is @@ -124,19 +118,25 @@ const getMetaData = { dev: async (page) => { const chunks = page.split('/') // Home page - if (chunks.length === 1 && chunks[0] === '') return { - title: ['FreeSewing.dev'], - intro: introAsLines('FreeSewing API documentation and tutorials for developers and contributors'), - sub: ['Also featuring', ' our developers blog'], - lead: '.dev', - } + if (chunks.length === 1 && chunks[0] === '') + return { + title: ['FreeSewing.dev'], + intro: introAsLines( + 'FreeSewing API documentation and tutorials for developers and contributors' + ), + sub: ['Also featuring', ' our developers blog'], + lead: '.dev', + } // Blog index page - if (chunks.length === 1 && chunks[0] === 'blog') return { - title: titleAsLines('FreeSewing Developer Blog'), - intro: introAsLines("Contains no sewing news whatsover. Only posts for (aspiring) developers :)"), - sub: ['freesewing.dev', '/blog'], - lead: 'Developer Blog', - } + if (chunks.length === 1 && chunks[0] === 'blog') + return { + title: titleAsLines('FreeSewing Developer Blog'), + intro: introAsLines( + 'Contains no sewing news whatsover. Only posts for (aspiring) developers :)' + ), + sub: ['freesewing.dev', '/blog'], + lead: 'Developer Blog', + } // Blog post if (chunks.length === 2 && chunks[0] === 'blog') { return await loadDevBlogPost(chunks[1]) @@ -148,45 +148,43 @@ const getMetaData = { return md ? md : { - title: titleAsLines('FreeSewing.dev'), - intro: introAsLines('Documentation, guides, and howtos for contributors and developers alike'), - sub: ['https://freesewing.dev/', '<== Check it out'], - lead: 'freesewing.dev' - } + title: titleAsLines('FreeSewing.dev'), + intro: introAsLines( + 'Documentation, guides, and howtos for contributors and developers alike' + ), + sub: ['https://freesewing.dev/', '<== Check it out'], + lead: 'freesewing.dev', + } }, - org: async (page, site, lang) => ({}) + org: async (page, site, lang) => ({}), } /* Hide unused placeholders */ -const hidePlaceholders = list => { +const hidePlaceholders = (list) => { let svg = template for (const i of list) { - svg = svg - .replace(`${i}title_1`, '') - .replace(`${i}title_2`, '') - .replace(`${i}title_3`, '') + svg = svg.replace(`${i}title_1`, '').replace(`${i}title_2`, '').replace(`${i}title_3`, '') } return svg } /* Place text in SVG template */ -const decorateSvg = data => { +const decorateSvg = (data) => { let svg // Single title line if (data.title.length === 1) { - svg = hidePlaceholders([2,3]) - .replace(`1title_1`, data.title[0]) + svg = hidePlaceholders([2, 3]).replace(`1title_1`, data.title[0]) } // Double title line else if (data.title.length === 2) { - svg = hidePlaceholders([1,3]) + svg = hidePlaceholders([1, 3]) .replace(`2title_1`, data.title[0]) .replace(`2title_2`, data.title[1]) } // Triple title line else if (data.title.length === 3) { - svg = hidePlaceholders([1,2]) + svg = hidePlaceholders([1, 2]) .replace(`3title_1`, data.title[0]) .replace(`3title_2`, data.title[1]) .replace(`3title_3`, data.title[2]) @@ -202,14 +200,14 @@ const decorateSvg = data => { /* This generates open graph images */ -function OgController() { } +function OgController() {} OgController.prototype.image = async function (req, res) { // Extract path parameters - const { lang='en', site='dev' } = req.params - const page = req.params["0"] - if (sites.indexOf(site) === -1) return res.send({error: 'sorry'}) - if (languages.indexOf(lang) === -1) return res.send({error: 'sorry'}) + const { lang = 'en', site = 'dev' } = req.params + const page = req.params['0'] + if (sites.indexOf(site) === -1) return res.send({ error: 'sorry' }) + if (languages.indexOf(lang) === -1) return res.send({ error: 'sorry' }) // Load meta data const data = await getMetaData[site](page, site, lang) @@ -224,6 +222,4 @@ OgController.prototype.image = async function (req, res) { }) } - - -export default OgController; +export default OgController diff --git a/sites/backend/src/controllers/pattern.js b/sites/backend/src/controllers/pattern.js index 1c2a91bd3fd..be3bab9025c 100644 --- a/sites/backend/src/controllers/pattern.js +++ b/sites/backend/src/controllers/pattern.js @@ -17,9 +17,9 @@ PatternController.prototype.create = (req, res) => { name: req.body.name, notes: req.body.notes, data: req.body.data, - created: new Date() + created: new Date(), }) - pattern.save(function(err) { + pattern.save(function (err) { if (err) { log.error('patternCreationFailed', user) console.log(err) @@ -56,7 +56,7 @@ PatternController.prototype.delete = (req, res) => { if (!req.user._id) return res.sendStatus(400) User.findById(req.user._id, async (err, user) => { if (err || user === null) return res.sendStatus(400) - Pattern.deleteOne({ handle: req.params.handle, user: user.handle }, err => { + Pattern.deleteOne({ handle: req.params.handle, user: user.handle }, (err) => { if (err) return res.sendStatus(400) else return res.sendStatus(204) }) @@ -64,7 +64,7 @@ PatternController.prototype.delete = (req, res) => { } // Delete multiple -PatternController.prototype.deleteMultiple = function(req, res) { +PatternController.prototype.deleteMultiple = function (req, res) { if (!req.body) return res.sendStatus(400) if (!req.body.patterns) return res.sendStatus(400) if (!req.user._id) return res.sendStatus(400) @@ -77,9 +77,9 @@ PatternController.prototype.deleteMultiple = function(req, res) { Pattern.deleteMany( { user: user.handle, - $or: handles + $or: handles, }, - err => { + (err) => { if (err) return res.sendStatus(500) const patterns = {} Patterns.find({ user: user.handle }, (err, patternList) => { @@ -93,7 +93,7 @@ PatternController.prototype.deleteMultiple = function(req, res) { } function saveAndReturnPattern(res, pattern) { - pattern.save(function(err, updatedPattern) { + pattern.save(function (err, updatedPattern) { if (err) { log.error('patternUpdateFailed', updatedPattern) return res.sendStatus(500) diff --git a/sites/backend/src/controllers/person.js b/sites/backend/src/controllers/person.js index 1dfb1247aa3..5abc165e964 100644 --- a/sites/backend/src/controllers/person.js +++ b/sites/backend/src/controllers/person.js @@ -4,7 +4,7 @@ import { log } from '../utils' function PersonController() {} // CRUD basics -PersonController.prototype.create = function(req, res) { +PersonController.prototype.create = function (req, res) { if (!req.body) return res.sendStatus(400) if (!req.user._id) return res.sendStatus(400) User.findById(req.user._id, (err, user) => { @@ -17,10 +17,10 @@ PersonController.prototype.create = function(req, res) { units: req.body.units, breasts: req.body.breasts, picture: handle + '.svg', - created: new Date() + created: new Date(), }) person.createAvatar() - person.save(function(err) { + person.save(function (err) { if (err) return res.sendStatus(400) log.info('personCreated', { handle: handle }) return res.send({ person: person.info() }) @@ -28,7 +28,7 @@ PersonController.prototype.create = function(req, res) { }) } -PersonController.prototype.read = function(req, res) { +PersonController.prototype.read = function (req, res) { if (!req.body) return res.sendStatus(400) if (!req.user._id) return res.sendStatus(400) User.findById(req.user._id, (err, user) => { @@ -56,7 +56,7 @@ PersonController.prototype.update = (req, res) => { if (typeof data.measurements !== 'undefined') person.measurements = { ...person.measurements, - ...data.measurements + ...data.measurements, } if (typeof data.picture !== 'undefined') person.saveAvatar(data.picture) @@ -69,7 +69,7 @@ PersonController.prototype.delete = (req, res) => { if (!req.user._id) return res.sendStatus(400) User.findById(req.user._id, async (err, user) => { if (err || user === null) return res.sendStatus(400) - Person.deleteOne({ handle: req.params.handle, user: user.handle }, err => { + Person.deleteOne({ handle: req.params.handle, user: user.handle }, (err) => { if (err) return res.sendStatus(400) else return res.sendStatus(204) }) @@ -77,10 +77,10 @@ PersonController.prototype.delete = (req, res) => { } // Clone -PersonController.prototype.clone = function(req, res) {} +PersonController.prototype.clone = function (req, res) {} function saveAndReturnPerson(res, person) { - person.save(function(err, updatedPerson) { + person.save(function (err, updatedPerson) { if (err) { log.error('personUpdateFailed', updatedPerson) return res.sendStatus(500) diff --git a/sites/backend/src/controllers/strapi.js b/sites/backend/src/controllers/strapi.js index bd974999d9b..218afe89e90 100644 --- a/sites/backend/src/controllers/strapi.js +++ b/sites/backend/src/controllers/strapi.js @@ -11,11 +11,10 @@ const getToken = async () => { `${config.strapi.protocol}://${config.strapi.host}:${config.strapi.port}/auth/local`, { identifier: config.strapi.username, - password: config.strapi.password + password: config.strapi.password, } ) - } - catch(err) { + } catch (err) { console.log('ERROR: Failed to load strapi token') return false } @@ -23,18 +22,18 @@ const getToken = async () => { return result.data.jwt } -const withToken = token => ({ +const withToken = (token) => ({ headers: { Authorization: `Bearer ${token}`, - } + }, }) -const ext = type => { +const ext = (type) => { switch (type.toLowerCase()) { case 'image/jpg': case 'image/jpeg': return 'jpg' - break; + break case 'image/png': return 'png' break @@ -46,47 +45,45 @@ const ext = type => { } } -const api = path => `${config.strapi.protocol}://${config.strapi.host}:${config.strapi.port}${path}` - +const api = (path) => + `${config.strapi.protocol}://${config.strapi.host}:${config.strapi.port}${path}` // Uploads a picture to Strapi const uploadPicture = async (img, name, token) => { const form = new FormData() const buff = asBuffer(img) const extention = ext(buff.type) - if (!extention) return [false, {error: `Filetype ${buff.type} is not supported`}] + if (!extention) return [false, { error: `Filetype ${buff.type} is not supported` }] // I hate you strapi, because this hack is the only way I can get your shitty upload to work const filename = `${config.strapi.tmp}/viaBackend.${extention}` const file = fs.createReadStream(filename) form.append('files', file) - form.append('fileInfo', JSON.stringify({ - alternativeText: `The picture/avatar for maker ${name}`, - caption: `Maker: ${name}`, - })) + form.append( + 'fileInfo', + JSON.stringify({ + alternativeText: `The picture/avatar for maker ${name}`, + caption: `Maker: ${name}`, + }) + ) let result try { - result = await axios.post( - api('/upload'), - form, - { - headers: { - ...form.getHeaders(), - Authorization: `Bearer ${token}`, - }, - } - ) - } - catch (err) { - console.log("ERROR: Failed to upload picture") - return [false, {error: 'Upload failed'}] + result = await axios.post(api('/upload'), form, { + headers: { + ...form.getHeaders(), + Authorization: `Bearer ${token}`, + }, + }) + } catch (err) { + console.log('ERROR: Failed to upload picture') + return [false, { error: 'Upload failed' }] } return [true, result.data] } -const validRequest = body => ( +const validRequest = (body) => body && body.displayname && body.about && @@ -94,40 +91,36 @@ const validRequest = body => ( typeof body.displayname === 'string' && typeof body.about === 'string' && typeof body.picture === 'string' -) - // Creates a maker or author in Strapi const createPerson = async (type, data, token) => { let result try { - result = await axios.post( - api(`/${type}s`), - data, - withToken(token) - ) - } - catch (err) { - console.log("ERROR: Failed to create", type) - return [false, {error: 'Creation failed'}] + result = await axios.post(api(`/${type}s`), data, withToken(token)) + } catch (err) { + console.log('ERROR: Failed to create', type) + return [false, { error: 'Creation failed' }] } return [true, result.data] - } function StrapiController() {} -StrapiController.prototype.addPerson = async function(req, res, type) { +StrapiController.prototype.addPerson = async function (req, res, type) { if (!validRequest(req.body)) return res.sendStatus(400) const token = await getToken() const [upload, picture] = await uploadPicture(req.body.picture, req.body.displayname, token) if (!upload) return res.status(400).send(picture) - const [create, person] = await createPerson(type, { - picture: picture[0].id, - displayname: req.body.displayname, - about: req.body.about, - }, token) + const [create, person] = await createPerson( + type, + { + picture: picture[0].id, + displayname: req.body.displayname, + about: req.body.about, + }, + token + ) if (!create) return res.status(400).send(person) return res.send(person) diff --git a/sites/backend/src/controllers/user.js b/sites/backend/src/controllers/user.js index 615ea5ad950..be4de55816d 100644 --- a/sites/backend/src/controllers/user.js +++ b/sites/backend/src/controllers/user.js @@ -1,11 +1,5 @@ import { User, Confirmation, Person, Pattern } from '../models' -import { - log, - email, - ehash, - newHandle, - uniqueHandle, -} from '../utils' +import { log, email, ehash, newHandle, uniqueHandle } from '../utils' import jwt from 'jsonwebtoken' import config from '../config' import path from 'path' @@ -15,15 +9,15 @@ import rimraf from 'rimraf' function UserController() {} -UserController.prototype.login = function(req, res) { +UserController.prototype.login = function (req, res) { if (!req.body || !req.body.username) return res.sendStatus(400) User.findOne( { $or: [ { username: req.body.username.toLowerCase().trim() }, { username: req.body.username.trim() }, - { ehash: ehash(req.body.username) } - ] + { ehash: ehash(req.body.username) }, + ], }, (err, user) => { if (err) return res.sendStatus(400) @@ -44,9 +38,7 @@ UserController.prototype.login = function(req, res) { Pattern.find({ user: user.handle }, (err, patternList) => { if (err) return res.sendStatus(400) for (let pattern of patternList) patterns[pattern.handle] = pattern - return user.updateLoginTime(() => - res.send({ account, people, patterns, token }) - ) + return user.updateLoginTime(() => res.send({ account, people, patterns, token })) }) }) } @@ -60,7 +52,7 @@ UserController.prototype.login = function(req, res) { } // For people who have forgotten their password, or password-less logins -UserController.prototype.confirmationLogin = function(req, res) { +UserController.prototype.confirmationLogin = function (req, res) { if (!req.body || !req.body.id) return res.sendStatus(400) Confirmation.findById(req.body.id, (err, confirmation) => { if (err) return res.sendStatus(400) @@ -83,9 +75,7 @@ UserController.prototype.confirmationLogin = function(req, res) { Pattern.find({ user: user.handle }, (err, patternList) => { if (err) return res.sendStatus(400) for (let pattern of patternList) patterns[pattern.handle] = pattern - return user.updateLoginTime(() => - res.send({ account, people, patterns, token }) - ) + return user.updateLoginTime(() => res.send({ account, people, patterns, token })) }) }) } @@ -112,7 +102,7 @@ UserController.prototype.create = (req, res) => { log.info('accountActivated', { handle: user.handle }) let account = user.account() let token = getToken(account) - user.save(function(err) { + user.save(function (err) { if (err) return res.sendStatus(400) Confirmation.findByIdAndDelete(req.body.id, (err, confirmation) => { return res.send({ account, people: {}, patterns: {}, token }) @@ -164,7 +154,7 @@ UserController.prototype.update = (req, res) => { if (typeof data.settings !== 'undefined') { user.settings = { ...user.settings, - ...data.settings + ...data.settings, } return saveAndReturnAccount(res, user) } else if (data.newsletter === true || data.newsletter === false) { @@ -183,7 +173,7 @@ UserController.prototype.update = (req, res) => { } else if (typeof data.consent === 'object') { user.consent = { ...user.consent, - ...data.consent + ...data.consent, } return saveAndReturnAccount(res, user) } else if (typeof data.avatar !== 'undefined') { @@ -223,15 +213,15 @@ UserController.prototype.update = (req, res) => { language: user.settings.language, email: { new: req.body.email, - current: user.email - } - } + current: user.email, + }, + }, }) - confirmation.save(function(err) { + confirmation.save(function (err) { if (err) return res.sendStatus(500) log.info('emailchangeRequest', { newEmail: req.body.email, - confirmation: confirmation._id + confirmation: confirmation._id, }) email.emailchange(req.body.email, user.email, user.settings.language, confirmation._id) return saveAndReturnAccount(res, user) @@ -242,7 +232,7 @@ UserController.prototype.update = (req, res) => { } function saveAndReturnAccount(res, user) { - user.save(function(err, updatedUser) { + user.save(function (err, updatedUser) { if (err) { log.error('accountUpdateFailed', err) return res.sendStatus(500) @@ -274,7 +264,7 @@ UserController.prototype.signup = (req, res) => { if (!req.body.language) return res.status(400).send('languageMissing') User.findOne( { - ehash: ehash(req.body.email) + ehash: ehash(req.body.email), }, (err, user) => { if (err) return res.sendStatus(500) @@ -293,10 +283,10 @@ UserController.prototype.signup = (req, res) => { status: 'pending', picture: handle + '.svg', time: { - created: new Date() - } + created: new Date(), + }, }) - user.save(function(err) { + user.save(function (err) { if (err) { log.error('accountCreationFailed', user) console.log(err) @@ -310,10 +300,10 @@ UserController.prototype.signup = (req, res) => { language: req.body.language, email: req.body.email, password: req.body.password, - handle - } + handle, + }, }) - confirmation.save(function(err) { + confirmation.save(function (err) { if (err) return res.sendStatus(500) log.info('signupRequest', { email: req.body.email, confirmation: confirmation._id }) email.signup(req.body.email, req.body.language, confirmation._id) @@ -332,7 +322,7 @@ UserController.prototype.resend = (req, res) => { if (!req.body.language) return res.status(400).send('languageMissing') User.findOne( { - ehash: ehash(req.body.email) + ehash: ehash(req.body.email), }, (err, user) => { if (err) return res.sendStatus(500) @@ -343,12 +333,15 @@ UserController.prototype.resend = (req, res) => { data: { language: req.body.language, email: user.email, - handle: user.handle - } + handle: user.handle, + }, }) - confirmation.save(function(err) { + confirmation.save(function (err) { if (err) return res.sendStatus(500) - log.info('resendActivationRequest', { email: req.body.email, confirmation: confirmation._id }) + log.info('resendActivationRequest', { + email: req.body.email, + confirmation: confirmation._id, + }) email.signup(req.body.email, req.body.language, confirmation._id) return res.sendStatus(200) }) @@ -363,8 +356,8 @@ UserController.prototype.resetPassword = (req, res) => { { $or: [ { username: req.body.username.toLowerCase().trim() }, - { ehash: ehash(req.body.username) } - ] + { ehash: ehash(req.body.username) }, + ], }, (err, user) => { if (err) { @@ -375,10 +368,10 @@ UserController.prototype.resetPassword = (req, res) => { let confirmation = new Confirmation({ type: 'passwordreset', data: { - handle: user.handle - } + handle: user.handle, + }, }) - confirmation.save(function(err) { + confirmation.save(function (err) { if (err) return res.sendStatus(500) log.info('passwordresetRequest', { user: user.handle, confirmation: confirmation._id }) email.passwordreset(user.email, user.settings.language, confirmation._id) @@ -398,7 +391,7 @@ UserController.prototype.setPassword = (req, res) => { if (user === null) return res.sendStatus(401) if (confirmation.type === 'passwordreset' && confirmation.data.handle === user.handle) { user.password = req.body.password - user.save(function(err) { + user.save(function (err) { log.info('passwordSet', { user, req }) let account = user.account() let token = getToken(account) @@ -433,7 +426,7 @@ UserController.prototype.patronList = (req, res) => { let patrons = { 2: [], 4: [], - 8: [] + 8: [], } for (let key of Object.keys(users)) { let user = users[key].profile() @@ -443,7 +436,7 @@ UserController.prototype.patronList = (req, res) => { bio: user.bio, picture: user.picture, social: user.social, - pictureUris: user.pictureUris + pictureUris: user.pictureUris, }) } return res.send(patrons) @@ -458,17 +451,17 @@ UserController.prototype.export = (req, res) => { if (!dir) return res.sendStatus(500) let zip = new Zip() zip.file('account.json', JSON.stringify(user.export(), null, 2)) - loadAvatar(user).then(avatar => { + loadAvatar(user).then((avatar) => { if (avatar) zip.file(user.picture, data) zip .generateAsync({ type: 'uint8array', comment: 'freesewing.org', - streamFiles: true + streamFiles: true, }) - .then(function(data) { + .then(function (data) { let file = path.join(dir, 'export.zip') - fs.writeFile(file, data, err => { + fs.writeFile(file, data, (err) => { log.info('dataExport', { user, req }) return res.send({ export: uri(file) }) }) @@ -477,7 +470,7 @@ UserController.prototype.export = (req, res) => { }) } -const loadAvatar = async user => { +const loadAvatar = async (user) => { if (user.picture) await fs.readFile(path.join(user.storagePath(), user.picture), (err, data) => data) else return false @@ -489,7 +482,7 @@ UserController.prototype.restrict = (req, res) => { User.findById(req.user._id, (err, user) => { if (user === null) return res.sendStatus(400) user.status = 'frozen' - user.save(function(err) { + user.save(function (err) { if (err) { log.error('accountFreezeFailed', user) return res.sendStatus(500) @@ -504,7 +497,7 @@ UserController.prototype.remove = (req, res) => { if (!req.user._id) return res.sendStatus(400) User.findById(req.user._id, (err, user) => { if (user === null) return res.sendStatus(400) - rimraf(user.storagePath(), err => { + rimraf(user.storagePath(), (err) => { if (err) { console.log('rimraf', err) log.error('accountRemovalFailed', { err, user, req }) @@ -520,14 +513,14 @@ UserController.prototype.remove = (req, res) => { }) } -const getToken = account => { +const getToken = (account) => { return jwt.sign( { _id: account._id, handle: account.handle, role: account.role, aud: config.jwt.audience, - iss: config.jwt.issuer + iss: config.jwt.issuer, }, config.jwt.secretOrKey ) @@ -535,7 +528,7 @@ const getToken = account => { const createTempDir = () => { let path = temporaryStoragePath(newHandle(10)) - fs.mkdir(path, { recursive: true }, err => { + fs.mkdir(path, { recursive: true }, (err) => { if (err) { log.error('mkdirFailed', err) path = false @@ -545,6 +538,6 @@ const createTempDir = () => { return path } -const uri = path => config.static + path.substring(config.storage.length) +const uri = (path) => config.static + path.substring(config.storage.length) export default UserController diff --git a/sites/backend/src/landing/already-subscribed.html b/sites/backend/src/landing/already-subscribed.html index f30ffe9bbae..2df1ecce436 100644 --- a/sites/backend/src/landing/already-subscribed.html +++ b/sites/backend/src/landing/already-subscribed.html @@ -37,7 +37,7 @@ -
+

Love the enthusiasm

But you were already subscribed

diff --git a/sites/backend/src/landing/index.html b/sites/backend/src/landing/index.html index d250e843eed..a313597a81c 100644 --- a/sites/backend/src/landing/index.html +++ b/sites/backend/src/landing/index.html @@ -34,21 +34,24 @@ max-width: 36ch; margin: 6rem auto; } - a, a:visited, a:active { + a, + a:visited, + a:active { color: #d0bfff !important; text-decoration: none; } -
+

Hi

This is the FreeSewing backend. -
+
Try freesewing.org instead.

-

For questions, join us at +

+ For questions, join us at discord.freesewing.org

diff --git a/sites/backend/src/landing/invalid.html b/sites/backend/src/landing/invalid.html index a3baa1d32ce..47058631900 100644 --- a/sites/backend/src/landing/invalid.html +++ b/sites/backend/src/landing/invalid.html @@ -34,18 +34,18 @@ max-width: 36ch; margin: 6rem auto; } - a, a:visited, a:active { + a, + a:visited, + a:active { color: #d0bfff !important; text-decoration: none; } -
+

What are you doing?

-

- Try freesewing.org instead. -

+

Try freesewing.org instead.

diff --git a/sites/backend/src/landing/oops.html b/sites/backend/src/landing/oops.html index 264ca143291..905c82e3b41 100644 --- a/sites/backend/src/landing/oops.html +++ b/sites/backend/src/landing/oops.html @@ -34,18 +34,18 @@ max-width: 36ch; margin: 6rem auto; } - a, a:visited, a:active { + a, + a:visited, + a:active { color: #d0bfff !important; text-decoration: none; } -
+

Oops

-

- That did not go as planned -

+

That did not go as planned

diff --git a/sites/backend/src/landing/subscribe.html b/sites/backend/src/landing/subscribe.html index e0920804cbd..57d8f6f488d 100644 --- a/sites/backend/src/landing/subscribe.html +++ b/sites/backend/src/landing/subscribe.html @@ -37,7 +37,7 @@ -
+

Done

You are now subscribed to the FreeSewing newsletter

diff --git a/sites/backend/src/landing/unsubscribe.html b/sites/backend/src/landing/unsubscribe.html index 76a4aef7dc1..b7ed6ad1a97 100644 --- a/sites/backend/src/landing/unsubscribe.html +++ b/sites/backend/src/landing/unsubscribe.html @@ -37,7 +37,7 @@ -
+

Gone

You are no longer subscribed to the FreeSewing newsletter

diff --git a/sites/backend/src/middleware/express/bodyParser.js b/sites/backend/src/middleware/express/bodyParser.js index 13ad583df26..8e242ebf56d 100644 --- a/sites/backend/src/middleware/express/bodyParser.js +++ b/sites/backend/src/middleware/express/bodyParser.js @@ -1,6 +1,6 @@ import bodyParser from 'body-parser' -export default app => { +export default (app) => { app.use(bodyParser.json({ limit: '20mb' })) app.use(bodyParser.urlencoded({ extended: true })) } diff --git a/sites/backend/src/middleware/express/cors.js b/sites/backend/src/middleware/express/cors.js index c285a89523b..206b0970a24 100644 --- a/sites/backend/src/middleware/express/cors.js +++ b/sites/backend/src/middleware/express/cors.js @@ -1,5 +1,5 @@ import cors from 'cors' -export default app => { +export default (app) => { app.use(cors()) } diff --git a/sites/backend/src/middleware/passport/jwt.js b/sites/backend/src/middleware/passport/jwt.js index 7488eebca43..85af45370f6 100644 --- a/sites/backend/src/middleware/passport/jwt.js +++ b/sites/backend/src/middleware/passport/jwt.js @@ -3,10 +3,10 @@ import config from '../../config' const options = { jwtFromRequest: jwt.ExtractJwt.fromAuthHeaderAsBearerToken(), - ...config.jwt + ...config.jwt, } -export default passport => { +export default (passport) => { passport.use( new jwt.Strategy(options, (jwt_payload, done) => { return done(null, jwt_payload) diff --git a/sites/backend/src/models/confirmation.js b/sites/backend/src/models/confirmation.js index 508bc61097f..7be3d196519 100644 --- a/sites/backend/src/models/confirmation.js +++ b/sites/backend/src/models/confirmation.js @@ -6,14 +6,14 @@ import config from '../config' const ConfirmationSchema = new Schema({ created: { type: Date, - default: Date.now + default: Date.now, }, type: { type: String, enum: ['signup', 'emailchange', 'passwordreset', 'oauth', 'newsletter'], - required: true + required: true, }, - data: {} + data: {}, }) ConfirmationSchema.plugin(bcrypt) @@ -21,7 +21,7 @@ ConfirmationSchema.plugin(bcrypt) ConfirmationSchema.plugin(encrypt, { secret: config.encryption.key, encryptedFields: ['data'], - decryptPostSave: false + decryptPostSave: false, }) export default mongoose.model('Confirmation', ConfirmationSchema) diff --git a/sites/backend/src/models/newsletter.js b/sites/backend/src/models/newsletter.js index f08661ad93f..b8c08a1937e 100644 --- a/sites/backend/src/models/newsletter.js +++ b/sites/backend/src/models/newsletter.js @@ -6,19 +6,19 @@ import config from '../config' const NewsletterSchema = new Schema({ created: { type: Date, - default: Date.now + default: Date.now, }, email: { type: String, - required: true + required: true, }, ehash: { type: String, required: true, unique: true, - index: true + index: true, }, - data: {} + data: {}, }) NewsletterSchema.plugin(bcrypt) @@ -28,7 +28,7 @@ NewsletterSchema.index({ ehash: 1 }) NewsletterSchema.plugin(encrypt, { secret: config.encryption.key, encryptedFields: ['email'], - decryptPostSave: false + decryptPostSave: false, }) export default mongoose.model('Newsletter', NewsletterSchema) diff --git a/sites/backend/src/models/pattern.js b/sites/backend/src/models/pattern.js index 72d7e613fd2..22c25377b79 100644 --- a/sites/backend/src/models/pattern.js +++ b/sites/backend/src/models/pattern.js @@ -8,51 +8,51 @@ const PatternSchema = new Schema( lowercase: true, unique: true, trim: true, - index: true + index: true, }, user: { type: String, required: true, lowercase: true, trim: true, - index: true + index: true, }, person: { type: String, required: true, lowercase: true, trim: true, - index: true + index: true, }, name: { type: String, required: true, - trim: true + trim: true, }, created: Date, notes: { type: String, - trim: true + trim: true, }, - data: {} + data: {}, }, { timestamps: true } ) PatternSchema.index({ user: 1, handle: 1 }) -PatternSchema.methods.info = function() { +PatternSchema.methods.info = function () { return this.toObject() } -PatternSchema.methods.export = function() { +PatternSchema.methods.export = function () { let pattern = this.toObject() for (let field of ['__v', '_id', '_v', 'created']) delete pattern[field] return pattern } -PatternSchema.methods.anonymize = function() { +PatternSchema.methods.anonymize = function () { let pattern = this.toObject() for (let field of ['__v', '_id', 'user', 'createdAt', 'updatedAt', '_v']) delete pattern[field] diff --git a/sites/backend/src/models/person.js b/sites/backend/src/models/person.js index 6bffe443e3a..b7732a72b48 100644 --- a/sites/backend/src/models/person.js +++ b/sites/backend/src/models/person.js @@ -13,37 +13,37 @@ const PersonSchema = new Schema( lowercase: true, unique: true, trim: true, - index: true + index: true, }, user: { type: String, required: true, lowercase: true, trim: true, - index: true + index: true, }, name: { type: String, required: true, - trim: true + trim: true, }, breasts: { type: Boolean, - default: false + default: false, }, picture: { type: String, trim: true, - default: '' + default: '', }, units: { type: String, enum: ['metric', 'imperial'], - default: 'metric' + default: 'metric', }, notes: { type: String, - trim: true + trim: true, }, measurements: { ankle: Number, @@ -90,7 +90,7 @@ const PersonSchema = new Schema( PersonSchema.index({ user: 1, handle: 1 }) -PersonSchema.methods.info = function() { +PersonSchema.methods.info = function () { let person = this.toObject() delete person.__v delete person._id @@ -98,20 +98,20 @@ PersonSchema.methods.info = function() { l: this.avatarUri(), m: this.avatarUri('m'), s: this.avatarUri('s'), - xs: this.avatarUri('xs') + xs: this.avatarUri('xs'), } return person } -PersonSchema.methods.avatarName = function(size = 'l') { +PersonSchema.methods.avatarName = function (size = 'l') { let prefix = size === 'l' ? '' : size + '-' if (this.picture.slice(-4).toLowerCase() === '.svg') prefix = '' return prefix + this.picture } -PersonSchema.methods.avatarUri = function(size = 'l') { +PersonSchema.methods.avatarUri = function (size = 'l') { return ( config.static + '/users/' + @@ -125,7 +125,7 @@ PersonSchema.methods.avatarUri = function(size = 'l') { ) } -PersonSchema.methods.storagePath = function() { +PersonSchema.methods.storagePath = function () { return ( config.storage + '/users/' + @@ -138,24 +138,24 @@ PersonSchema.methods.storagePath = function() { ) } -PersonSchema.methods.createAvatar = function() { +PersonSchema.methods.createAvatar = function () { let dir = this.storagePath() - fs.mkdir(dir, { recursive: true }, err => { + fs.mkdir(dir, { recursive: true }, (err) => { if (err) console.log('mkdirFailed', dir, err) - fs.writeFile(path.join(dir, this.handle) + '.svg', randomAvatar(), err => { + fs.writeFile(path.join(dir, this.handle) + '.svg', randomAvatar(), (err) => { if (err) console.log('writeFileFailed', dir, err) }) }) } -PersonSchema.methods.saveAvatar = function(picture) { +PersonSchema.methods.saveAvatar = function (picture) { let type = picture.split(';').shift() type = type.split('/').pop() this.picture = this.handle + '.' + type let dir = this.storagePath() let b64 = picture.split(';base64,').pop() - fs.mkdir(dir, { recursive: true }, err => { + fs.mkdir(dir, { recursive: true }, (err) => { if (err) log.error('mkdirFailed', err) let imgBuffer = Buffer.from(b64, 'base64') for (let size of Object.keys(config.avatar.sizes)) { diff --git a/sites/backend/src/models/user.js b/sites/backend/src/models/user.js index 63c3278f989..d1c3e4eb551 100644 --- a/sites/backend/src/models/user.js +++ b/sites/backend/src/models/user.js @@ -12,24 +12,24 @@ const UserSchema = new Schema( { email: { type: String, - required: true + required: true, }, ehash: { type: String, required: true, unique: true, - index: true + index: true, }, initial: { type: String, - required: true + required: true, }, username: { type: String, required: true, unique: true, index: true, - trim: true + trim: true, }, handle: { type: String, @@ -37,89 +37,89 @@ const UserSchema = new Schema( lowercase: true, trim: true, index: true, - unique: true + unique: true, }, role: { type: String, enum: ['user', 'moderator', 'admin'], required: true, - default: 'user' + default: 'user', }, patron: { type: Number, enum: [0, 2, 4, 8], - default: 0 + default: 0, }, bio: { type: String, - default: '' + default: '', }, picture: { type: String, trim: true, - default: '' + default: '', }, status: { type: String, enum: ['pending', 'active', 'blocked', 'frozen'], default: 'pending', - required: true + required: true, }, password: { type: String, - bcrypt: true + bcrypt: true, }, settings: { language: { type: String, default: 'en', - enum: config.languages + enum: config.languages, }, units: { type: String, enum: ['metric', 'imperial'], - default: 'metric' - } + default: 'metric', + }, }, consent: { profile: { type: Boolean, - default: false + default: false, }, measurements: { type: Boolean, - default: false + default: false, }, openData: { type: Boolean, - default: true - } + default: true, + }, }, time: { migrated: Date, login: Date, - patron: Date + patron: Date, }, social: { twitter: String, instagram: String, - github: String + github: String, }, newsletter: { type: Boolean, - default: false + default: false, }, }, { timestamps: true } ) -UserSchema.pre('remove', function(next) { +UserSchema.pre('remove', function (next) { email .goodbye(this.email, this.settings.language) .then(() => { next() }) - .catch(err => { + .catch((err) => { logger.error(err) next() }) @@ -131,10 +131,10 @@ UserSchema.index({ ehash: 1, username: 1, handle: 1 }) UserSchema.plugin(encrypt, { secret: config.encryption.key, encryptedFields: ['email', 'initial', 'social.twitter', 'social.instagram', 'social.github'], - decryptPostSave: true + decryptPostSave: true, }) -UserSchema.methods.account = function() { +UserSchema.methods.account = function () { let account = this.toObject() delete account.password delete account.ehash @@ -147,13 +147,13 @@ UserSchema.methods.account = function() { l: this.avatarUri(), m: this.avatarUri('m'), s: this.avatarUri('s'), - xs: this.avatarUri('xs') + xs: this.avatarUri('xs'), } return account } -UserSchema.methods.profile = function() { +UserSchema.methods.profile = function () { let account = this.toObject() delete account.password delete account.ehash @@ -174,13 +174,13 @@ UserSchema.methods.profile = function() { l: this.avatarUri(), m: this.avatarUri('m'), s: this.avatarUri('s'), - xs: this.avatarUri('xs') + xs: this.avatarUri('xs'), } return account } -UserSchema.methods.adminProfile = function() { +UserSchema.methods.adminProfile = function () { let account = this.toObject() delete account.password delete account.ehash @@ -194,13 +194,13 @@ UserSchema.methods.adminProfile = function() { l: this.avatarUri(), m: this.avatarUri('m'), s: this.avatarUri('s'), - xs: this.avatarUri('xs') + xs: this.avatarUri('xs'), } return account } -UserSchema.methods.export = function() { +UserSchema.methods.export = function () { let exported = this.toObject() delete exported.password delete exported.ehash @@ -211,26 +211,26 @@ UserSchema.methods.export = function() { return exported } -UserSchema.methods.updateLoginTime = function(callback) { +UserSchema.methods.updateLoginTime = function (callback) { this.set({ time: { login: new Date() } }) - this.save(function(err, user) { + this.save(function (err, user) { return callback() }) } -UserSchema.methods.avatarName = function(size = 'l') { +UserSchema.methods.avatarName = function (size = 'l') { let prefix = size === 'l' ? '' : size + '-' if (this.picture.slice(-4).toLowerCase() === '.svg') prefix = '' return prefix + this.picture } -UserSchema.methods.storagePath = function() { +UserSchema.methods.storagePath = function () { return path.join(config.storage, 'users', this.handle.substring(0, 1), this.handle) } -UserSchema.methods.avatarUri = function(size = 'l') { - if (!this.picture || this.picture.length < 5) return "https://freesewing.org/avatar.svg" +UserSchema.methods.avatarUri = function (size = 'l') { + if (!this.picture || this.picture.length < 5) return 'https://freesewing.org/avatar.svg' return ( config.static + '/users/' + @@ -242,14 +242,14 @@ UserSchema.methods.avatarUri = function(size = 'l') { ) } -UserSchema.methods.saveAvatar = function(picture) { +UserSchema.methods.saveAvatar = function (picture) { let type = picture.split(';').shift() type = type.split('/').pop() this.picture = this.handle + '.' + type let dir = this.storagePath() let b64 = picture.split(';base64,').pop() - fs.mkdir(dir, { recursive: true }, err => { + fs.mkdir(dir, { recursive: true }, (err) => { if (err) log.error('mkdirFailed', err) let imgBuffer = Buffer.from(b64, 'base64') for (let size of Object.keys(config.avatar.sizes)) { @@ -262,11 +262,11 @@ UserSchema.methods.saveAvatar = function(picture) { }) } -UserSchema.methods.createAvatar = function() { +UserSchema.methods.createAvatar = function () { let dir = this.storagePath() - fs.mkdirSync(dir, { recursive: true }, err => { + fs.mkdirSync(dir, { recursive: true }, (err) => { if (err) console.log('mkdirFailed', dir, err) - fs.writeFileSync(path.join(dir, this.handle) + '.svg', randomAvatar(), err => { + fs.writeFileSync(path.join(dir, this.handle) + '.svg', randomAvatar(), (err) => { if (err) console.log('writeFileFailed', dir, err) }) }) diff --git a/sites/backend/src/routes/admin.js b/sites/backend/src/routes/admin.js index 6739041e003..87db357b78f 100644 --- a/sites/backend/src/routes/admin.js +++ b/sites/backend/src/routes/admin.js @@ -4,24 +4,20 @@ const Admin = new Controller() export default (app, passport) => { // Users + app.post('/admin/search', passport.authenticate('jwt', { session: false }), Admin.search) + app.put('/admin/patron', passport.authenticate('jwt', { session: false }), Admin.setPatronStatus) + app.put('/admin/role', passport.authenticate('jwt', { session: false }), Admin.setRole) app.post( - '/admin/search', + '/admin/impersonate', passport.authenticate('jwt', { session: false }), - Admin.search + Admin.impersonate ) - app.put( - '/admin/patron', - passport.authenticate('jwt', { session: false }), - Admin.setPatronStatus - ) - app.put( - '/admin/role', - passport.authenticate('jwt', { session: false }), - Admin.setRole - ) - app.post('/admin/impersonate', passport.authenticate('jwt', { session: false }), Admin.impersonate) app.put('/admin/unfreeze', passport.authenticate('jwt', { session: false }), Admin.unfreeze) app.get('/admin/patrons', passport.authenticate('jwt', { session: false }), Admin.patronList) - app.get('/admin/subscribers', passport.authenticate('jwt', { session: false }), Admin.subscriberList) + app.get( + '/admin/subscribers', + passport.authenticate('jwt', { session: false }), + Admin.subscriberList + ) app.get('/admin/stats', passport.authenticate('jwt', { session: false }), Admin.stats) } diff --git a/sites/backend/src/routes/index.js b/sites/backend/src/routes/index.js index 950627b1fc9..80f8143b278 100644 --- a/sites/backend/src/routes/index.js +++ b/sites/backend/src/routes/index.js @@ -6,6 +6,6 @@ import github from './github' import admin from './admin' import newsletter from './newsletter' import strapi from './strapi' -import og from "./og"; +import og from './og' export default { user, pattern, person, auth, github, admin, newsletter, strapi, og } diff --git a/sites/backend/src/routes/newsletter.js b/sites/backend/src/routes/newsletter.js index 5884b3409cb..52cf6e69cad 100644 --- a/sites/backend/src/routes/newsletter.js +++ b/sites/backend/src/routes/newsletter.js @@ -1,6 +1,6 @@ import Controller from '../controllers/newsletter' -const Nws= new Controller() +const Nws = new Controller() export default (app, passport) => { // Email subscribe diff --git a/sites/backend/src/routes/og.js b/sites/backend/src/routes/og.js index 8431f15e453..72f1b7d7413 100644 --- a/sites/backend/src/routes/og.js +++ b/sites/backend/src/routes/og.js @@ -1,11 +1,9 @@ -import Controller from "../controllers/og"; +import Controller from '../controllers/og' // Note: Og = Open graph. See https://ogp.me/ -const Og = new Controller(); +const Og = new Controller() export default (app, passport) => { - // Load open graph image (requires no authentication) - app.get("/og-img/:lang/:site/*", Og.image); - + app.get('/og-img/:lang/:site/*', Og.image) } diff --git a/sites/backend/src/routes/strapi.js b/sites/backend/src/routes/strapi.js index 65a4767ec0c..a0a8049b9e0 100644 --- a/sites/backend/src/routes/strapi.js +++ b/sites/backend/src/routes/strapi.js @@ -1,6 +1,6 @@ import Controller from '../controllers/strapi' -const Strapi= new Controller() +const Strapi = new Controller() export default (app, passport) => { // Email subscribe diff --git a/sites/backend/src/templates/emailchange.js b/sites/backend/src/templates/emailchange.js index cf3456e36b3..afd2cb88d3a 100644 --- a/sites/backend/src/templates/emailchange.js +++ b/sites/backend/src/templates/emailchange.js @@ -4,7 +4,7 @@ const emailchange = { 'email.emailchangeCopy1', 'email.emailchangeActionText', 'email.questionsJustReply', - 'email.signature' + 'email.signature', ], html: ` @@ -71,7 +71,7 @@ __emailchangeCopy1__ __emailchangeActionLink__ -__questionsJustReply__` +__questionsJustReply__`, } export default emailchange diff --git a/sites/backend/src/templates/footer.js b/sites/backend/src/templates/footer.js index 375f34694f4..8cb96af50e4 100644 --- a/sites/backend/src/templates/footer.js +++ b/sites/backend/src/templates/footer.js @@ -29,7 +29,7 @@ const footer = {
`, - text: '' + text: '', } export default footer diff --git a/sites/backend/src/templates/goodbye.js b/sites/backend/src/templates/goodbye.js index 469b8e4de2d..60ed4f1db3b 100644 --- a/sites/backend/src/templates/goodbye.js +++ b/sites/backend/src/templates/goodbye.js @@ -39,7 +39,7 @@ const goodbye = { `, text: `__goodbyeTitle__ -__goodbyeCopy1__` +__goodbyeCopy1__`, } export default goodbye diff --git a/sites/backend/src/templates/header.js b/sites/backend/src/templates/header.js index 1c4652df347..2d27b0be6cc 100644 --- a/sites/backend/src/templates/header.js +++ b/sites/backend/src/templates/header.js @@ -113,7 +113,7 @@ const header = { `, - text: '' + text: '', } export default header diff --git a/sites/backend/src/templates/newsletter-subscribe.js b/sites/backend/src/templates/newsletter-subscribe.js index e67a5acc871..f4518091d28 100644 --- a/sites/backend/src/templates/newsletter-subscribe.js +++ b/sites/backend/src/templates/newsletter-subscribe.js @@ -56,7 +56,7 @@ If it was you, please click below to confirm your subscription: __newsletterConfirmationLink__ -` +`, } export default subscribe diff --git a/sites/backend/src/templates/newsletter-welcome.js b/sites/backend/src/templates/newsletter-welcome.js index e6188ef8a94..ce6a3470da4 100644 --- a/sites/backend/src/templates/newsletter-welcome.js +++ b/sites/backend/src/templates/newsletter-welcome.js @@ -38,7 +38,7 @@ If you'd like to catch up, we keep an online archive of previous editions at: ht You can unsubscribe at any time by visiting this link: __newsletterUnsubscribeLink__ -` +`, } export default welcome diff --git a/sites/backend/src/templates/passwordreset.js b/sites/backend/src/templates/passwordreset.js index c55e38a8fa1..347bff20fa9 100644 --- a/sites/backend/src/templates/passwordreset.js +++ b/sites/backend/src/templates/passwordreset.js @@ -4,7 +4,7 @@ const passwordreset = { 'passwordresetCopy1', 'passwordresetActionText', 'questionsJustReply', - 'signature' + 'signature', ], html: ` @@ -71,7 +71,7 @@ __passwordresetCopy1__ __passwordresetActionLink__ -__questionsJustReply__` +__questionsJustReply__`, } export default passwordreset diff --git a/sites/backend/src/templates/signup.js b/sites/backend/src/templates/signup.js index ba83ccaf269..f9d0fc368e9 100644 --- a/sites/backend/src/templates/signup.js +++ b/sites/backend/src/templates/signup.js @@ -65,7 +65,7 @@ __signupCopy1__ __signupActionLink__ -__questionsJustReply__` +__questionsJustReply__`, } export default signup diff --git a/sites/backend/src/utils/email/index.js b/sites/backend/src/utils/email/index.js index 2468ab37ed3..0fb20667b57 100644 --- a/sites/backend/src/utils/email/index.js +++ b/sites/backend/src/utils/email/index.js @@ -7,7 +7,7 @@ import sendEmailWith from './relays' const deliver = sendEmailWith(config.sendEmailWith) const email = {} -const loadTemplate = (type, format, language='en') => { +const loadTemplate = (type, format, language = 'en') => { let template = templates.header[format] + templates[type][format] + templates.footer[format] let toTranslate = templates[type].i18n.concat(templates.footer.i18n) let from = [] @@ -22,7 +22,7 @@ const loadTemplate = (type, format, language='en') => { } const replace = (text, from, to) => { - for (let id=0; id < from.length; id++) text = text.split(from[id]).join(to[id] || from[id]) + for (let id = 0; id < from.length; id++) text = text.split(from[id]).join(to[id] || from[id]) return text } @@ -36,7 +36,7 @@ email.signup = (recipient, language, id) => { link, i18n[language]['email.signupHeaderOpeningLine'], i18n[language]['email.signupHiddenIntro'], - i18n[language]['email.signupWhy'] + i18n[language]['email.signupWhy'], ] html = replace(html, from, to) text = replace(text, from, to) @@ -45,10 +45,10 @@ email.signup = (recipient, language, id) => { to: recipient, subject: i18n[language]['email.signupSubject'], headers: { - 'X-Freesewing-Confirmation-ID': '' + id + 'X-Freesewing-Confirmation-ID': '' + id, }, text, - html + html, } deliver(options, (error, info) => { if (error) return console.log(error) @@ -68,7 +68,7 @@ email.emailchange = (newAddress, currentAddress, language, id) => { '__hiddenIntro__', '__footerWhy__', '__questionsJustReply__', - '__signature__' + '__signature__', ] let to = [ createUrl(language, `/confirm/email/${id}`), @@ -90,10 +90,10 @@ email.emailchange = (newAddress, currentAddress, language, id) => { cc: currentAddress, subject: i18n[language]['email.emailchangeSubject'], headers: { - 'X-Freesewing-Confirmation-ID': '' + id + 'X-Freesewing-Confirmation-ID': '' + id, }, text, - html + html, } deliver(options, (error, info) => { if (error) return console.log(error) @@ -108,13 +108,13 @@ email.passwordreset = (recipient, language, id) => { '__passwordresetActionLink__', '__headerOpeningLine__', '__hiddenIntro__', - '__footerWhy__' + '__footerWhy__', ] let to = [ createUrl(language, `/confirm/reset/${id}`), i18n[language]['email.passwordresetHeaderOpeningLine'], i18n[language]['email.passwordresetHiddenIntro'], - i18n[language]['email.passwordresetWhy'] + i18n[language]['email.passwordresetWhy'], ] html = replace(html, from, to) text = replace(text, from, to) @@ -124,10 +124,10 @@ email.passwordreset = (recipient, language, id) => { to: recipient, subject: i18n[language]['email.passwordresetSubject'], headers: { - 'X-Freesewing-Confirmation-ID': '' + id + 'X-Freesewing-Confirmation-ID': '' + id, }, text, - html + html, } deliver(options, (error, info) => { if (error) return console.log(error) @@ -142,7 +142,7 @@ email.goodbye = async (recipient, language) => { let to = [ i18n[language]['email.goodbyeHeaderOpeningLine'], i18n[language]['email.goodbyeHiddenIntro'], - i18n[language]['email.goodbyeWhy'] + i18n[language]['email.goodbyeWhy'], ] html = replace(html, from, to) text = replace(text, from, to) @@ -152,7 +152,7 @@ email.goodbye = async (recipient, language) => { to: recipient, subject: i18n[language]['email.goodbyeSubject'], text, - html + html, } deliver(options, (error, info) => { if (error) return console.log(error) @@ -163,12 +163,17 @@ email.goodbye = async (recipient, language) => { email.subscribe = async (recipient, token) => { let html = loadTemplate('newsletterSubscribe', 'html', 'en') let text = loadTemplate('newsletterSubscribe', 'text', 'en') - let from = ['__hiddenIntro__', '__headerOpeningLine__', '__newsletterConfirmationLink__', '__footerWhy__'] + let from = [ + '__hiddenIntro__', + '__headerOpeningLine__', + '__newsletterConfirmationLink__', + '__footerWhy__', + ] let to = [ 'Confirm your subscription to the FreeSewing newsletter', 'Please confirm it was you who requested this', `https://backend.freesewing.org/newsletter/confirm/${token}`, - `You received this email because somebody tried to subscribe ${recipient} to the FreeSewing newsletter` + `You received this email because somebody tried to subscribe ${recipient} to the FreeSewing newsletter`, ] html = replace(html, from, to) text = replace(text, from, to) @@ -178,7 +183,7 @@ email.subscribe = async (recipient, token) => { to: recipient, subject: 'Confirm your subscription to the FreeSewing newsletter', text, - html + html, } deliver(options, (error, info) => { if (error) return console.log(error) @@ -189,12 +194,17 @@ email.subscribe = async (recipient, token) => { email.newsletterWelcome = async (recipient, ehash) => { let html = loadTemplate('newsletterWelcome', 'html', 'en') let text = loadTemplate('newsletterWelcome', 'text', 'en') - let from = ['__hiddenIntro__', '__headerOpeningLine__', '__newsletterUnsubscribeLink__', '__footerWhy__'] + let from = [ + '__hiddenIntro__', + '__headerOpeningLine__', + '__newsletterUnsubscribeLink__', + '__footerWhy__', + ] let to = [ 'No action required; This is just an FYI', "You're in. Now what?", `https://backend.freesewing.org/newsletter/unsubscribe/${ehash}`, - `You received this email because you subscribed to the FreeSewing newsletter` + `You received this email because you subscribed to the FreeSewing newsletter`, ] html = replace(html, from, to) text = replace(text, from, to) @@ -204,7 +214,7 @@ email.newsletterWelcome = async (recipient, ehash) => { to: recipient, subject: 'Welcome to the FreeSewing newsletter', text, - html + html, } deliver(options, (error, info) => { if (error) return console.log(error) diff --git a/sites/backend/src/utils/email/relays.js b/sites/backend/src/utils/email/relays.js index c9dc4a322a2..0ceacbfbb56 100644 --- a/sites/backend/src/utils/email/relays.js +++ b/sites/backend/src/utils/email/relays.js @@ -1,9 +1,9 @@ import smtp from './smtp' //import sendgrid from './sendgrid' -const sendEmailWith = type => { +const sendEmailWith = (type) => { const types = { - smtp + smtp, //sendgrid, } return types[type] diff --git a/sites/backend/src/utils/email/sendgrid.js b/sites/backend/src/utils/email/sendgrid.js index 84b38eef507..b9592f1e4f5 100644 --- a/sites/backend/src/utils/email/sendgrid.js +++ b/sites/backend/src/utils/email/sendgrid.js @@ -4,13 +4,13 @@ import config from '../../config' sendgrid.setApiKey(config.sendgrid) const deliver = (data, callback) => { - sendgrid.send(data).then(result => { + sendgrid.send(data).then((result) => { // FIXME: This is obviously nonsense if (result[0].statusCode === 202) callback(false, { from: data.from, to: data.to, - subject: data.subject + subject: data.subject, }) else callback(true, 'Sending via SendGridfailed') }) diff --git a/sites/backend/src/utils/email/smtp.js b/sites/backend/src/utils/email/smtp.js index 5053fca7967..6ea7979558d 100644 --- a/sites/backend/src/utils/email/smtp.js +++ b/sites/backend/src/utils/email/smtp.js @@ -7,8 +7,8 @@ const transporter = nodemailer.createTransport({ secure: false, // Only needed or SSL, not for TLS auth: { user: config.smtp.user, - pass: config.smtp.pass - } + pass: config.smtp.pass, + }, }) const deliver = (data, callback) => { diff --git a/sites/backend/src/utils/index.js b/sites/backend/src/utils/index.js index b68a3c662c9..10dc8c35cb8 100644 --- a/sites/backend/src/utils/index.js +++ b/sites/backend/src/utils/index.js @@ -12,7 +12,7 @@ import avatar from '../templates/avatar' export const email = mailer export const log = logger -export const capitalize = string => string.charAt(0).toUpperCase() + string.slice(1) +export const capitalize = (string) => string.charAt(0).toUpperCase() + string.slice(1) export const createUrl = (language, path) => { // Handle development mode @@ -20,27 +20,27 @@ export const createUrl = (language, path) => { else return config.website.scheme + '://' + language + '.' + config.website.domain + path } -export const getHash = email => { +export const getHash = (email) => { let hash = crypto.createHash('sha256') hash.update(clean(email)) return hash.digest('hex') } -export const clean = email => email.toLowerCase().trim() +export const clean = (email) => email.toLowerCase().trim() -export const getToken = account => { +export const getToken = (account) => { return jwt.sign( { _id: account._id, handle: account.handle, aud: config.jwt.audience, - iss: config.jwt.issuer + iss: config.jwt.issuer, }, config.jwt.secretOrKey ) } -export const getHandle = type => { +export const getHandle = (type) => { let go, handle, exists if (type === 'person') go = Person else if (type === 'pattern') go = Pattern @@ -65,7 +65,7 @@ export const createHandle = (length = 5) => { return handle } -export const imageType = contentType => { +export const imageType = (contentType) => { if (contentType === 'image/png') return 'png' if (contentType === 'image/jpeg') return 'jpg' if (contentType === 'image/gif') return 'gif' @@ -74,7 +74,7 @@ export const imageType = contentType => { } export const saveAvatarFromBase64 = (data, handle, type) => { - fs.mkdir(userStoragePath(handle), { recursive: true }, err => { + fs.mkdir(userStoragePath(handle), { recursive: true }, (err) => { if (err) log.error('mkdirFailed', err) let imgBuffer = Buffer.from(data, 'base64') for (let size of Object.keys(config.avatar.sizes)) { @@ -98,7 +98,7 @@ export const randomColor = () => (0x1000000 + Math.random() * 0xffffff).toString export const randomAvatar = () => avatar.replace('000000', randomColor()).replace('FFFFFF', randomColor()) -export const ehash = email => { +export const ehash = (email) => { let hash = crypto.createHash('sha256') hash.update(clean(email)) return hash.digest('hex') @@ -126,14 +126,14 @@ export const uniqueHandle = () => { return handle } -export const userStoragePath = handle => +export const userStoragePath = (handle) => path.join(config.storage, 'users', handle.substring(0, 1), handle) -export const createAvatar = handle => { +export const createAvatar = (handle) => { let dir = userStoragePath(handle) - fs.mkdir(dir, { recursive: true }, err => { + fs.mkdir(dir, { recursive: true }, (err) => { if (err) console.log('mkdirFailed', dir, err) - fs.writeFile(path.join(dir, handle) + '.svg', randomAvatar(), err => { + fs.writeFile(path.join(dir, handle) + '.svg', randomAvatar(), (err) => { if (err) console.log('writeFileFailed', dir, err) }) }) diff --git a/sites/backend/tests/admin.test.js b/sites/backend/tests/admin.test.js index fd2cf416ae5..9c9c73d85bf 100644 --- a/sites/backend/tests/admin.test.js +++ b/sites/backend/tests/admin.test.js @@ -1,12 +1,12 @@ module.exports = function tests(store, config, chai) { describe('Admin routes', () => { - it('should login ad admin', done => { + it('should login ad admin', (done) => { chai .request(config.backend) .post('/login') .send({ username: 'admin', - password: 'admin' + password: 'admin', }) .end((err, res) => { console.log(res) @@ -15,7 +15,7 @@ module.exports = function tests(store, config, chai) { }) }) - it('should load a user account', done => { + it('should load a user account', (done) => { chai .request(config.backend) .get('/admin/users/rracx') diff --git a/sites/backend/tests/config.js b/sites/backend/tests/config.js index d3de6391563..13269f57c64 100644 --- a/sites/backend/tests/config.js +++ b/sites/backend/tests/config.js @@ -9,23 +9,23 @@ module.exports = { de: '🇩🇪', es: '🇪🇸', nl: '🇳🇱', - fr: '🇫🇷' + fr: '🇫🇷', }, strings: strings, user: { email: 'test@freesewing.org', changedEmail: 'changedtest@freesewing.org', password: 'test', - username: 'test_user' + username: 'test_user', }, oauth: { github: { - url: `https://github.com/login/oauth/authorize?client_id=${process.env.FS_GITHUB_CLIENT_ID}&redirect_uri=${process.env.FS_BACKEND}/oauth/callback/from/github&scope=read:user&state=` + url: `https://github.com/login/oauth/authorize?client_id=${process.env.FS_GITHUB_CLIENT_ID}&redirect_uri=${process.env.FS_BACKEND}/oauth/callback/from/github&scope=read:user&state=`, }, google: { - url: `https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=${process.env.FS_GOOGLE_CLIENT_ID}&redirect_uri=${process.env.FS_BACKEND}/oauth/callback/from/google&scope=https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email&access_type=online&state=` - } + url: `https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=${process.env.FS_GOOGLE_CLIENT_ID}&redirect_uri=${process.env.FS_BACKEND}/oauth/callback/from/google&scope=https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email&access_type=online&state=`, + }, }, avatar: - 'data:image/png;base64,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' + 'data:image/png;base64,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', } diff --git a/sites/backend/tests/env.js b/sites/backend/tests/env.js index 429f4b3cb89..4f0b08fcc3e 100644 --- a/sites/backend/tests/env.js +++ b/sites/backend/tests/env.js @@ -1,20 +1,20 @@ -process.env.FS_BACKEND = "http://localhost:3000"; -process.env.FS_STATIC = "https://static.freesewing.org"; -process.env.FS_STORAGE = "/tmp/backendstorage"; -process.env.FS_MONGO_URI = "mongodb://localhost:27017/freesewing"; -process.env.FS_ENC_KEY = "longRandomStringHere"; -process.env.FS_STRAPI_HOST = "posts.freesewing.org"; -process.env.FS_STRAPI_PROTOCOL = "https"; -process.env.FS_STRAPI_PORT = "443"; -process.env.FS_STRAPI_USERNAME = "REPLACEME"; -process.env.FS_STRAPI_PASSWORD = "REPLACEME"; -process.env.FS_STRAPI_TMP = "/fs/ramdisk"; -process.env.FS_SMTP_USER = "smtpRelayUsername"; -process.env.FS_SMTP_PASS = "smtpRelayPassword"; -process.env.FS_SMTP_HOST = "smtp.relay.somedomain.com"; -process.env.FS_GITHUB_TOKEN = "githubTokenHere"; -process.env.FS_GITHUB_CLIENT_ID = "githubClientIdHere"; -process.env.FS_GITHUB_CLIENT_SECRET = "githubClientSecretHere"; -process.env.FS_GOOGLE_CLIENT_ID = "googleClientIdHere"; -process.env.FS_GOOGLE_CLIENT_SECRET = "googleClientSecretHere"; -process.env.FS_JWT_ISSUER = "freesewing.org"; +process.env.FS_BACKEND = 'http://localhost:3000' +process.env.FS_STATIC = 'https://static.freesewing.org' +process.env.FS_STORAGE = '/tmp/backendstorage' +process.env.FS_MONGO_URI = 'mongodb://localhost:27017/freesewing' +process.env.FS_ENC_KEY = 'longRandomStringHere' +process.env.FS_STRAPI_HOST = 'posts.freesewing.org' +process.env.FS_STRAPI_PROTOCOL = 'https' +process.env.FS_STRAPI_PORT = '443' +process.env.FS_STRAPI_USERNAME = 'REPLACEME' +process.env.FS_STRAPI_PASSWORD = 'REPLACEME' +process.env.FS_STRAPI_TMP = '/fs/ramdisk' +process.env.FS_SMTP_USER = 'smtpRelayUsername' +process.env.FS_SMTP_PASS = 'smtpRelayPassword' +process.env.FS_SMTP_HOST = 'smtp.relay.somedomain.com' +process.env.FS_GITHUB_TOKEN = 'githubTokenHere' +process.env.FS_GITHUB_CLIENT_ID = 'githubClientIdHere' +process.env.FS_GITHUB_CLIENT_SECRET = 'githubClientSecretHere' +process.env.FS_GOOGLE_CLIENT_ID = 'googleClientIdHere' +process.env.FS_GOOGLE_CLIENT_SECRET = 'googleClientSecretHere' +process.env.FS_JWT_ISSUER = 'freesewing.org' diff --git a/sites/backend/tests/oauth.test.js b/sites/backend/tests/oauth.test.js index 67fda68ee7c..9fdab34ba8b 100644 --- a/sites/backend/tests/oauth.test.js +++ b/sites/backend/tests/oauth.test.js @@ -1,13 +1,12 @@ module.exports = function tests(store, config, chai) { - describe('Oauth via Github', () => { - it('should trigger Oauth via Github', done => { + it('should trigger Oauth via Github', (done) => { chai .request(config.backend) .post('/oauth/init') .send({ provider: 'github', - language: 'en' + language: 'en', }) .end((err, res) => { res.should.have.status(200) @@ -18,13 +17,13 @@ module.exports = function tests(store, config, chai) { }) }) - it('should trigger Oauth via Google', done => { + it('should trigger Oauth via Google', (done) => { chai .request(config.backend) .post('/oauth/init') .send({ provider: 'github', - language: 'en' + language: 'en', }) .end((err, res) => { res.should.have.status(200) diff --git a/sites/backend/tests/pattern.test.js b/sites/backend/tests/pattern.test.js index 3676039dc2b..5b291b07088 100644 --- a/sites/backend/tests/pattern.test.js +++ b/sites/backend/tests/pattern.test.js @@ -1,6 +1,6 @@ module.exports = function tests(store, config, chai) { describe('Pattern endpoints', () => { - it('should create a pattern', done => { + it('should create a pattern', (done) => { chai .request(config.backend) .post('/patterns') @@ -10,8 +10,8 @@ module.exports = function tests(store, config, chai) { person: 'Someone', notes: 'Some notes', data: { - test: 'value' - } + test: 'value', + }, }) .end((err, res) => { res.should.have.status(200) @@ -24,13 +24,13 @@ module.exports = function tests(store, config, chai) { }) }) - it('should update the pattern name', done => { + it('should update the pattern name', (done) => { chai .request(config.backend) .put('/patterns/' + config.user.pattern) .set('Authorization', 'Bearer ' + config.user.token) .send({ - name: 'New name' + name: 'New name', }) .end((err, res) => { res.should.have.status(200) @@ -41,13 +41,13 @@ module.exports = function tests(store, config, chai) { }) }) - it('should update the pattern notes', done => { + it('should update the pattern notes', (done) => { chai .request(config.backend) .put('/patterns/' + config.user.pattern) .set('Authorization', 'Bearer ' + config.user.token) .send({ - notes: 'These are the notes' + notes: 'These are the notes', }) .end((err, res) => { res.should.have.status(200) @@ -58,7 +58,7 @@ module.exports = function tests(store, config, chai) { }) }) - it('should load the pattern data without authentication', done => { + it('should load the pattern data without authentication', (done) => { chai .request(config.backend) .get('/patterns/' + config.user.pattern) @@ -71,7 +71,7 @@ module.exports = function tests(store, config, chai) { }) }) - it('should delete the pattern', done => { + it('should delete the pattern', (done) => { chai .request(config.backend) .delete('/patterns/' + config.user.pattern) @@ -82,7 +82,7 @@ module.exports = function tests(store, config, chai) { }) }) - it('should no longer have this pattern', done => { + it('should no longer have this pattern', (done) => { chai .request(config.backend) .get('/patterns/' + config.user.pattern) diff --git a/sites/backend/tests/person.test.js b/sites/backend/tests/person.test.js index 5b43947ebdd..63309eb5911 100644 --- a/sites/backend/tests/person.test.js +++ b/sites/backend/tests/person.test.js @@ -2,7 +2,7 @@ module.exports = function tests(store, config, chai) { const should = chai.should() describe('Person endpoints', () => { - it('should create a person', done => { + it('should create a person', (done) => { chai .request(config.backend) .post('/people') @@ -10,7 +10,7 @@ module.exports = function tests(store, config, chai) { .send({ name: 'Test person', units: 'imperial', - breasts: true + breasts: true, }) .end((err, res) => { res.should.have.status(200) @@ -27,13 +27,13 @@ module.exports = function tests(store, config, chai) { }) }) - it('should update the person name', done => { + it('should update the person name', (done) => { chai .request(config.backend) .put('/people/' + config.user.person) .set('Authorization', 'Bearer ' + config.user.token) .send({ - name: 'New person name' + name: 'New person name', }) .end((err, res) => { res.should.have.status(200) @@ -44,13 +44,13 @@ module.exports = function tests(store, config, chai) { }) }) - it('should update the person chest', done => { + it('should update the person chest', (done) => { chai .request(config.backend) .put('/people/' + config.user.person) .set('Authorization', 'Bearer ' + config.user.token) .send({ - breasts: 'false' + breasts: 'false', }) .end((err, res) => { res.should.have.status(200) @@ -61,13 +61,13 @@ module.exports = function tests(store, config, chai) { }) }) - it('should update the person units', done => { + it('should update the person units', (done) => { chai .request(config.backend) .put('/people/' + config.user.person) .set('Authorization', 'Bearer ' + config.user.token) .send({ - units: 'metric' + units: 'metric', }) .end((err, res) => { res.should.have.status(200) @@ -78,13 +78,13 @@ module.exports = function tests(store, config, chai) { }) }) - it('should update the person notes', done => { + it('should update the person notes', (done) => { chai .request(config.backend) .put('/people/' + config.user.person) .set('Authorization', 'Bearer ' + config.user.token) .send({ - notes: 'These are the notes' + notes: 'These are the notes', }) .end((err, res) => { res.should.have.status(200) @@ -95,7 +95,7 @@ module.exports = function tests(store, config, chai) { }) }) - it('should update the person measurements', done => { + it('should update the person measurements', (done) => { chai .request(config.backend) .put('/people/' + config.user.person) @@ -103,8 +103,8 @@ module.exports = function tests(store, config, chai) { .send({ measurements: { shoulderToShoulder: 456, - neck: 345 - } + neck: 345, + }, }) .end((err, res) => { res.should.have.status(200) @@ -116,15 +116,15 @@ module.exports = function tests(store, config, chai) { }) }) - it('should not set a non-existing measurement', done => { + it('should not set a non-existing measurement', (done) => { chai .request(config.backend) .put('/people/' + config.user.person) .set('Authorization', 'Bearer ' + config.user.token) .send({ measurements: { - hairLength: 12 - } + hairLength: 12, + }, }) .end((err, res) => { res.should.have.status(200) @@ -137,13 +137,13 @@ module.exports = function tests(store, config, chai) { }) }) - it('should update the person avatar', done => { + it('should update the person avatar', (done) => { chai .request(config.backend) .put('/people/' + config.user.person) .set('Authorization', 'Bearer ' + config.user.token) .send({ - picture: config.avatar + picture: config.avatar, }) .end((err, res) => { res.should.have.status(200) @@ -155,7 +155,7 @@ module.exports = function tests(store, config, chai) { }) }) - it('should load the person data', done => { + it('should load the person data', (done) => { chai .request(config.backend) .get('/people/' + config.user.person) @@ -170,7 +170,7 @@ module.exports = function tests(store, config, chai) { }) }) - it('should delete the person', done => { + it('should delete the person', (done) => { chai .request(config.backend) .delete('/people/' + config.user.person) @@ -181,7 +181,7 @@ module.exports = function tests(store, config, chai) { }) }) - it('should no longer have this person', done => { + it('should no longer have this person', (done) => { chai .request(config.backend) .get('/people/' + config.user.person) diff --git a/sites/backend/tests/user.all.test.js b/sites/backend/tests/user.all.test.js index 286f14cabc4..6cc6cf8ba76 100644 --- a/sites/backend/tests/user.all.test.js +++ b/sites/backend/tests/user.all.test.js @@ -5,17 +5,17 @@ module.exports = function tests(store, config, chai) { for (let lang in config.languages) { store[lang] = { email: lang + email, - password: 'test' + password: 'test', } - it(config.languages[lang] + ' => should create a pending signup', done => { + it(config.languages[lang] + ' => should create a pending signup', (done) => { chai .request(config.backend) .post('/signup') .send({ email: store[lang].email, password: store[lang].password, - language: lang + language: lang, }) .end((err, res) => { res.should.have.status(200) @@ -24,14 +24,14 @@ module.exports = function tests(store, config, chai) { }) }) - it(config.languages[lang] + ' => should detect a pre-existing signup', done => { + it(config.languages[lang] + ' => should detect a pre-existing signup', (done) => { chai .request(config.backend) .post('/signup') .send({ email: store[lang].email, password: store[lang].password, - language: lang + language: lang, }) .end((err, res) => { res.should.have.status(400) @@ -43,13 +43,13 @@ module.exports = function tests(store, config, chai) { }) describe(`Send out emails for other tests that rely on email delivery`, () => { - it('should fetch the JWT token for test_user', done => { + it('should fetch the JWT token for test_user', (done) => { chai .request(config.backend) .post('/login') .send({ username: config.user.username, - password: config.user.password + password: config.user.password, }) .end((err, res) => { res.should.have.status(200) @@ -59,13 +59,13 @@ module.exports = function tests(store, config, chai) { }) }) - it('should trigger the email change confirmation email', done => { + it('should trigger the email change confirmation email', (done) => { chai .request(config.backend) .put('/account') .set('Authorization', 'Bearer ' + store.emailChange.token) .send({ - email: config.user.changedEmail + email: config.user.changedEmail, }) .end((err, res) => { res.should.have.status(200) @@ -75,7 +75,7 @@ module.exports = function tests(store, config, chai) { }) describe(`Take a ${config.sleep} second power nap while we wait for the emails to be delivered`, () => { - it(`should sleep for ${config.sleep} seconds to allow the emails to arrive`, done => { + it(`should sleep for ${config.sleep} seconds to allow the emails to arrive`, (done) => { console.log('\n 😴 \n') setTimeout(() => { done() @@ -85,7 +85,7 @@ module.exports = function tests(store, config, chai) { for (let lang in config.languages) { it( config.languages[lang] + ' => should have sent out an email to the signup email address', - done => { + (done) => { let url = `/api/v2/search?kind=to&query=${lang}${email}` chai .request(config.mailhog) @@ -100,9 +100,8 @@ module.exports = function tests(store, config, chai) { message.Content.Headers.Subject[0].should.equal( config.strings[lang]['email.signupSubject'] ) - store[lang].confirmation = message.Content.Headers[ - 'X-Freesewing-Confirmation-ID' - ].pop() + store[lang].confirmation = + message.Content.Headers['X-Freesewing-Confirmation-ID'].pop() done() }) } @@ -111,12 +110,12 @@ module.exports = function tests(store, config, chai) { it( config.languages[lang] + ' => should not activate the pending confirmation without consent', - done => { + (done) => { chai .request(config.backend) .post('/account') .send({ - id: store[lang].confirmation + id: store[lang].confirmation, }) .end((err, res) => { res.should.have.status(400) @@ -126,15 +125,15 @@ module.exports = function tests(store, config, chai) { } ) - it(config.languages[lang] + ' => should activate the pending confirmation', done => { + it(config.languages[lang] + ' => should activate the pending confirmation', (done) => { chai .request(config.backend) .post('/account') .send({ id: store[lang].confirmation, consent: { - profile: true - } + profile: true, + }, }) .end((err, res) => { res.should.have.status(200) @@ -161,7 +160,7 @@ module.exports = function tests(store, config, chai) { }) } - it('should have sent out an email to confirm the email change', done => { + it('should have sent out an email to confirm the email change', (done) => { chai .request(config.mailhog) .get(`/api/v2/search?kind=to&query=${config.user.changedEmail}`) diff --git a/sites/backend/tests/user.test.js b/sites/backend/tests/user.test.js index ad23717d604..7950a91fbb0 100644 --- a/sites/backend/tests/user.test.js +++ b/sites/backend/tests/user.test.js @@ -1,12 +1,12 @@ module.exports = function tests(store, config, chai) { describe('Non language-specific User controller signup routes', () => { - it('should not create signup without email address', done => { + it('should not create signup without email address', (done) => { chai .request(config.backend) .post('/signup') .send({ password: config.user.password, - language: 'en' + language: 'en', }) .end((err, res) => { res.should.have.status(400) @@ -15,13 +15,13 @@ module.exports = function tests(store, config, chai) { }) }) - it('should not create signup without password', done => { + it('should not create signup without password', (done) => { chai .request(config.backend) .post('/signup') .send({ email: config.user.email, - language: 'en' + language: 'en', }) .end((err, res) => { res.should.have.status(400) @@ -30,13 +30,13 @@ module.exports = function tests(store, config, chai) { }) }) - it('should not create signup without language', done => { + it('should not create signup without language', (done) => { chai .request(config.backend) .post('/signup') .send({ email: config.user.email, - password: config.user.password + password: config.user.password, }) .end((err, res) => { res.should.have.status(400) @@ -47,13 +47,13 @@ module.exports = function tests(store, config, chai) { }) describe('Login/Logout and session handling', () => { - it('should login with the username', done => { + it('should login with the username', (done) => { chai .request(config.backend) .post('/login') .send({ username: config.user.username, - password: config.user.password + password: config.user.password, }) .end((err, res) => { res.should.have.status(200) @@ -65,13 +65,13 @@ module.exports = function tests(store, config, chai) { }) }) - it('should login with the email address', done => { + it('should login with the email address', (done) => { chai .request(config.backend) .post('/login') .send({ username: config.user.email, - password: config.user.password + password: config.user.password, }) .end((err, res) => { res.should.have.status(200) @@ -82,7 +82,7 @@ module.exports = function tests(store, config, chai) { }) }) - it('should load account with JSON Web Token', done => { + it('should load account with JSON Web Token', (done) => { chai .request(config.backend) .get('/account') @@ -101,13 +101,13 @@ module.exports = function tests(store, config, chai) { }) describe('Account management', () => { - it('should update the account avatar', done => { + it('should update the account avatar', (done) => { chai .request(config.backend) .put('/account') .set('Authorization', 'Bearer ' + config.user.token) .send({ - avatar: config.avatar + avatar: config.avatar, }) .end((err, res) => { res.should.have.status(200) @@ -116,13 +116,13 @@ module.exports = function tests(store, config, chai) { done() }) }) - it('should update the account username', done => { + it('should update the account username', (done) => { chai .request(config.backend) .put('/account') .set('Authorization', 'Bearer ' + config.user.token) .send({ - username: config.user.username + '_updated' + username: config.user.username + '_updated', }) .end((err, res) => { res.should.have.status(200) @@ -132,13 +132,13 @@ module.exports = function tests(store, config, chai) { }) }) - it('should restore the account username', done => { + it('should restore the account username', (done) => { chai .request(config.backend) .put('/account') .set('Authorization', 'Bearer ' + config.user.token) .send({ - username: config.user.username + username: config.user.username, }) .end((err, res) => { res.should.have.status(200) @@ -148,13 +148,13 @@ module.exports = function tests(store, config, chai) { }) }) - it('should not update the account username if that username is taken', done => { + it('should not update the account username if that username is taken', (done) => { chai .request(config.backend) .put('/account') .set('Authorization', 'Bearer ' + config.user.token) .send({ - username: 'admin' + username: 'admin', }) .end((err, res) => { res.should.have.status(400) @@ -163,14 +163,14 @@ module.exports = function tests(store, config, chai) { }) }) - it('should update the account bio', done => { + it('should update the account bio', (done) => { let bio = 'This is the test bio ' chai .request(config.backend) .put('/account') .set('Authorization', 'Bearer ' + config.user.token) .send({ - bio: bio + bio: bio, }) .end((err, res) => { res.should.have.status(200) @@ -180,15 +180,15 @@ module.exports = function tests(store, config, chai) { }) }) - it('should update the account language', done => { + it('should update the account language', (done) => { chai .request(config.backend) .put('/account') .set('Authorization', 'Bearer ' + config.user.token) .send({ settings: { - language: 'nl' - } + language: 'nl', + }, }) .end((err, res) => { res.should.have.status(200) @@ -198,15 +198,15 @@ module.exports = function tests(store, config, chai) { }) }) - it('should update the account units', done => { + it('should update the account units', (done) => { chai .request(config.backend) .put('/account') .set('Authorization', 'Bearer ' + config.user.token) .send({ settings: { - units: 'imperial' - } + units: 'imperial', + }, }) .end((err, res) => { res.should.have.status(200) @@ -217,7 +217,7 @@ module.exports = function tests(store, config, chai) { }) for (let network of ['github', 'twitter', 'instagram']) { - it(`should update the account's ${network} username`, done => { + it(`should update the account's ${network} username`, (done) => { let data = { social: {} } data.social[network] = network chai @@ -233,13 +233,13 @@ module.exports = function tests(store, config, chai) { }) } - it('should update the account password', done => { + it('should update the account password', (done) => { chai .request(config.backend) .put('/account') .set('Authorization', 'Bearer ' + config.user.token) .send({ - password: 'changeme' + password: 'changeme', }) .end((err, res) => { res.should.have.status(200) @@ -247,13 +247,13 @@ module.exports = function tests(store, config, chai) { }) }) - it('should login with the new password', done => { + it('should login with the new password', (done) => { chai .request(config.backend) .post('/login') .send({ username: config.user.username, - password: 'changeme' + password: 'changeme', }) .end((err, res) => { res.should.have.status(200) @@ -261,13 +261,13 @@ module.exports = function tests(store, config, chai) { }) }) - it('should restore the account password', done => { + it('should restore the account password', (done) => { chai .request(config.backend) .put('/account') .set('Authorization', 'Bearer ' + config.user.token) .send({ - password: config.user.password + password: config.user.password, }) .end((err, res) => { res.should.have.status(200) @@ -277,7 +277,7 @@ module.exports = function tests(store, config, chai) { }) describe('Other user endpoints', () => { - it("should load a user's profile", done => { + it("should load a user's profile", (done) => { chai .request(config.backend) .get('/users/admin') @@ -290,13 +290,13 @@ module.exports = function tests(store, config, chai) { }) }) - it('should confirm that a username is available', done => { + it('should confirm that a username is available', (done) => { chai .request(config.backend) .post('/available/username') .set('Authorization', 'Bearer ' + config.user.token) .send({ - username: Date.now() + ' ' + Date.now() + username: Date.now() + ' ' + Date.now(), }) .end((err, res) => { res.should.have.status(200) @@ -304,13 +304,13 @@ module.exports = function tests(store, config, chai) { }) }) - it('should confirm that a username is not available', done => { + it('should confirm that a username is not available', (done) => { chai .request(config.backend) .post('/available/username') .set('Authorization', 'Bearer ' + config.user.token) .send({ - username: 'admin' + username: 'admin', }) .end((err, res) => { res.should.have.status(400) @@ -318,7 +318,7 @@ module.exports = function tests(store, config, chai) { }) }) - it('should load the patron list', done => { + it('should load the patron list', (done) => { chai .request(config.backend) .get('/patrons') @@ -332,7 +332,7 @@ module.exports = function tests(store, config, chai) { }) }) - it('should export the user data', done => { + it('should export the user data', (done) => { chai .request(config.backend) .get('/account/export') diff --git a/tests/designs/drafting.mjs b/tests/designs/drafting.mjs index 095b24bcae6..b534e9577f0 100644 --- a/tests/designs/drafting.mjs +++ b/tests/designs/drafting.mjs @@ -1,4 +1,5 @@ import { adult, doll, giant } from '@freesewing/models' +import { getFamily, getShortName } from './config.mjs' import chai from 'chai' const expect = chai.expect @@ -10,12 +11,14 @@ const expect = chai.expect * @param object Pattern: pattern constructor * @param boolean log: Set to true to log errors */ -export const testPatternDrafting = (Pattern, log=false) => { - +export const testPatternDrafting = (Pattern, log = false) => { const pattern = new Pattern() const config = pattern.getConfig() + const design = getShortName(config.data.name) + const family = getFamily(design) + // Helper method to try/catch pattern drafting - const doesItDraftAndRender = (pattern, log=false) => { + const doesItDraftAndRender = (pattern, log = false) => { try { pattern.draft().render() if (pattern.store.logs.error.length < 1) return true @@ -31,8 +34,8 @@ export const testPatternDrafting = (Pattern, log=false) => { * Draft pattern for different models */ if (family !== 'utilities') { - describe('Draft for humans:', function() { - this.timeout(5000); + describe('Draft for humans:', function () { + this.timeout(5000) for (const type of ['cisFemale', 'cisMale']) { describe(type, () => { for (const size in adult[type]) { @@ -40,8 +43,9 @@ export const testPatternDrafting = (Pattern, log=false) => { expect( doesItDraftAndRender( new Pattern({ - measurements: adult[type][size] - }), log + measurements: adult[type][size], + }), + log ) ).to.equal(true) }) @@ -53,8 +57,8 @@ export const testPatternDrafting = (Pattern, log=false) => { // Do the same for fantastical models (doll, giant) const fams = { doll, giant } for (const family of ['doll', 'giant']) { - describe(`Draft for ${family}:`, function() { - this.timeout(5000); + describe(`Draft for ${family}:`, function () { + this.timeout(5000) for (const type of ['cisFemale', 'cisMale']) { describe(type, () => { for (const size in fams[family][type]) { @@ -62,8 +66,9 @@ export const testPatternDrafting = (Pattern, log=false) => { expect( doesItDraftAndRender( new Pattern({ - measurements: fams[family][type][size] - }), log + measurements: fams[family][type][size], + }), + log ) ).to.equal(true) }) @@ -89,11 +94,9 @@ export const testPatternDrafting = (Pattern, log=false) => { } } - - - /* - * Draft parts individually - */ +/* + * Draft parts individually + */ /* it('Draft parts individually:', () => true) for (const name of parts) { @@ -110,9 +113,9 @@ export const testPatternDrafting = (Pattern, log=false) => { } */ - /* - * Draft a paperless non-detailed pattern - */ +/* + * Draft a paperless non-detailed pattern + */ /* it('Draft paperless non-detailed pattern:', () => true) if (family !== 'utilities') { @@ -133,4 +136,3 @@ export const testPatternDrafting = (Pattern, log=false) => { } } */ - diff --git a/yarn.lock b/yarn.lock index 64dbeb8cc6c..0d07dc1582e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4114,7 +4114,7 @@ ansi-escapes@^3.0.0, ansi-escapes@^3.2.0: resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== -ansi-escapes@^4.2.1, ansi-escapes@^4.3.1: +ansi-escapes@^4.2.1, ansi-escapes@^4.3.0, ansi-escapes@^4.3.1: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== @@ -4552,6 +4552,11 @@ ast-types-flow@^0.0.7: resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" integrity sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag== +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + astring@^1.4.0, astring@^1.8.0: version "1.8.3" resolved "https://registry.yarnpkg.com/astring/-/astring-1.8.3.tgz#1a0ae738c7cc558f8e5ddc8e3120636f5cebcb85" @@ -5814,6 +5819,14 @@ cli-truncate@^0.2.1: slice-ansi "0.0.4" string-width "^1.0.1" +cli-truncate@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" + integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg== + dependencies: + slice-ansi "^3.0.0" + string-width "^4.2.0" + cli-truncate@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-3.1.0.tgz#3f23ab12535e3d73e839bb43e73c9de487db1389" @@ -5982,6 +5995,11 @@ color@^4.2, color@^4.2.3: color-convert "^2.0.1" color-string "^1.9.0" +colorette@^2.0.16, colorette@^2.0.17: + version "2.0.19" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" + integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== + colors-option@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/colors-option/-/colors-option-3.0.0.tgz#51f5d0d2b511a01859cdd70eaa9ed43ca4abf108" @@ -11534,6 +11552,11 @@ lie@~3.3.0: dependencies: immediate "~3.0.5" +lilconfig@2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.5.tgz#19e57fd06ccc3848fd1891655b5a447092225b25" + integrity sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg== + lilconfig@^2.0.5, lilconfig@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.6.tgz#32a384558bd58af3d4c6e077dd1ad1d397bc69d4" @@ -11557,6 +11580,25 @@ lines-and-columns@^2.0.2: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-2.0.3.tgz#b2f0badedb556b747020ab8ea7f0373e22efac1b" integrity sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w== +lint-staged@^13.0.3: + version "13.0.3" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-13.0.3.tgz#d7cdf03a3830b327a2b63c6aec953d71d9dc48c6" + integrity sha512-9hmrwSCFroTSYLjflGI8Uk+GWAwMB4OlpU4bMJEAT5d/llQwtYKoim4bLOyLCuWFAhWEupE0vkIFqtw/WIsPug== + dependencies: + cli-truncate "^3.1.0" + colorette "^2.0.17" + commander "^9.3.0" + debug "^4.3.4" + execa "^6.1.0" + lilconfig "2.0.5" + listr2 "^4.0.5" + micromatch "^4.0.5" + normalize-path "^3.0.0" + object-inspect "^1.12.2" + pidtree "^0.6.0" + string-argv "^0.3.1" + yaml "^2.1.1" + listr-silent-renderer@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e" @@ -11586,6 +11628,20 @@ listr-verbose-renderer@^0.5.0: date-fns "^1.27.2" figures "^2.0.0" +listr2@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-4.0.5.tgz#9dcc50221583e8b4c71c43f9c7dfd0ef546b75d5" + integrity sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA== + dependencies: + cli-truncate "^2.1.0" + colorette "^2.0.16" + log-update "^4.0.0" + p-map "^4.0.0" + rfdc "^1.3.0" + rxjs "^7.5.5" + through "^2.3.8" + wrap-ansi "^7.0.0" + listr@^0.14.3: version "0.14.3" resolved "https://registry.yarnpkg.com/listr/-/listr-0.14.3.tgz#2fea909604e434be464c50bddba0d496928fa586" @@ -11907,6 +11963,16 @@ log-update@^2.3.0: cli-cursor "^2.0.0" wrap-ansi "^3.0.1" +log-update@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1" + integrity sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg== + dependencies: + ansi-escapes "^4.3.0" + cli-cursor "^3.1.0" + slice-ansi "^4.0.0" + wrap-ansi "^6.2.0" + log-update@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/log-update/-/log-update-5.0.1.tgz#9e928bf70cb183c1f0c9e91d9e6b7115d597ce09" @@ -13025,7 +13091,7 @@ micromatch@^3.1.10, micromatch@^3.1.4: snapdragon "^0.8.1" to-regex "^3.0.2" -micromatch@^4.0.2, micromatch@^4.0.4: +micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5: version "4.0.5" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== @@ -14306,7 +14372,7 @@ object-hash@^3.0.0: resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9" integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== -object-inspect@^1.12.0, object-inspect@^1.9.0: +object-inspect@^1.12.0, object-inspect@^1.12.2, object-inspect@^1.9.0: version "1.12.2" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== @@ -15171,6 +15237,11 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +pidtree@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.6.0.tgz#90ad7b6d42d5841e69e0a2419ef38f8883aa057c" + integrity sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g== + pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -15407,7 +15478,7 @@ prepend-http@^2.0.0: resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" integrity sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA== -prettier@^2.3.0, prettier@^2.3.1: +prettier@^2.3.1, prettier@^2.7.1: version "2.7.1" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64" integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g== @@ -17429,6 +17500,24 @@ slice-ansi@0.0.4: resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" integrity sha512-up04hB2hR92PgjpyU3y/eg91yIBILyjVY26NvvciY3EVVPjybkMszMpXQ9QAkcS3I5rtJBDLoTxxg+qvW8c7rw== +slice-ansi@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787" + integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + slice-ansi@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-5.0.0.tgz#b73063c57aa96f9cd881654b15294d95d285c42a" @@ -17809,6 +17898,11 @@ strict-uri-encode@^2.0.0: resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" integrity sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ== +string-argv@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" + integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg== + string-similarity@^4.0.4: version "4.0.4" resolved "https://registry.yarnpkg.com/string-similarity/-/string-similarity-4.0.4.tgz#42d01ab0b34660ea8a018da8f56a3309bb8b2a5b" @@ -19888,7 +19982,7 @@ yaml@^1.10.0, yaml@^1.10.2: resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== -yaml@^2.0.0: +yaml@^2.0.0, yaml@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.1.1.tgz#1e06fb4ca46e60d9da07e4f786ea370ed3c3cfec" integrity sha512-o96x3OPo8GjWeSLF+wOAbrPfhFOGY0W00GNaxCDv+9hkcDJEnev1yh8S7pgHF0ik6zc8sQLuL8hjHjJULZp8bw==