text-guitar-chart 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,705 @@
1
+ // @ts-check
2
+
3
+ import { describe, test } from "node:test";
4
+ import assert from "node:assert/strict";
5
+ import fingeringToString from "../lib/fingeringToString.js";
6
+
7
+ describe("fingeringToString", () => {
8
+ describe("ASCII format output", () => {
9
+ test("outputs simple A minor chord (open strings with dots)", () => {
10
+ /** @type {import("svguitar").Chord} */
11
+ const chord = {
12
+ fingers: [
13
+ [2, 1, { text: "", color: "#000000" }],
14
+ [3, 2, { text: "", color: "#e74c3c" }],
15
+ [4, 2, { text: "", color: "#000000" }],
16
+ [5, 0, { text: "", color: "#000000" }],
17
+ [6, 0, { text: "", color: "#000000" }],
18
+ [1, 0, { text: "", color: "#000000" }],
19
+ ],
20
+ barres: [],
21
+ title: "A min",
22
+ };
23
+
24
+ const result = fingeringToString(chord);
25
+
26
+ const expected = ` A min
27
+ ######
28
+ oo o
29
+ ------
30
+ ||||o|
31
+ ||o*||
32
+ ||||||`;
33
+
34
+ assert.equal(result, expected);
35
+ });
36
+
37
+ test("outputs D chord with muted strings", () => {
38
+ /** @type {import("svguitar").Chord} */
39
+ const chord = {
40
+ fingers: [
41
+ [1, 2, { text: "", color: "#000000" }],
42
+ [3, 2, { text: "", color: "#000000" }],
43
+ [2, 3, { text: "", color: "#e74c3c" }],
44
+ [6, "x", { text: "", color: "#000000" }],
45
+ [5, 0, { text: "", color: "#000000" }],
46
+ [4, 0, { text: "", color: "#000000" }],
47
+ ],
48
+ barres: [],
49
+ title: "D",
50
+ };
51
+
52
+ const result = fingeringToString(chord);
53
+
54
+ const expected = ` D
55
+ ######
56
+ xoo
57
+ ------
58
+ ||||||
59
+ |||o|o
60
+ ||||*|`;
61
+
62
+ assert.equal(result, expected);
63
+ });
64
+
65
+ test("outputs G7 chord with starting fret number", () => {
66
+ /** @type {import("svguitar").Chord} */
67
+ const chord = {
68
+ fingers: [
69
+ [6, "x", { text: "", color: "#000000" }],
70
+ [5, "x", { text: "", color: "#000000" }],
71
+ [4, 1, { text: "", color: "#e74c3c" }],
72
+ [2, 2, { text: "", color: "#000000" }],
73
+ [3, 3, { text: "", color: "#000000" }],
74
+ [1, 3, { text: "", color: "#000000" }],
75
+ ],
76
+ barres: [],
77
+ title: "G 7",
78
+ position: 5,
79
+ };
80
+
81
+ const result = fingeringToString(chord);
82
+
83
+ const expected = ` G 7
84
+ ######
85
+ xx
86
+ ------
87
+ 5||*|||
88
+ ||||o|
89
+ |||o|o`;
90
+
91
+ assert.equal(result, expected);
92
+ });
93
+
94
+ test("outputs G7 chord with starting with 2 digits fret number", () => {
95
+ /** @type {import("svguitar").Chord} */
96
+ const chord = {
97
+ fingers: [
98
+ [6, "x", { text: "", color: "#000000" }],
99
+ [5, "x", { text: "", color: "#000000" }],
100
+ [4, 1, { text: "", color: "#e74c3c" }],
101
+ [2, 2, { text: "", color: "#000000" }],
102
+ [3, 3, { text: "", color: "#000000" }],
103
+ [1, 3, { text: "", color: "#000000" }],
104
+ ],
105
+ barres: [],
106
+ title: "G 7",
107
+ position: 15,
108
+ };
109
+
110
+ const result = fingeringToString(chord);
111
+
112
+ const expected = ` G 7
113
+ ######
114
+ xx
115
+ ------
116
+ 15||*|||
117
+ ||||o|
118
+ |||o|o`;
119
+
120
+ assert.equal(result, expected);
121
+ });
122
+
123
+ test("outputs G7 chord with starting with 1 as fret number", () => {
124
+ /** @type {import("svguitar").Chord} */
125
+ const chord = {
126
+ fingers: [
127
+ [6, "x", { text: "", color: "#000000" }],
128
+ [5, "x", { text: "", color: "#000000" }],
129
+ [4, 1, { text: "", color: "#e74c3c" }],
130
+ [2, 2, { text: "", color: "#000000" }],
131
+ [3, 3, { text: "", color: "#000000" }],
132
+ [1, 3, { text: "", color: "#000000" }],
133
+ ],
134
+ barres: [],
135
+ title: "G 7",
136
+ position: 1,
137
+ };
138
+
139
+ const result = fingeringToString(chord);
140
+
141
+ const expected = ` G 7
142
+ ######
143
+ xx
144
+ ======
145
+ ||*|||
146
+ ||||o|
147
+ |||o|o`;
148
+
149
+ assert.equal(result, expected);
150
+ });
151
+
152
+ test("outputs E dom 7 chord with finger numbers", () => {
153
+ /** @type {import("svguitar").Chord} */
154
+ const chord = {
155
+ fingers: [
156
+ [5, 2, { text: "5", color: "#000000" }],
157
+ [4, 2, { text: "1", color: "#000000" }],
158
+ [3, 1, { text: "3", color: "#000000" }],
159
+ [2, 3, { text: "7", color: "#000000" }],
160
+ [6, "x", { text: "", color: "#000000" }],
161
+ [1, "x", { text: "", color: "#000000" }],
162
+ ],
163
+ barres: [],
164
+ title: "E dom 7",
165
+ };
166
+
167
+ const result = fingeringToString(chord);
168
+
169
+ const expected = ` E dom 7
170
+ #######
171
+ x x
172
+ ------
173
+ |||3||
174
+ |51|||
175
+ ||||7|`;
176
+
177
+ assert.equal(result, expected);
178
+ });
179
+ });
180
+
181
+ describe("Unicode format output", () => {
182
+ test("outputs A minor chord (Unicode format)", () => {
183
+ /** @type {import("svguitar").Chord} */
184
+ const chord = {
185
+ fingers: [
186
+ [2, 1, { text: "", color: "#000000" }],
187
+ [3, 2, { text: "", color: "#e74c3c" }],
188
+ [4, 2, { text: "", color: "#000000" }],
189
+ [5, 0, { text: "", color: "#000000" }],
190
+ [6, 0, { text: "", color: "#000000" }],
191
+ [1, 0, { text: "", color: "#000000" }],
192
+ ],
193
+ barres: [],
194
+ title: "A min",
195
+ };
196
+
197
+ const result = fingeringToString(chord, { useUnicode: true });
198
+
199
+ const expected = ` A min
200
+ ‾‾‾‾‾‾‾‾‾‾‾
201
+ ○ ○ ○
202
+ ┌─┬─┬─┬─┬─┐
203
+ │ │ │ │ ○ │
204
+ ├─┼─┼─┼─┼─┤
205
+ │ │ ○ ● │ │
206
+ ├─┼─┼─┼─┼─┤
207
+ │ │ │ │ │ │
208
+ └─┴─┴─┴─┴─┘`;
209
+
210
+ assert.equal(result, expected);
211
+ });
212
+
213
+ test("outputs D chord (Unicode format)", () => {
214
+ /** @type {import("svguitar").Chord} */
215
+ const chord = {
216
+ fingers: [
217
+ [1, 2, { text: "", color: "#000000" }],
218
+ [3, 2, { text: "", color: "#000000" }],
219
+ [2, 3, { text: "", color: "#e74c3c" }],
220
+ [6, "x", { text: "", color: "#000000" }],
221
+ [5, 0, { text: "", color: "#000000" }],
222
+ [4, 0, { text: "", color: "#000000" }],
223
+ ],
224
+ barres: [],
225
+ title: "D",
226
+ };
227
+
228
+ const result = fingeringToString(chord, { useUnicode: true });
229
+
230
+ const expected = ` D
231
+ ‾‾‾‾‾‾‾‾‾‾‾
232
+ × ○ ○
233
+ ┌─┬─┬─┬─┬─┐
234
+ │ │ │ │ │ │
235
+ ├─┼─┼─┼─┼─┤
236
+ │ │ │ ○ │ ○
237
+ ├─┼─┼─┼─┼─┤
238
+ │ │ │ │ ● │
239
+ └─┴─┴─┴─┴─┘`;
240
+
241
+ assert.equal(result, expected);
242
+ });
243
+
244
+ test("outputs G7 chord with starting fret (Unicode format)", () => {
245
+ /** @type {import("svguitar").Chord} */
246
+ const chord = {
247
+ fingers: [
248
+ [6, "x", { text: "", color: "#000000" }],
249
+ [5, "x", { text: "", color: "#000000" }],
250
+ [4, 1, { text: "", color: "#e74c3c" }],
251
+ [2, 2, { text: "", color: "#000000" }],
252
+ [3, 3, { text: "", color: "#000000" }],
253
+ [1, 3, { text: "", color: "#000000" }],
254
+ ],
255
+ barres: [],
256
+ title: "G 7",
257
+ position: 5,
258
+ };
259
+
260
+ const result = fingeringToString(chord, { useUnicode: true });
261
+
262
+ const expected = ` G 7
263
+ ‾‾‾‾‾‾‾‾‾‾‾
264
+ × ×
265
+ ┌─┬─┬─┬─┬─┐
266
+ 5│ │ ● │ │ │
267
+ ├─┼─┼─┼─┼─┤
268
+ │ │ │ │ ○ │
269
+ ├─┼─┼─┼─┼─┤
270
+ │ │ │ ○ │ ○
271
+ └─┴─┴─┴─┴─┘`;
272
+
273
+ assert.equal(result, expected);
274
+ });
275
+
276
+ test("outputs G7 chord with starting 2 digits starting fret (Unicode format)", () => {
277
+ /** @type {import("svguitar").Chord} */
278
+ const chord = {
279
+ fingers: [
280
+ [6, "x", { text: "", color: "#000000" }],
281
+ [5, "x", { text: "", color: "#000000" }],
282
+ [4, 1, { text: "", color: "#e74c3c" }],
283
+ [2, 2, { text: "", color: "#000000" }],
284
+ [3, 3, { text: "", color: "#000000" }],
285
+ [1, 3, { text: "", color: "#000000" }],
286
+ ],
287
+ barres: [],
288
+ title: "G 7",
289
+ position: 15,
290
+ };
291
+
292
+ const result = fingeringToString(chord, { useUnicode: true });
293
+
294
+ const expected = ` G 7
295
+ ‾‾‾‾‾‾‾‾‾‾‾
296
+ × ×
297
+ ┌─┬─┬─┬─┬─┐
298
+ 15│ │ ● │ │ │
299
+ ├─┼─┼─┼─┼─┤
300
+ │ │ │ │ ○ │
301
+ ├─┼─┼─┼─┼─┤
302
+ │ │ │ ○ │ ○
303
+ └─┴─┴─┴─┴─┘`;
304
+
305
+ assert.equal(result, expected);
306
+ });
307
+
308
+ test("outputs G7 chord with starting fret equal 1 (Unicode format)", () => {
309
+ /** @type {import("svguitar").Chord} */
310
+ const chord = {
311
+ fingers: [
312
+ [6, "x", { text: "", color: "#000000" }],
313
+ [5, "x", { text: "", color: "#000000" }],
314
+ [4, 1, { text: "", color: "#e74c3c" }],
315
+ [2, 2, { text: "", color: "#000000" }],
316
+ [3, 3, { text: "", color: "#000000" }],
317
+ [1, 3, { text: "", color: "#000000" }],
318
+ ],
319
+ barres: [],
320
+ title: "G 7",
321
+ position: 1,
322
+ };
323
+
324
+ const result = fingeringToString(chord, { useUnicode: true });
325
+
326
+ const expected = ` G 7
327
+ ‾‾‾‾‾‾‾‾‾‾‾
328
+ × ×
329
+ ╒═╤═╤═╤═╤═╕
330
+ │ │ ● │ │ │
331
+ ├─┼─┼─┼─┼─┤
332
+ │ │ │ │ ○ │
333
+ ├─┼─┼─┼─┼─┤
334
+ │ │ │ ○ │ ○
335
+ └─┴─┴─┴─┴─┘`;
336
+
337
+ assert.equal(result, expected);
338
+ });
339
+
340
+ test("outputs E dom 7 with finger numbers (Unicode format)", () => {
341
+ /** @type {import("svguitar").Chord} */
342
+ const chord = {
343
+ fingers: [
344
+ [5, 2, { text: "5", color: "#000000" }],
345
+ [4, 2, { text: "1", color: "#000000" }],
346
+ [3, 1, { text: "3", color: "#000000" }],
347
+ [2, 3, { text: "7", color: "#000000" }],
348
+ [6, "x", { text: "", color: "#000000" }],
349
+ [1, "x", { text: "", color: "#000000" }],
350
+ ],
351
+ barres: [],
352
+ title: "E dom 7",
353
+ };
354
+
355
+ const result = fingeringToString(chord, { useUnicode: true });
356
+
357
+ const expected = ` E dom 7
358
+ ‾‾‾‾‾‾‾‾‾‾‾
359
+ × ×
360
+ ┌─┬─┬─┬─┬─┐
361
+ │ │ │ 3 │ │
362
+ ├─┼─┼─┼─┼─┤
363
+ │ 5 1 │ │ │
364
+ ├─┼─┼─┼─┼─┤
365
+ │ │ │ │ 7 │
366
+ └─┴─┴─┴─┴─┘`;
367
+
368
+ assert.equal(result, expected);
369
+ });
370
+ });
371
+
372
+ describe("Edge cases and variations", () => {
373
+ test("handles empty chord", () => {
374
+ /** @type {import("svguitar").Chord} */
375
+ const chord = {
376
+ fingers: [],
377
+ barres: [],
378
+ };
379
+
380
+ const result = fingeringToString(chord);
381
+ const expected = ` ------
382
+ ||||||
383
+ ||||||
384
+ ||||||`;
385
+
386
+ assert.equal(result, expected);
387
+ });
388
+
389
+ test("handles empty chord (unicode)", () => {
390
+ /** @type {import("svguitar").Chord} */
391
+ const chord = {
392
+ fingers: [],
393
+ barres: [],
394
+ };
395
+
396
+ const result = fingeringToString(chord, { useUnicode: true });
397
+ const expected = ` ┌─┬─┬─┬─┬─┐
398
+ │ │ │ │ │ │
399
+ ├─┼─┼─┼─┼─┤
400
+ │ │ │ │ │ │
401
+ ├─┼─┼─┼─┼─┤
402
+ │ │ │ │ │ │
403
+ └─┴─┴─┴─┴─┘`;
404
+
405
+ assert.equal(result, expected);
406
+ });
407
+
408
+ test("handles chord with no title", () => {
409
+ /** @type {import("svguitar").Chord} */
410
+ const chord = {
411
+ fingers: [
412
+ [2, 1, { text: "", color: "#000000" }],
413
+ [3, 2, { text: "", color: "#e74c3c" }],
414
+ [4, 2, { text: "", color: "#000000" }],
415
+ [5, 0, { text: "", color: "#000000" }],
416
+ [6, 0, { text: "", color: "#000000" }],
417
+ [1, 0, { text: "", color: "#000000" }],
418
+ ],
419
+ barres: [],
420
+ title: "",
421
+ };
422
+
423
+ const result = fingeringToString(chord);
424
+
425
+ const expected = ` oo o
426
+ ------
427
+ ||||o|
428
+ ||o*||
429
+ ||||||`;
430
+
431
+ assert.equal(result, expected);
432
+ });
433
+
434
+ test("handles all open strings", () => {
435
+ /** @type {import("svguitar").Chord} */
436
+ const chord = {
437
+ fingers: [
438
+ [1, 0, { text: "", color: "#000000" }],
439
+ [2, 0, { text: "", color: "#000000" }],
440
+ [3, 0, { text: "", color: "#000000" }],
441
+ [4, 0, { text: "", color: "#000000" }],
442
+ [5, 0, { text: "", color: "#000000" }],
443
+ [6, 0, { text: "", color: "#000000" }],
444
+ ],
445
+ barres: [],
446
+ title: "E major",
447
+ };
448
+
449
+ const result = fingeringToString(chord);
450
+
451
+ const expected = ` E major
452
+ #######
453
+ oooooo
454
+ ------
455
+ ||||||
456
+ ||||||
457
+ ||||||`;
458
+
459
+ assert.equal(result, expected);
460
+ });
461
+
462
+ test("handles all muted strings", () => {
463
+ /** @type {import("svguitar").Chord} */
464
+ const chord = {
465
+ fingers: [
466
+ [1, "x", { text: "", color: "#000000" }],
467
+ [2, "x", { text: "", color: "#000000" }],
468
+ [3, "x", { text: "", color: "#000000" }],
469
+ [4, "x", { text: "", color: "#000000" }],
470
+ [5, "x", { text: "", color: "#000000" }],
471
+ [6, "x", { text: "", color: "#000000" }],
472
+ ],
473
+ barres: [],
474
+ title: "Muted",
475
+ };
476
+
477
+ const result = fingeringToString(chord);
478
+
479
+ const expected = ` Muted
480
+ ######
481
+ xxxxxx
482
+ ------
483
+ ||||||
484
+ ||||||
485
+ ||||||`;
486
+
487
+ assert.equal(result, expected);
488
+ });
489
+
490
+ test("handles chord with title but no fingers", () => {
491
+ /** @type {import("svguitar").Chord} */
492
+ const chord = {
493
+ fingers: [],
494
+ barres: [],
495
+ title: "Muted",
496
+ };
497
+
498
+ const result = fingeringToString(chord);
499
+
500
+ const expected = ` Muted
501
+ ######
502
+ ------
503
+ ||||||
504
+ ||||||
505
+ ||||||`;
506
+
507
+ assert.equal(result, expected);
508
+ });
509
+ });
510
+
511
+ describe("Optional finger array element and properties", () => {
512
+ test("third element of finger array is optional (defaults to black dot)", () => {
513
+ /** @type {import("svguitar").Chord} */
514
+ const chord = {
515
+ fingers: [
516
+ [3, 2],
517
+ [4, 2],
518
+ [2, 1],
519
+ ],
520
+ barres: [],
521
+ title: "Test",
522
+ };
523
+
524
+ const result = fingeringToString(chord);
525
+
526
+ const expected = ` Test
527
+ ######
528
+ ------
529
+ ||||o|
530
+ ||oo||
531
+ ||||||`;
532
+
533
+ assert.equal(result, expected);
534
+ });
535
+
536
+ test("third element of finger array is optional (Unicode format)", () => {
537
+ /** @type {import("svguitar").Chord} */
538
+ const chord = {
539
+ fingers: [
540
+ [3, 2],
541
+ [4, 2],
542
+ [2, 1],
543
+ ],
544
+ barres: [],
545
+ title: "Test",
546
+ };
547
+
548
+ const result = fingeringToString(chord, { useUnicode: true });
549
+
550
+ const expected = ` Test
551
+ ‾‾‾‾‾‾‾‾‾‾‾
552
+ ┌─┬─┬─┬─┬─┐
553
+ │ │ │ │ ○ │
554
+ ├─┼─┼─┼─┼─┤
555
+ │ │ ○ ○ │ │
556
+ ├─┼─┼─┼─┼─┤
557
+ │ │ │ │ │ │
558
+ └─┴─┴─┴─┴─┘`;
559
+
560
+ assert.equal(result, expected);
561
+ });
562
+
563
+ test("text property is optional (defaults to empty string)", () => {
564
+ /** @type {import("svguitar").Chord} */
565
+ const chord = {
566
+ fingers: [
567
+ [3, 2, { color: "#000000" }],
568
+ [4, 2, { color: "#000000" }],
569
+ ],
570
+ barres: [],
571
+ title: "Test",
572
+ };
573
+
574
+ const result = fingeringToString(chord);
575
+
576
+ const expected = ` Test
577
+ ######
578
+ ------
579
+ ||||||
580
+ ||oo||
581
+ ||||||`;
582
+
583
+ assert.equal(result, expected);
584
+ });
585
+
586
+ test("color property is optional (defaults to black)", () => {
587
+ /** @type {import("svguitar").Chord} */
588
+ const chord = {
589
+ fingers: [
590
+ [3, 2, { text: "1" }],
591
+ [4, 2, { text: "2" }],
592
+ ],
593
+ barres: [],
594
+ title: "Test",
595
+ };
596
+
597
+ const result = fingeringToString(chord);
598
+
599
+ const expected = ` Test
600
+ ######
601
+ ------
602
+ ||||||
603
+ ||21||
604
+ ||||||`;
605
+
606
+ assert.equal(result, expected);
607
+ });
608
+
609
+ test("non-black color ignores text and shows root marker (ASCII)", () => {
610
+ /** @type {import("svguitar").Chord} */
611
+ const chord = {
612
+ fingers: [
613
+ [3, 2, { text: "R", color: "#e74c3c" }],
614
+ [4, 2, { text: "3", color: "#000000" }],
615
+ ],
616
+ barres: [],
617
+ title: "Test",
618
+ };
619
+
620
+ const result = fingeringToString(chord);
621
+
622
+ const expected = ` Test
623
+ ######
624
+ ------
625
+ ||||||
626
+ ||3*||
627
+ ||||||`;
628
+
629
+ assert.equal(result, expected);
630
+ });
631
+
632
+ test("non-black color ignores text and shows root marker (Unicode)", () => {
633
+ /** @type {import("svguitar").Chord} */
634
+ const chord = {
635
+ fingers: [
636
+ [3, 2, { text: "R", color: "#e74c3c" }],
637
+ [4, 2, { text: "3", color: "#000000" }],
638
+ ],
639
+ barres: [],
640
+ title: "Test",
641
+ };
642
+
643
+ const result = fingeringToString(chord, { useUnicode: true });
644
+
645
+ const expected = ` Test
646
+ ‾‾‾‾‾‾‾‾‾‾‾
647
+ ┌─┬─┬─┬─┬─┐
648
+ │ │ │ │ │ │
649
+ ├─┼─┼─┼─┼─┤
650
+ │ │ 3 ● │ │
651
+ ├─┼─┼─┼─┼─┤
652
+ │ │ │ │ │ │
653
+ └─┴─┴─┴─┴─┘`;
654
+
655
+ assert.equal(result, expected);
656
+ });
657
+
658
+ test("any non-black color is treated as root marker", () => {
659
+ /** @type {import("svguitar").Chord} */
660
+ const chord = {
661
+ fingers: [
662
+ [3, 2, { text: "", color: "#ff0000" }],
663
+ [4, 2, { text: "", color: "#00ff00" }],
664
+ [5, 2, { text: "", color: "#0000ff" }],
665
+ ],
666
+ barres: [],
667
+ title: "Test",
668
+ };
669
+
670
+ const result = fingeringToString(chord);
671
+
672
+ const expected = ` Test
673
+ ######
674
+ ------
675
+ ||||||
676
+ |***||
677
+ ||||||`;
678
+
679
+ assert.equal(result, expected);
680
+ });
681
+
682
+ test("empty options object in finger array treated as default", () => {
683
+ /** @type {import("svguitar").Chord} */
684
+ const chord = {
685
+ fingers: [
686
+ [3, 2, {}],
687
+ [4, 2, {}],
688
+ ],
689
+ barres: [],
690
+ title: "Test",
691
+ };
692
+
693
+ const result = fingeringToString(chord);
694
+
695
+ const expected = ` Test
696
+ ######
697
+ ------
698
+ ||||||
699
+ ||oo||
700
+ ||||||`;
701
+
702
+ assert.equal(result, expected);
703
+ });
704
+ });
705
+ });