From fb348aeae7df6e77d5a1f864e58e665ed20ca5e2 Mon Sep 17 00:00:00 2001 From: Raphael Voellmy Date: Sat, 5 Oct 2024 21:20:33 +0200 Subject: [PATCH] feat(chord diagram): implement fret markers --- README.md | 51 +- src/svguitar.ts | 330 ++++++++-- test/svguitar.test.ts | 1466 ++++++++++++++++++++++------------------- 3 files changed, 1108 insertions(+), 739 deletions(-) diff --git a/README.md b/README.md index 8bfe8dc..f08c262 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ Example chord charts: ``` -Of course you can also add SVGuitar as a dependency to your project: +Of course, you can also add SVGuitar as a dependency to your project: ```bash # Add the dependency to your project @@ -55,6 +55,9 @@ npm install --save svguitar # or yarn add svguitar + +# or +pnpm add svguitar ``` And then import it in your project: @@ -332,6 +335,52 @@ new SVGuitarChord('#some-selector') * The title of the SVG. This is not visible in the SVG, but can be used for accessibility. */ svgTitle: 'Guitar chord diagram of F# minor', + + + /** + * The fret markers. See type docs for more options. + */ + fretMarkers: [ + 2, 4, 6, 8, { + fret: 11, + double: true, + }, + ], + + /** + * The shape of the fret markets. Applies to all fret markets unless overridden + * on specific fret markers. Defaults to circles. + */ + fretMarkerShape: 'circle', + + /** + * The size of a fret marker. This is relative to the space between two strings, so + * a value of 1 means a fret marker spans from one string to another. + */ + fretMarkerSize: 0.4, + + /** + * The color of the fret markers. + */ + fretMarkerColor: 'rgba(0, 0, 0, 0.2)', + + /** + * The stroke color of the fret markers. By default, the fret markets have no border. + */ + fretMarkerStrokeColor: '#000000', + + /** + * The stroke width of the fret markers. By default, the fret markets have no border. + */ + fretMarkerStrokeWidth: 0, + + /** + * The distance between the double fret markers, relative to the width + * of the whole neck. E.g. 0.5 means the distance between the fret markers + * is equivalent to 0.5 times the width of the whole neck. + */ + doubleFretMarkerDistance: 0.4 + }) .draw() ``` diff --git a/src/svguitar.ts b/src/svguitar.ts index c0f57a5..2ba2d68 100644 --- a/src/svguitar.ts +++ b/src/svguitar.ts @@ -90,6 +90,57 @@ export enum FretLabelPosition { RIGHT = 'right', } +export type FretMarker = DoubleFretMarker | SingleFretMarker | number + +export interface SingleFretMarker { + /** + * Position of the fret marker. Starts at 0. + * Position of 0 means between fret 0 and 1. + */ + fret: number, + + /** + * The color of the fret marker. + */ + color?: string, + + /** + * The stroke color of the fret marker. + */ + strokeColor?: string, + /** + * The stroke color of the fret marker. + */ + strokeWidth?: number, + + /** + * Shape of the fret marker. Defaults to {@link Shape.CIRCLE} + */ + shape?: Shape + + /** + * The relative size of a fret marker + */ + size?: number + + /** + * Class name on the fret markers + */ + className?: string +} +export interface DoubleFretMarker extends SingleFretMarker { + /** + * Set to true if there should be two fret markers at this position + */ + double: true + + /** + * Distance between double fret markers. + * Overrides the default {@link ChordSettings#doubleFretMarkerDistance} + */ + distance?: number +} + export enum Shape { CIRCLE = 'circle', SQUARE = 'square', @@ -116,6 +167,7 @@ export enum ElementType { TITLE = 'title', TUNING = 'tuning', FRET_POSITION = 'fret-position', + FRET_MARKER = 'fret-marker', STRING_TEXT = 'string-text', SILENT_STRING = 'silent-string', OPEN_STRING = 'open-string', @@ -141,7 +193,47 @@ export interface ChordSettings { /** * The number of frets */ - frets?: number + frets?: number, + + /** + * The fret markers + */ + fretMarkers?: FretMarker[] + + /** + * The {@link Shape} of the fret markets. Applies to all fret markets unless overridden + * on specific fret markers. + */ + fretMarkerShape?: Shape, + + /** + * The size of a fret marker. This is relative to the space between two strings, so + * a value of 1 means a fret marker spans from one string to another. + */ + fretMarkerSize?: number, + + /** + * The color of the fret markers. + */ + fretMarkerColor?: string, + + /** + * The stroke color of the fret markers. By default, the fret markets have no border. + */ + fretMarkerStrokeColor?: string, + + /** + * The stroke width of the fret markers. By default, the fret markets have no border. + */ + fretMarkerStrokeWidth?: number, + + /** + * The distance between the double fret markers, relative to the width + * of the whole neck. E.g. 0.5 means the distance between the fret markers + * is equivalent to 0.5 times the width of the whole neck. + */ + doubleFretMarkerDistance?: number + /** * The starting fret (first fret is 1). The position can also be provided with the {@link Chord}. * If the position is provided via the chord, this value will be ignored. @@ -244,7 +336,7 @@ export interface ChordSettings { titleBottomMargin?: number /** - * Global color of the whole diagram. Can be overridden with more specifig color settings such as + * Global color of the whole diagram. Can be overridden with more specific color settings such as * @link titleColor or @link stringColor etc. */ color?: string @@ -378,6 +470,10 @@ interface RequiredChordSettings { orientation: Orientation watermarkFontSize: number noPosition: boolean + fretMarkerSize: number, + fretMarkerShape: Shape, + fretMarkerColor: string, + doubleFretMarkerDistance: number, } const defaultSettings: RequiredChordSettings = { @@ -408,6 +504,10 @@ const defaultSettings: RequiredChordSettings = { orientation: Orientation.vertical, watermarkFontSize: 12, noPosition: false, + fretMarkerColor: 'rgba(0, 0, 0, 0.2)', + fretMarkerSize: 0.4, + doubleFretMarkerDistance: 0.4, + fretMarkerShape: Shape.CIRCLE, } export class SVGuitarChord { @@ -541,13 +641,20 @@ export class SVGuitarChord { if (typeof settings.strokeWidth !== 'undefined' && settings.strokeWidth < 0) { throw new Error('Stroke width cannot be smaller than 0') } + + if (typeof settings.doubleFretMarkerDistance !== 'undefined' + && settings.doubleFretMarkerDistance < 0 + && settings.doubleFretMarkerDistance > 1 + ) { + throw new Error('Double fret marker distance has to be a number between [0, 1]') + } } private drawTunings(y: number) { // add some padding relative to the fret spacing const padding = this.fretSpacing() / 5 const stringXPositions = this.stringXPos() - const strings = this.settings.strings ?? defaultSettings.strings + const strings = this.numStrings() const color = this.settings.tuningsColor ?? this.settings.color ?? defaultSettings.color const tuning = this.settings.tuning ?? defaultSettings.tuning const fontFamily = this.settings.fontFamily ?? defaultSettings.fontFamily @@ -770,7 +877,7 @@ export class SVGuitarChord { } private stringXPos(): number[] { - const strings = this.settings.strings ?? defaultSettings.strings + const strings = this.numStrings() const sidePadding = this.settings.sidePadding ?? defaultSettings.sidePadding const startX = constants.width * sidePadding const stringsSpacing = this.stringSpacing() @@ -778,9 +885,13 @@ export class SVGuitarChord { return range(strings).map((i) => startX + stringsSpacing * i) } + private numStrings() { + return this.settings.strings ?? defaultSettings.strings + } + private stringSpacing(): number { const sidePadding = this.settings.sidePadding ?? defaultSettings.sidePadding - const strings = this.settings.strings ?? defaultSettings.strings + const strings = this.numStrings() const startX = constants.width * sidePadding const endX = constants.width - startX const width = endX - startX @@ -803,7 +914,7 @@ export class SVGuitarChord { } private toArrayIndex(stringIndex: number): number { - const strings = this.settings.strings ?? defaultSettings.strings + const strings = this.numStrings() return Math.abs(stringIndex - strings) } @@ -924,7 +1035,7 @@ export class SVGuitarChord { private drawGrid(y: number): number { const frets = this.settings.frets ?? defaultSettings.frets const fretSize = this.settings.fretSize ?? defaultSettings.fretSize - const relativefingerSize = this.settings.fingerSize ?? defaultSettings.fingerSize + const relativeFingerSize = this.settings.fingerSize ?? defaultSettings.fingerSize const stringXPositions = this.stringXPos() const fretYPositions = this.fretLinesYPos(y) const stringSpacing = this.stringSpacing() @@ -934,7 +1045,7 @@ export class SVGuitarChord { const startX = stringXPositions[0] const endX = stringXPositions[stringXPositions.length - 1] - const fingerSize = relativefingerSize * stringSpacing + const fingerSize = relativeFingerSize * stringSpacing const fingerColor = this.settings.fingerColor ?? this.settings.color ?? defaultSettings.color const fretColor = this.settings.fretColor ?? this.settings.color ?? defaultSettings.color const barreChordRadius = this.settings.barreChordRadius ?? defaultSettings.barreChordRadius @@ -1067,8 +1178,6 @@ export class SVGuitarChord { ...(fingerOptions.className ? [fingerOptions.className] : []), ] - // const { x: x0, y: y0 } = this.coordinates(fingerCenterX, fingerCenterY) - this.drawFinger( fingerCenterX, fingerCenterY, @@ -1081,9 +1190,98 @@ export class SVGuitarChord { ) }) + this.settings.fretMarkers + ?.forEach((fretMarker) => { + const fretMarkerOptions = (typeof fretMarker == 'number' ? { + fret: fretMarker, + } : fretMarker) as DoubleFretMarker | SingleFretMarker + + const fretMarkerIndex = fretMarkerOptions.fret + const fretMarkerCenterX = constants.width / 2 + const fretMarkerCenterY = y + (fretMarkerIndex + 1) * fretSpacing - fretSpacing / 2 + const fretMarkerSize = this.settings.fretMarkerSize ?? defaultSettings.fretMarkerSize + const fretMarkerColor = this.settings.fretMarkerColor ?? defaultSettings.fretMarkerColor + + const classNames = [ + ElementType.FRET_MARKER, + `${ElementType.FRET_MARKER}-fret-${fretMarkerIndex}`, + ...(fretMarkerOptions.className ?? []), + ] + + if ('double' in fretMarkerOptions) { + this.stringSpacing() + const doubleFretMarkerDistance = fretMarkerOptions.distance ?? this.settings.doubleFretMarkerDistance ?? defaultSettings.doubleFretMarkerDistance + + const neckWidth = (this.numStrings() - 1) * this.stringSpacing(); + const fretMarkerDistanceFromCenter = neckWidth * doubleFretMarkerDistance / 2 + + this.drawFretMarker( + fretMarkerCenterX - fretMarkerDistanceFromCenter, + fretMarkerCenterY, + fretMarkerSize, + fretMarkerColor, + fretMarker, + classNames + ) + this.drawFretMarker( + fretMarkerCenterX + fretMarkerDistanceFromCenter, + fretMarkerCenterY, + fretMarkerSize, + fretMarkerColor, + fretMarker, + classNames + ) + } else { + this.drawFretMarker( + fretMarkerCenterX, + fretMarkerCenterY, + fretMarkerSize, + fretMarkerColor, + fretMarker, + classNames + ) + } + }); + return y + height } + private drawFretMarker( + x: number, + y: number, + size: number, + color: string, + fretMarketOptions: FretMarker, + classNames: string[], + ) { + const markerOptions = typeof fretMarketOptions === 'number' ? {fret: fretMarketOptions} : fretMarketOptions + + const shape = markerOptions.shape ?? defaultSettings.fretMarkerShape + const fretMarkerColor = markerOptions.color ?? this.settings.fretMarkerColor ?? defaultSettings.fretMarkerColor + const fretMarkerStrokeColor = markerOptions.strokeColor ?? this.settings.fretMarkerStrokeColor ?? color + const fretMarkerStrokeWidth = markerOptions.strokeWidth ?? this.settings.fretMarkerStrokeWidth ?? 0 + + const fretMarkerSize = this.stringSpacing() * (markerOptions.size ?? size) + const startX = x - fretMarkerSize / 2 + const startY = y - fretMarkerSize / 2 + + const classNamesWithShape = [...classNames, `${ElementType.FRET_MARKER}-${shape}`] + + const { x: x0, y: y0 } = this.rectCoordinates(startX, startY, fretMarkerSize, fretMarkerSize) + + this.drawShape( + shape, + x0, + y0, + fretMarkerSize, + fretMarkerStrokeWidth, + fretMarkerStrokeColor, + fretMarkerColor ?? color, + classNamesWithShape + ) + + } + private drawFinger( x: number, y: number, @@ -1114,77 +1312,99 @@ export class SVGuitarChord { const { x: x0, y: y0 } = this.rectCoordinates(startX, startY, size, size) + this.drawShape( + shape, + x0, + y0, + size, + fingerStrokeWidth, + fingerStrokeColor, + fingerOptions.color ?? color, + classNamesWithShape + ) + + // draw text on the finger + const textClassNames = [...classNames, `${ElementType.FINGER}-text`] + if (fingerOptions.text) { + const { x: textX, y: textY } = this.coordinates(x, y) + + this.renderer.text( + fingerOptions.text, + textX, + textY, + textSize, + fingerOptions.textColor ?? fingerTextColor, + fontFamily, + Alignment.MIDDLE, + textClassNames, + true, + ) + } + } + + private drawShape( + shape: Shape, + x: number, + y: number, + size: number, + strokeWidth: number, + strokeColor: string, + fillColor: string, + classNames: string[] + ) { switch (shape) { case Shape.CIRCLE: this.renderer.circle( - x0, - y0, + x, + y, size, - fingerStrokeWidth, - fingerStrokeColor, - fingerOptions.color ?? color, - classNamesWithShape, + strokeWidth, + strokeColor, + fillColor, + classNames, ) break case Shape.SQUARE: this.renderer.rect( - x0, - y0, + x, + y, size, size, - fingerStrokeWidth, - fingerStrokeColor, - classNamesWithShape, - fingerOptions.color ?? color, + strokeWidth, + strokeColor, + classNames, + fillColor, ) break case Shape.TRIANGLE: this.renderer.triangle( - x0, - y0, + x, + y, size, - fingerStrokeWidth, - fingerStrokeColor, - classNamesWithShape, - fingerOptions.color ?? color, + strokeWidth, + strokeColor, + classNames, + fillColor, ) break case Shape.PENTAGON: this.renderer.pentagon( - x0, - y0, + x, + y, size, - fingerStrokeWidth, - fingerStrokeColor, - fingerOptions.color ?? color, - classNamesWithShape, + strokeWidth, + strokeColor, + fillColor, + classNames, ) break default: throw new Error( - `Invalid shape "${fingerOptions.shape}". Valid shapes are: ${Object.values(Shape) - .map((val) => `"${val}"`) - .join(', ')}.`, + `Invalid shape "${shape}". Valid shapes are: ${Object.values(Shape) + .map((val) => `"${val}"`) + .join(', ')}.`, ) } - - // draw text on the finger - const textClassNames = [...classNames, `${ElementType.FINGER}-text`] - if (fingerOptions.text) { - const { x: textX, y: textY } = this.coordinates(x, y) - - this.renderer.text( - fingerOptions.text, - textX, - textY, - textSize, - fingerOptions.textColor ?? fingerTextColor, - fontFamily, - Alignment.MIDDLE, - textClassNames, - true, - ) - } } private drawTitle(size: number): number { diff --git a/test/svguitar.test.ts b/test/svguitar.test.ts index b597ed5..d13e97f 100644 --- a/test/svguitar.test.ts +++ b/test/svguitar.test.ts @@ -28,423 +28,423 @@ describe('SVGuitarChord', () => { it('Should render an svg of an arbitrary chord', () => { svguitar - .chord({ - fingers: [ - [1, 2, '1'], - [2, 1, '2'], - [3, 2, '3'], - [4, 0], // fret 0 = open string - [5, 'x'], // fret x = muted string - ], - barres: [ - { - fret: 3, - fromString: 4, - toString: 1, - text: 'B', - }, - ], - }) - .configure({ - position: 5, - tuning: ['1', '2', '3', '4', '5', '6'], - strings: 5, - frets: 6, - title: 'Amaj7', - }) - .draw() + .chord({ + fingers: [ + [1, 2, '1'], + [2, 1, '2'], + [3, 2, '3'], + [4, 0], // fret 0 = open string + [5, 'x'], // fret x = muted string + ], + barres: [ + { + fret: 3, + fromString: 4, + toString: 1, + text: 'B', + }, + ], + }) + .configure({ + position: 5, + tuning: ['1', '2', '3', '4', '5', '6'], + strings: 5, + frets: 6, + title: 'Amaj7', + }) + .draw() saveSvg('arbitrary chord', container.outerHTML) }) it('Should render an svg of a horizontal chart', () => { svguitar - .chord({ - fingers: [ - [1, 2, '1'], - [2, 1, '2'], - [3, 2, '3'], - [4, 0], // fret 0 = open string - [5, 'x'], // fret x = muted string - ], - barres: [ - { - fret: 3, - fromString: 4, - toString: 1, - text: 'B', - }, - ], - }) - .configure({ - position: 5, - tuning: ['1', '2', '3', '4', '5', '6'], - orientation: Orientation.horizontal, - strings: 5, - frets: 6, - title: 'Amaj7', - }) - .draw() + .chord({ + fingers: [ + [1, 2, '1'], + [2, 1, '2'], + [3, 2, '3'], + [4, 0], // fret 0 = open string + [5, 'x'], // fret x = muted string + ], + barres: [ + { + fret: 3, + fromString: 4, + toString: 1, + text: 'B', + }, + ], + }) + .configure({ + position: 5, + tuning: ['1', '2', '3', '4', '5', '6'], + orientation: Orientation.horizontal, + strings: 5, + frets: 6, + title: 'Amaj7', + }) + .draw() saveSvg('horizontal chord', container.outerHTML) }) it('Should render an svg of a horizontal chart', () => { svguitar - .chord({ - fingers: [], - barres: [], - }) - .configure({ - fixedDiagramPosition: true, - orientation: Orientation.horizontal, - strings: 5, - frets: 6, - }) - .draw() + .chord({ + fingers: [], + barres: [], + }) + .configure({ + fixedDiagramPosition: true, + orientation: Orientation.horizontal, + strings: 5, + frets: 6, + }) + .draw() saveSvg('horizontal fixed diagram position', container.outerHTML) }) it('Should render the fret position correctly on the bottom', () => { svguitar - .chord({ - fingers: [], - barres: [], - }) - .configure({ - fixedDiagramPosition: true, - orientation: Orientation.horizontal, - fretLabelPosition: FretLabelPosition.LEFT, - strings: 5, - frets: 6, - position: 5, - }) - .draw() + .chord({ + fingers: [], + barres: [], + }) + .configure({ + fixedDiagramPosition: true, + orientation: Orientation.horizontal, + fretLabelPosition: FretLabelPosition.LEFT, + strings: 5, + frets: 6, + position: 5, + }) + .draw() saveSvg('horizontal bottom fret position', container.outerHTML) }) it('Should render fingers over barre chords', () => { svguitar - .chord({ - fingers: [[2, 1, { color: 'green', text: '1' }]], - barres: [ - { - fromString: 3, - toString: 1, - fret: 1, - color: 'blue', - }, - ], - }) - .configure({ - strings: 5, - frets: 6, - title: 'Finger over Barre Chord', - }) - .draw() + .chord({ + fingers: [[2, 1, {color: 'green', text: '1'}]], + barres: [ + { + fromString: 3, + toString: 1, + fret: 1, + color: 'blue', + }, + ], + }) + .configure({ + strings: 5, + frets: 6, + title: 'Finger over Barre Chord', + }) + .draw() saveSvg('finger over barre', container.outerHTML) }) it('Should render text on the fingers', () => { svguitar - .chord({ - fingers: [ - [1, 2, 'A'], - [2, 1, 'B'], - [3, 2, 'C'], - [4, 0], // fret 0 = open string - [5, 'x'], // fret x = muted string - ], - barres: [], - }) - .configure({ - strings: 5, - frets: 6, - title: 'Text on Fingers', - fingerTextColor: 'tomato', - }) - .draw() + .chord({ + fingers: [ + [1, 2, 'A'], + [2, 1, 'B'], + [3, 2, 'C'], + [4, 0], // fret 0 = open string + [5, 'x'], // fret x = muted string + ], + barres: [], + }) + .configure({ + strings: 5, + frets: 6, + title: 'Text on Fingers', + fingerTextColor: 'tomato', + }) + .draw() saveSvg('text on fingers', container.outerHTML) }) it('Should set the stroke width on silent and open string indicators', () => { svguitar - .chord({ - fingers: [ - [2, 0], - [3, 'x'], - [4, 0, { strokeWidth: 5 }], - [5, 'x', { strokeWidth: 5 }], - ], - barres: [], - }) - .configure({ - title: 'Open & Silent String Indicator Strokes', - }) - .draw() + .chord({ + fingers: [ + [2, 0], + [3, 'x'], + [4, 0, {strokeWidth: 5}], + [5, 'x', {strokeWidth: 5}], + ], + barres: [], + }) + .configure({ + title: 'Open & Silent String Indicator Strokes', + }) + .draw() saveSvg('silent and open strokes', container.outerHTML) }) it('Should set the stroke colors on silent and open string indicators', () => { svguitar - .chord({ - fingers: [ - [4, 0, { strokeColor: 'blue' }], - [5, 'x', { strokeColor: 'green' }], - ], - barres: [], - }) - .configure({ - title: 'Open & Silent String Indicator Colors', - }) - .draw() + .chord({ + fingers: [ + [4, 0, {strokeColor: 'blue'}], + [5, 'x', {strokeColor: 'green'}], + ], + barres: [], + }) + .configure({ + title: 'Open & Silent String Indicator Colors', + }) + .draw() saveSvg('silent and open colored', container.outerHTML) }) it('Should render text on silent and open string indicators', () => { svguitar - .chord({ - fingers: [ - [2, 0, 'A'], - [3, 'x', 'B'], - [4, 0, { text: 'C', textColor: 'green' }], - [5, 'x', { text: 'D', textColor: 'blue' }], - ], - barres: [], - }) - .configure({ - title: 'Text on Open & Silent Strings', - }) - .draw() + .chord({ + fingers: [ + [2, 0, 'A'], + [3, 'x', 'B'], + [4, 0, {text: 'C', textColor: 'green'}], + [5, 'x', {text: 'D', textColor: 'blue'}], + ], + barres: [], + }) + .configure({ + title: 'Text on Open & Silent Strings', + }) + .draw() saveSvg('silent and open colored', container.outerHTML) }) it('Should render text on silent and open string indicators vertically', () => { svguitar - .chord({ - fingers: [ - [2, 0, 'A'], - [3, 'x', 'B'], - [4, 0, { text: 'C', textColor: 'green' }], - [5, 'x', { text: 'D', textColor: 'blue' }], - ], - barres: [], - }) - .configure({ - orientation: Orientation.horizontal, - title: 'Text on Open & Silent Strings Horizontal', - }) - .draw() + .chord({ + fingers: [ + [2, 0, 'A'], + [3, 'x', 'B'], + [4, 0, {text: 'C', textColor: 'green'}], + [5, 'x', {text: 'D', textColor: 'blue'}], + ], + barres: [], + }) + .configure({ + orientation: Orientation.horizontal, + title: 'Text on Open & Silent Strings Horizontal', + }) + .draw() saveSvg('silent and open colored', container.outerHTML) }) it('Should render fingers with a different color', () => { svguitar - .chord({ - fingers: [ - [1, 2, { color: 'green' }], - [2, 1, { text: 'B', color: 'blue' }], - ], - barres: [], - }) - .configure({ - strings: 5, - frets: 6, - title: 'Colored Fingers', - }) - .draw() + .chord({ + fingers: [ + [1, 2, {color: 'green'}], + [2, 1, {text: 'B', color: 'blue'}], + ], + barres: [], + }) + .configure({ + strings: 5, + frets: 6, + title: 'Colored Fingers', + }) + .draw() saveSvg('colored fingers', container.outerHTML) }) it('Should render square fingers', () => { svguitar - .chord({ - fingers: [ - [1, 2, { shape: Shape.SQUARE }], - [2, 3, { shape: Shape.SQUARE, color: 'blue', text: 'X' }], - ], - barres: [], - }) - .configure({ - strings: 5, - frets: 6, - title: 'Square Fingers', - }) - .draw() + .chord({ + fingers: [ + [1, 2, {shape: Shape.SQUARE}], + [2, 3, {shape: Shape.SQUARE, color: 'blue', text: 'X'}], + ], + barres: [], + }) + .configure({ + strings: 5, + frets: 6, + title: 'Square Fingers', + }) + .draw() saveSvg('square fingers', container.outerHTML) }) it('Should render triangle fingers', () => { svguitar - .chord({ - fingers: [ - [1, 2, { shape: Shape.TRIANGLE }], - [2, 3, { shape: Shape.TRIANGLE, color: 'blue', text: 'X' }], - ], - barres: [], - }) - .configure({ - strings: 5, - frets: 6, - title: 'Triangle Fingers', - }) - .draw() + .chord({ + fingers: [ + [1, 2, {shape: Shape.TRIANGLE}], + [2, 3, {shape: Shape.TRIANGLE, color: 'blue', text: 'X'}], + ], + barres: [], + }) + .configure({ + strings: 5, + frets: 6, + title: 'Triangle Fingers', + }) + .draw() saveSvg('triangle fingers', container.outerHTML) }) it('Should render pentagon shaped fingers', () => { svguitar - .chord({ - fingers: [ - [1, 2, { shape: Shape.PENTAGON }], - [2, 3, { shape: Shape.PENTAGON, color: 'blue', text: 'X' }], - ], - barres: [], - }) - .configure({ - strings: 5, - frets: 6, - title: 'Pentagon Fingers', - }) - .draw() + .chord({ + fingers: [ + [1, 2, {shape: Shape.PENTAGON}], + [2, 3, {shape: Shape.PENTAGON, color: 'blue', text: 'X'}], + ], + barres: [], + }) + .configure({ + strings: 5, + frets: 6, + title: 'Pentagon Fingers', + }) + .draw() saveSvg('pentagon fingers', container.outerHTML) }) it('Should render outline square fingers ', () => { svguitar - .chord({ - fingers: [ - [ - 2, - 3, - { - shape: Shape.SQUARE, - color: 'blue', - text: 'X', - strokeColor: 'red', - strokeWidth: 3, - }, - ], + .chord({ + fingers: [ + [ + 2, + 3, + { + shape: Shape.SQUARE, + color: 'blue', + text: 'X', + strokeColor: 'red', + strokeWidth: 3, + }, ], - barres: [], - }) - .configure({ - title: 'Outline Square Fingers', - }) - .draw() + ], + barres: [], + }) + .configure({ + title: 'Outline Square Fingers', + }) + .draw() saveSvg('outline square fingers', container.outerHTML) }) it('Should render outline triangle fingers', () => { svguitar - .chord({ - fingers: [ - [ - 2, - 3, - { - shape: Shape.TRIANGLE, - color: 'blue', - text: 'X', - strokeColor: 'red', - strokeWidth: 3, - }, - ], + .chord({ + fingers: [ + [ + 2, + 3, + { + shape: Shape.TRIANGLE, + color: 'blue', + text: 'X', + strokeColor: 'red', + strokeWidth: 3, + }, ], - barres: [], - }) - .configure({ - title: 'Outline Triangle Fingers', - }) - .draw() + ], + barres: [], + }) + .configure({ + title: 'Outline Triangle Fingers', + }) + .draw() saveSvg('outline triangle fingers', container.outerHTML) }) it('Should render pentagon shaped fingers', () => { svguitar - .chord({ - fingers: [ - [ - 2, - 3, - { - shape: Shape.PENTAGON, - color: 'blue', - text: 'X', - strokeColor: 'red', - strokeWidth: 3, - }, - ], + .chord({ + fingers: [ + [ + 2, + 3, + { + shape: Shape.PENTAGON, + color: 'blue', + text: 'X', + strokeColor: 'red', + strokeWidth: 3, + }, ], - barres: [], - }) - .configure({ - title: 'Outline Pentagon Fingers', - }) - .draw() + ], + barres: [], + }) + .configure({ + title: 'Outline Pentagon Fingers', + }) + .draw() saveSvg('outline pentagon fingers', container.outerHTML) }) it('Should render an outlined barre chord', () => { svguitar - .chord({ - fingers: [], - barres: [ - { - fromString: 4, - toString: 2, - fret: 1, - strokeWidth: 3, - strokeColor: 'green', - }, - ], - }) - .configure({ - title: 'Outlined Barre Chord', - }) - .draw() + .chord({ + fingers: [], + barres: [ + { + fromString: 4, + toString: 2, + fret: 1, + strokeWidth: 3, + strokeColor: 'green', + }, + ], + }) + .configure({ + title: 'Outlined Barre Chord', + }) + .draw() saveSvg('outline barre', container.outerHTML) }) it('Should render all fingers and barre chords with an outline', () => { svguitar - .chord({ - fingers: [ - [2, 3, { shape: Shape.SQUARE }], - [3, 4], - ], - barres: [ - { - fromString: 3, - toString: 1, - fret: 1, - }, - ], - }) - .configure({ - fingerStrokeWidth: 3, - barreChordStrokeWidth: 3, - barreChordStrokeColor: 'green', - fingerStrokeColor: 'red', - title: 'Outlined', - }) - .draw() + .chord({ + fingers: [ + [2, 3, {shape: Shape.SQUARE}], + [3, 4], + ], + barres: [ + { + fromString: 3, + toString: 1, + fret: 1, + }, + ], + }) + .configure({ + fingerStrokeWidth: 3, + barreChordStrokeWidth: 3, + barreChordStrokeColor: 'green', + fingerStrokeColor: 'red', + title: 'Outlined', + }) + .draw() saveSvg('outline fingers', container.outerHTML) }) @@ -452,197 +452,197 @@ describe('SVGuitarChord', () => { it('Should throw an error if an invliad shape is provided', () => { expect(() => { svguitar - .chord({ - fingers: [[1, 2, { shape: 'XXX' as Shape }]], - barres: [], - }) - .draw() + .chord({ + fingers: [[1, 2, {shape: 'XXX' as Shape}]], + barres: [], + }) + .draw() }).toThrowError(/XXX/) }) it('Should render text on fingers with a different color', () => { svguitar - .chord({ - fingers: [ - [1, 2, { text: 'G', textColor: 'green' }], - [2, 1, { text: 'B', textColor: 'blue' }], - [3, 1, { textColor: 'green' }], // no effect - ], - barres: [], - }) - .configure({ - strings: 5, - frets: 6, - title: 'Colored Text on Fingers', - }) - .draw() + .chord({ + fingers: [ + [1, 2, {text: 'G', textColor: 'green'}], + [2, 1, {text: 'B', textColor: 'blue'}], + [3, 1, {textColor: 'green'}], // no effect + ], + barres: [], + }) + .configure({ + strings: 5, + frets: 6, + title: 'Colored Text on Fingers', + }) + .draw() saveSvg('colored text on fingers', container.outerHTML) }) it('Should render barre chords with a different color', () => { svguitar - .chord({ - fingers: [], - barres: [ - { - fret: 1, - fromString: 4, - toString: 1, - color: 'blue', - }, - { - fret: 3, - fromString: 5, - toString: 2, - color: 'red', - }, - ], - }) - .configure({ - strings: 5, - frets: 6, - title: 'Colored Barre Chords', - }) - .draw() + .chord({ + fingers: [], + barres: [ + { + fret: 1, + fromString: 4, + toString: 1, + color: 'blue', + }, + { + fret: 3, + fromString: 5, + toString: 2, + color: 'red', + }, + ], + }) + .configure({ + strings: 5, + frets: 6, + title: 'Colored Barre Chords', + }) + .draw() saveSvg('colored barre chords', container.outerHTML) }) it('Should render text on barre chords with a different color', () => { svguitar - .chord({ - fingers: [], - barres: [ - { - fret: 1, - fromString: 4, - toString: 1, - text: 'Blue Text', - textColor: 'blue', - }, - { - fret: 3, - fromString: 5, - toString: 2, - text: 'Red Text', - textColor: 'red', - }, - { - fret: 2, - fromString: 3, - toString: 2, - textColor: 'red', - }, - ], - }) - .configure({ - strings: 5, - frets: 6, - title: 'Colored Text on Barre Chords', - }) - .draw() + .chord({ + fingers: [], + barres: [ + { + fret: 1, + fromString: 4, + toString: 1, + text: 'Blue Text', + textColor: 'blue', + }, + { + fret: 3, + fromString: 5, + toString: 2, + text: 'Red Text', + textColor: 'red', + }, + { + fret: 2, + fromString: 3, + toString: 2, + textColor: 'red', + }, + ], + }) + .configure({ + strings: 5, + frets: 6, + title: 'Colored Text on Barre Chords', + }) + .draw() saveSvg('colored text on barre chords', container.outerHTML) }) it('Should render text on the barre chords', () => { svguitar - .chord({ - fingers: [], - barres: [ - { - fret: 1, - fromString: 4, - toString: 1, - text: 'B', - }, - { - fret: 3, - fromString: 5, - toString: 2, - text: 'A', - }, - ], - }) - .configure({ - strings: 5, - frets: 5, - title: 'Text on Barres', - fingerTextColor: 'lightgreen', - }) - .draw() + .chord({ + fingers: [], + barres: [ + { + fret: 1, + fromString: 4, + toString: 1, + text: 'B', + }, + { + fret: 3, + fromString: 5, + toString: 2, + text: 'A', + }, + ], + }) + .configure({ + strings: 5, + frets: 5, + title: 'Text on Barres', + fingerTextColor: 'lightgreen', + }) + .draw() saveSvg('text on barre chords', container.outerHTML) }) it('Should render a title nicely', () => { svguitar - .configure({ - title: 'Test Title', - }) - .draw() + .configure({ + title: 'Test Title', + }) + .draw() saveSvg('with title', container.outerHTML) }) it('Should render a title provided as part of the chord', () => { svguitar - .configure({ - title: 'DO NOT RENDER THIS', - }) - .chord({ - fingers: [], - barres: [], - title: 'title from chord', - }) - .draw() + .configure({ + title: 'DO NOT RENDER THIS', + }) + .chord({ + fingers: [], + barres: [], + title: 'title from chord', + }) + .draw() saveSvg('title from chord', container.outerHTML) }) it('Should render the position provided as part of the chord', () => { svguitar - .configure({ - position: 999, - }) - .chord({ - fingers: [], - barres: [], - position: 3, - }) - .draw() + .configure({ + position: 999, + }) + .chord({ + fingers: [], + barres: [], + position: 3, + }) + .draw() saveSvg('position from chord', container.outerHTML) }) it('Should not render a nut if no position is true', () => { svguitar - .configure({ - title: 'No position', - noPosition: true, - }) - .chord({ - fingers: [], - barres: [], - position: 3, - }) - .draw() + .configure({ + title: 'No position', + noPosition: true, + }) + .chord({ + fingers: [], + barres: [], + position: 3, + }) + .draw() saveSvg('no position', container.outerHTML) }) it('Should not render a nut if no position is true and position is 1', () => { svguitar - .configure({ - title: 'No nut', - noPosition: true, - }) - .chord({ - fingers: [], - barres: [], - }) - .draw() + .configure({ + title: 'No nut', + noPosition: true, + }) + .chord({ + fingers: [], + barres: [], + }) + .draw() saveSvg('no position with position 1', container.outerHTML) }) @@ -660,365 +660,465 @@ describe('SVGuitarChord', () => { it('Should render a very long title nicely', () => { svguitar - .configure({ - title: 'This is a very long title that does not fit easily', - }) - .draw() + .configure({ + title: 'This is a very long title that does not fit easily', + }) + .draw() saveSvg('with long title', container.outerHTML) }) it('Should render 8 strings', () => { svguitar - .configure({ - title: '8 Strings', - }) - .configure({ - strings: 8, - }) - .draw() + .configure({ + title: '8 Strings', + }) + .configure({ + strings: 8, + }) + .draw() saveSvg('8 strings', container.outerHTML) }) it('Should render 8 frets', () => { svguitar - .configure({ - title: '8 Frets', - }) - .configure({ - frets: 8, - }) - .draw() + .configure({ + title: '8 Frets', + }) + .configure({ + frets: 8, + }) + .draw() saveSvg('8 frets', container.outerHTML) }) it('Should render from fret 2 with the fret label left', () => { svguitar - .configure({ - position: 2, - fretLabelPosition: FretLabelPosition.LEFT, - }) - .draw() + .configure({ + position: 2, + fretLabelPosition: FretLabelPosition.LEFT, + }) + .draw() saveSvg('starting fret 2 left', container.outerHTML) }) it('Should render from fret 2 with the fret label right', () => { svguitar - .configure({ - position: 2, - fretLabelPosition: FretLabelPosition.RIGHT, - }) - .draw() + .configure({ + position: 2, + fretLabelPosition: FretLabelPosition.RIGHT, + }) + .draw() saveSvg('starting fret 2 right', container.outerHTML) }) it('Should render all tunings', () => { svguitar - .configure({ - strings: 5, - tuning: ['1', '2', '3', '4', '5'], - }) - .draw() + .configure({ + strings: 5, + tuning: ['1', '2', '3', '4', '5'], + }) + .draw() saveSvg('tunings', container.outerHTML) }) it('Should render not render all tunings if there are extranous tunings', () => { svguitar - .configure({ - strings: 5, - tuning: ['1', '2', '3', '4', '5', '6'], - }) - .draw() + .configure({ + strings: 5, + tuning: ['1', '2', '3', '4', '5', '6'], + }) + .draw() saveSvg('too many tunings', container.outerHTML) }) it('Should render barre chords', () => { svguitar - .configure({ - strings: 5, - frets: 5, - }) - .chord({ - fingers: [], - barres: [ - { - fret: 1, - fromString: 4, - toString: 1, - }, - { - fret: 3, - fromString: 5, - toString: 2, - }, - ], - }) - .draw() + .configure({ + strings: 5, + frets: 5, + }) + .chord({ + fingers: [], + barres: [ + { + fret: 1, + fromString: 4, + toString: 1, + }, + { + fret: 3, + fromString: 5, + toString: 2, + }, + ], + }) + .draw() saveSvg('barre chords', container.outerHTML) }) it('Should render everything in red', () => { svguitar - .configure({ - color: '#f00', - tuning: ['1', '2', '3', '4', '5', '6'], - title: 'Test', - position: 3, - }) - .chord({ - fingers: [ - [1, 2], - [2, 1], - [3, 2], - [4, 0], // fret 0 = open string - [5, 'x'], // fret x = muted string - ], - barres: [], - }) - .draw() + .configure({ + color: '#f00', + tuning: ['1', '2', '3', '4', '5', '6'], + title: 'Test', + position: 3, + }) + .chord({ + fingers: [ + [1, 2], + [2, 1], + [3, 2], + [4, 0], // fret 0 = open string + [5, 'x'], // fret x = muted string + ], + barres: [], + }) + .draw() saveSvg('red', container.outerHTML) }) it('Should render correctly with all default settings overridden', () => { svguitar - .configure({ - strings: 6, - frets: 5, - position: 1, - tuning: [], - tuningsFontSize: 28, - fretLabelFontSize: 38, - fretLabelPosition: FretLabelPosition.RIGHT, - fingerSize: 0.65, - sidePadding: 0.2, - titleFontSize: 48, - titleBottomMargin: 0, - color: '#000', - emptyStringIndicatorSize: 0.6, - strokeWidth: 2, - topFretWidth: 10, - fretSize: 1.5, - barreChordRadius: 0.25, - fontFamily: 'Arial, "Helvetica Neue", Helvetica, sans-serif', - }) - .chord({ - fingers: [ - [1, 2], - [2, 1], - [3, 2], - [4, 0], // fret 0 = open string - [5, 'x'], // fret x = muted string - ], - barres: [], - }) - .draw() + .configure({ + strings: 6, + frets: 5, + position: 1, + tuning: [], + tuningsFontSize: 28, + fretLabelFontSize: 38, + fretLabelPosition: FretLabelPosition.RIGHT, + fingerSize: 0.65, + sidePadding: 0.2, + titleFontSize: 48, + titleBottomMargin: 0, + color: '#000', + emptyStringIndicatorSize: 0.6, + strokeWidth: 2, + topFretWidth: 10, + fretSize: 1.5, + barreChordRadius: 0.25, + fontFamily: 'Arial, "Helvetica Neue", Helvetica, sans-serif', + }) + .chord({ + fingers: [ + [1, 2], + [2, 1], + [3, 2], + [4, 0], // fret 0 = open string + [5, 'x'], // fret x = muted string + ], + barres: [], + }) + .draw() saveSvg('settings overridden', container.outerHTML) }) it('Should render correctly without any configuration', () => { svguitar - .chord({ - fingers: [ - [1, 2], - [2, 1], - [3, 2], - [4, 0], // fret 0 = open string - [5, 'x'], // fret x = muted string - ], - barres: [], - }) - .draw() + .chord({ + fingers: [ + [1, 2], + [2, 1], + [3, 2], + [4, 0], // fret 0 = open string + [5, 'x'], // fret x = muted string + ], + barres: [], + }) + .draw() saveSvg('settings overridden', container.outerHTML) }) it('Should render very fat strokes', () => { svguitar - .configure({ - title: 'Fat Strokes', - strokeWidth: 10, - topFretWidth: 30, - }) - .chord({ - fingers: [ - [1, 2], - [2, 1], - [3, 2], - [4, 0], // fret 0 = open string - [5, 'x'], // fret x = muted string - ], - barres: [], - }) - .draw() + .configure({ + title: 'Fat Strokes', + strokeWidth: 10, + topFretWidth: 30, + }) + .chord({ + fingers: [ + [1, 2], + [2, 1], + [3, 2], + [4, 0], // fret 0 = open string + [5, 'x'], // fret x = muted string + ], + barres: [], + }) + .draw() saveSvg('fat strokes', container.outerHTML) }) it('Should render a green background', () => { svguitar - .configure({ - title: 'With Background', - backgroundColor: '#00FF00', - }) - .draw() + .configure({ + title: 'With Background', + backgroundColor: '#00FF00', + }) + .draw() saveSvg('with background', container.outerHTML) }) it('Should vertically center the barre correctly', () => { svguitar - .chord({ - fingers: [], - barres: [ - { - fret: 1, - fromString: 4, - toString: 1, - }, - ], - }) - .configure({ - title: 'Centered Barre', - fretSize: 1, - fingerSize: 1, - strokeWidth: 5, - fingerColor: 'tomato', - barreChordRadius: 0, - }) - .draw() + .chord({ + fingers: [], + barres: [ + { + fret: 1, + fromString: 4, + toString: 1, + }, + ], + }) + .configure({ + title: 'Centered Barre', + fretSize: 1, + fingerSize: 1, + strokeWidth: 5, + fingerColor: 'tomato', + barreChordRadius: 0, + }) + .draw() saveSvg('centered barre', container.outerHTML) }) it('Should render two diagrams in the same position, with and without title', () => { svguitar - .configure({ - title: 'With Title', - fixedDiagramPosition: true, - }) - .draw() + .configure({ + title: 'With Title', + fixedDiagramPosition: true, + }) + .draw() saveSvg('fixed diagram position 1', container.outerHTML) svguitar - .configure({ - title: undefined, - fixedDiagramPosition: true, - }) - .draw() + .configure({ + title: undefined, + fixedDiagramPosition: true, + }) + .draw() saveSvg('fixed diagram position 2', container.outerHTML) svguitar - .configure({ - fixedDiagramPosition: true, - }) - .chord({ - fingers: [[5, 'x']], - barres: [], - }) - .draw() + .configure({ + fixedDiagramPosition: true, + }) + .chord({ + fingers: [[5, 'x']], + barres: [], + }) + .draw() saveSvg('fixed diagram position 3', container.outerHTML) }) it('Should add custom classes to the barrre chord', () => { svguitar - .chord({ - fingers: [], - barres: [ - { - fret: 1, - fromString: 4, - toString: 1, - className: 'custom-class-123', - }, - ], - }) - .configure({ - title: 'Barre with Custom Class', - }) - .draw() + .chord({ + fingers: [], + barres: [ + { + fret: 1, + fromString: 4, + toString: 1, + className: 'custom-class-123', + }, + ], + }) + .configure({ + title: 'Barre with Custom Class', + }) + .draw() saveSvg('barre with class', container.outerHTML) }) it('Should add custom classes to fingers', () => { svguitar - .chord({ - fingers: [ - [1, 2, { text: 'a', className: 'custom-class-a' }], - [2, 1, { text: 'b', className: 'custom-class-b' }], - [3, 1, { text: 'c', className: 'custom-class-c' }], - ], - barres: [], - }) - .configure({ - title: 'Fingers with Custom Class', - }) - .draw() + .chord({ + fingers: [ + [1, 2, {text: 'a', className: 'custom-class-a'}], + [2, 1, {text: 'b', className: 'custom-class-b'}], + [3, 1, {text: 'c', className: 'custom-class-c'}], + ], + barres: [], + }) + .configure({ + title: 'Fingers with Custom Class', + }) + .draw() saveSvg('fingers with class', container.outerHTML) }) it('Should add a watermark', () => { svguitar - .chord({ - fingers: [], - barres: [], - }) - .configure({ - tuning: ['1', '2', '3', '4', '5', '6'], - title: 'With watermark', - watermark: 'test watermark', - watermarkFontSize: 20, - watermarkColor: 'rgba(255, 0, 0, 0.5)', - }) - .draw() + .chord({ + fingers: [], + barres: [], + }) + .configure({ + tuning: ['1', '2', '3', '4', '5', '6'], + title: 'With watermark', + watermark: 'test watermark', + watermarkFontSize: 20, + watermarkColor: 'rgba(255, 0, 0, 0.5)', + }) + .draw() saveSvg('with watermark', container.outerHTML) }) it('Should add a watermark on a horizontal chart', () => { svguitar - .chord({ - fingers: [], - barres: [], - }) - .configure({ - orientation: Orientation.horizontal, - tuning: ['1', '2', '3', '4', '5', '6'], - title: 'Horizontal watermark', - watermark: 'test watermark', - watermarkFontSize: 20, - watermarkColor: 'rgba(255, 0, 0, 0.5)', - }) - .draw() + .chord({ + fingers: [], + barres: [], + }) + .configure({ + orientation: Orientation.horizontal, + tuning: ['1', '2', '3', '4', '5', '6'], + title: 'Horizontal watermark', + watermark: 'test watermark', + watermarkFontSize: 20, + watermarkColor: 'rgba(255, 0, 0, 0.5)', + }) + .draw() saveSvg('with watermark horizontal', container.outerHTML) }) it('Should render a chart with an SVG title', () => { svguitar - .chord({ - fingers: [], - barres: [], - }) - .configure({ - title: 'SVG Title', - svgTitle: 'This is the SVG title', - }) - .draw() + .chord({ + fingers: [], + barres: [], + }) + .configure({ + title: 'SVG Title', + svgTitle: 'This is the SVG title', + }) + .draw() saveSvg('with svg title', container.outerHTML) }) + it('Should render a chart with fret markers', () => { + svguitar + .chord({ + fingers: [], + barres: [], + }) + .configure({ + fretMarkers: [ + 0, + { + fret: 1, + color: '#FF0000', + }, { + fret: 2, + shape: Shape.SQUARE, + }, { + fret: 3, + size: 1, + }, { + fret: 4, + strokeColor: '#0000FF', + strokeWidth: 3, + }], + }) + .draw() + + saveSvg('fret markers', container.outerHTML) + }) + + it('Should render a chart with double fret markers', () => { + svguitar + .chord({ + fingers: [], + barres: [], + }) + .configure({ + frets: 6, + fretMarkers: [{ + fret: 0, + double: true, + }, { + fret: 1, + color: '#FF0000', + double: true, + }, { + fret: 2, + shape: Shape.SQUARE, + double: true, + }, { + fret: 3, + double: true, + distance: 0.8, + }, { + fret: 4, + double: true, + distance: 1, + }, { + fret: 5, + double: true, + distance: 0, + }], + }) + .draw() + + saveSvg('double fret markers', container.outerHTML) + }) + + it('Should render a horizontal chart with double fret markers', () => { + svguitar + .chord({ + fingers: [ + [1, 2], + [2, 1], + [3, 2], + [4, 0], + [5, 'x'], + ], + barres: [ + { + fret: 3, + fromString: 4, + toString: 1, + }, + ], + }) + .configure({ + orientation: Orientation.horizontal, + frets: 14, + fretMarkers: [ + 2, 4, 6, 8, { + fret: 11, + double: true, + }, + ], + }) + .draw() + + saveSvg('fret markers horizontal', container.outerHTML) + }) + test.each` setting | value | valid ${'strings'} | ${1} | ${false} @@ -1030,12 +1130,12 @@ describe('SVGuitarChord', () => { ${'fretSize'} | ${-1} | ${false} ${'fingerSize'} | ${-1} | ${false} ${'strokeWidth'} | ${-1} | ${false} - `('Should correctly sanity check the settings', ({ setting, value, valid }) => { + `('Should correctly sanity check the settings', ({setting, value, valid}) => { // console.log(`Should ${valid ? 'not' : ''} thrown if ${setting} is ${value}`) if (valid) { - expect(() => svguitar.configure({ [setting]: value })).not.toThrow() + expect(() => svguitar.configure({[setting]: value})).not.toThrow() } else { - expect(() => svguitar.configure({ [setting]: value })).toThrow() + expect(() => svguitar.configure({[setting]: value})).toThrow() } }) })