@goplayerjuggler/abc-tools 1.0.0 → 1.0.2

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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@goplayerjuggler/abc-tools",
3
- "version": "1.0.0",
4
- "description": "sorting algorithm and implementation for ABC tunes; plus other tools to come later",
3
+ "version": "1.0.2",
4
+ "description": "sorting algorithm and implementation for ABC tunes; plus other tools for parsing and manipulating ABC tunes",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
7
7
  "test": "jest",
@@ -15,6 +15,7 @@
15
15
  "music",
16
16
  "melody",
17
17
  "sorting",
18
+ "parsing",
18
19
  "modal",
19
20
  "tune",
20
21
  "traditional",
package/src/incipit.js ADDED
@@ -0,0 +1,268 @@
1
+ "use strict";
2
+ const { Fraction } = require("./math.js");
3
+ const {getFirstBars} = require("./manipulator.js")
4
+
5
+ const {
6
+ getUnitLength,
7
+ getMeter
8
+ } = require("./parser.js");
9
+
10
+ //const incipitLength = 35;
11
+ //
12
+ // Clean an incipit line
13
+ //
14
+ // function cleanIncipitLine(theTextIncipit) {
15
+ // //console.log("Starting incipit:");
16
+ // //console.log(theTextIncipit);
17
+
18
+ // // Strip any embedded voice [V:*]
19
+ // let searchRegExp = /\[V:\s*\d+\]/gm;
20
+ // theTextIncipit = theTextIncipit.replace(searchRegExp, "");
21
+ // //console.log(theTextIncipit);
22
+
23
+ // // Strip any embedded voice V: *
24
+ // //searchRegExp = /V: [^ ]+ /gm
25
+ // searchRegExp = /V:\s+\S+\s/gm;
26
+ // theTextIncipit = theTextIncipit.replace(searchRegExp, "");
27
+ // //console.log(theTextIncipit);
28
+
29
+ // // Strip any embedded voice V:*
30
+ // searchRegExp = /V:[^ ]+ /gm;
31
+ // theTextIncipit = theTextIncipit.replace(searchRegExp, "");
32
+ // //console.log(theTextIncipit);
33
+
34
+ // // Sanitize !*! style annotations, but keep !fermata!
35
+ // searchRegExp = /!(?!fermata!)[^!\n]*!/gm;
36
+ // theTextIncipit = theTextIncipit.replace(searchRegExp, "");
37
+ // //console.log(theTextIncipit);
38
+
39
+ // // Strip out repeat marks
40
+ // theTextIncipit = theTextIncipit.replaceAll("|:", "|");
41
+ // theTextIncipit = theTextIncipit.replaceAll(":|", "|");
42
+
43
+ // // strip out 1st 2nd etc time repeats
44
+ // searchRegExp = /\[\d(,\d)*/gm;
45
+ // theTextIncipit = theTextIncipit.replace(searchRegExp, "");
46
+
47
+ // //console.log(theTextIncipit);
48
+
49
+ // // Strip out brackets
50
+ // // theTextIncipit = theTextIncipit.replaceAll("[", "");
51
+ // //console.log(theTextIncipit);
52
+
53
+ // // Strip out brackets
54
+ // // theTextIncipit = theTextIncipit.replaceAll("]", "");
55
+ // //console.log(theTextIncipit);
56
+
57
+ // // // Strip out continuations
58
+ // // theTextIncipit = theTextIncipit.replaceAll("\\", "");
59
+
60
+ // // Segno
61
+ // theTextIncipit = theTextIncipit.replaceAll("S", "");
62
+
63
+ // // Strip out comments
64
+ // theTextIncipit = theTextIncipit.replace(/"[^"]+"/gm, "");
65
+ // // Strip out inline parts
66
+ // theTextIncipit = theTextIncipit.replace(/\[P:[Ⅰ\w]\]/gm, "");
67
+
68
+ // //console.log("Final raw incipit :");
69
+ // //console.log(theTextIncipit);
70
+
71
+ // return theTextIncipit;
72
+ // }
73
+
74
+ function StripAnnotationsOneForIncipits(theNotes) {
75
+ // Strip out tempo markings
76
+ let searchRegExp = /^Q:.*[\r\n]*/gm;
77
+
78
+ // Strip out tempo markings
79
+ theNotes = theNotes.replace(searchRegExp, "");
80
+
81
+ // Strip out Z: annotation
82
+ searchRegExp = /^Z:.*[\r\n]*/gm;
83
+
84
+ // Strip out Z: annotation
85
+ theNotes = theNotes.replace(searchRegExp, "");
86
+
87
+ // Strip out R: annotation
88
+ searchRegExp = /^R:.*[\r\n]*/gm;
89
+
90
+ // Strip out R: annotation
91
+ theNotes = theNotes.replace(searchRegExp, "");
92
+
93
+ // Strip out S: annotation
94
+ searchRegExp = /^S:.*[\r\n]*/gm;
95
+
96
+ // Strip out S: annotation
97
+ theNotes = theNotes.replace(searchRegExp, "");
98
+
99
+ // Strip out N: annotation
100
+ searchRegExp = /^N:.*[\r\n]*/gm;
101
+
102
+ // Strip out N: annotation
103
+ theNotes = theNotes.replace(searchRegExp, "");
104
+
105
+ // Strip out D: annotation
106
+ searchRegExp = /^D:.*[\r\n]*/gm;
107
+
108
+ // Strip out D: annotation
109
+ theNotes = theNotes.replace(searchRegExp, "");
110
+
111
+ // Strip out H: annotation
112
+ searchRegExp = /^H:.*[\r\n]*/gm;
113
+
114
+ // Strip out H: annotation
115
+ theNotes = theNotes.replace(searchRegExp, "");
116
+
117
+ // Strip out B: annotation
118
+ searchRegExp = /^B:.*[\r\n]*/gm;
119
+
120
+ // Strip out B: annotation
121
+ theNotes = theNotes.replace(searchRegExp, "");
122
+
123
+ // Strip out C: annotation
124
+ searchRegExp = /^C:.*[\r\n]*/gm;
125
+
126
+ // Strip out C: annotation
127
+ theNotes = theNotes.replace(searchRegExp, "");
128
+
129
+ // Strip out O: annotation
130
+ searchRegExp = /^O:.*[\r\n]*/gm;
131
+
132
+ // Strip out O: annotation
133
+ theNotes = theNotes.replace(searchRegExp, "");
134
+
135
+ // Strip out A: annotation
136
+ searchRegExp = /^A:.*[\r\n]*/gm;
137
+
138
+ // Strip out A: annotation
139
+ theNotes = theNotes.replace(searchRegExp, "");
140
+
141
+ // Strip out P: annotation
142
+ searchRegExp = /^P:.*[\r\n]*/gm;
143
+
144
+ // Strip out P: annotation
145
+ theNotes = theNotes.replace(searchRegExp, "");
146
+
147
+ return theNotes;
148
+ }
149
+
150
+ //
151
+ // Strip all the text annotations in the ABC
152
+ //
153
+ function StripTextAnnotationsOne(theNotes) {
154
+ // Strip out text markings
155
+ let searchRegExp = /%%text .*[\r\n]*/gm;
156
+
157
+ theNotes = theNotes.replace(searchRegExp, "");
158
+
159
+ searchRegExp = /%%text[\r\n]/gm;
160
+
161
+ theNotes = theNotes.replace(searchRegExp, "");
162
+
163
+ // Strip out %%center annotation
164
+ searchRegExp = /%%center.*[\r\n]*/gm;
165
+
166
+ // Strip out %%center annotation
167
+ theNotes = theNotes.replace(searchRegExp, "");
168
+
169
+ // Strip out %%right annotation
170
+ searchRegExp = /%%right.*[\r\n]*/gm;
171
+
172
+ // Strip out %%right annotation
173
+ theNotes = theNotes.replace(searchRegExp, "");
174
+
175
+ // Strip out %%begintext / %%endtext blocks
176
+ theNotes = theNotes.replace(/^%%begintext[\s\S]*?^%%endtext.*(\r?\n)?/gm, "");
177
+
178
+ return theNotes;
179
+ }
180
+
181
+ //
182
+ // Strip all the chords in the ABC
183
+ //
184
+ function StripChordsOne(theNotes) {
185
+ function match_callback(match) {
186
+ // Don't strip tab annotations, only chords
187
+ if (match.indexOf('"_') === -1 && match.indexOf('"^') === -1) {
188
+ // Try and avoid stripping long text strings that aren't chords
189
+ if (match.length > 9) {
190
+ return match;
191
+ }
192
+ // If there are spaces in the match, also probably not a chord
193
+ else if (match.indexOf(" ") !== -1) {
194
+ return match;
195
+ } else {
196
+ return "";
197
+ }
198
+ } else {
199
+ return match;
200
+ }
201
+ }
202
+
203
+ // Strip out chord markings and not text annotations
204
+ const searchRegExp = /"[^"]*"/gm;
205
+
206
+ const output = theNotes
207
+ .split("\n")
208
+ .map((line) => {
209
+ // If line starts with one of the forbidden prefixes, skip replacement
210
+ if (/^[XTMKLQWZRCAOPNGHBDFSIV]:/.test(line) || /^%/.test(line)) {
211
+ return line;
212
+ } else {
213
+ return line.replace(searchRegExp, match_callback);
214
+ }
215
+ })
216
+ .join("\n");
217
+
218
+ // Replace the ABC
219
+ return output;
220
+ }
221
+
222
+ function sanitise (theTune) {
223
+
224
+ // Strip out annotations
225
+ theTune = StripAnnotationsOneForIncipits(theTune);
226
+
227
+ // Strip out textnnotations
228
+ theTune = StripTextAnnotationsOne(theTune);
229
+
230
+ // Strip out chord markings
231
+ theTune = StripChordsOne(theTune);
232
+
233
+ return theTune;
234
+ };
235
+
236
+
237
+ /**
238
+ * Get incipit (opening bars) of a tune for display/search purposes
239
+ * @param {object} Object of the form {abc} with optional property: numBars
240
+ * @param {string} params.abc - ABC notation
241
+ * @param {number|Fraction} params.numBars - Number of bars to return, counting the anacrucis if there is one. (default:2)
242
+ * @returns {string} - ABC incipit
243
+ */
244
+ function getIncipit({
245
+ abc,
246
+ numBars, //, part=null
247
+ } = {}) {
248
+ if (!numBars) {
249
+ numBars = 2;
250
+ const currentMeter = getMeter(abc);
251
+ const unitLength = getUnitLength(abc);
252
+ if (
253
+ (currentMeter[0] === 4 &&
254
+ currentMeter[1] === 4 &&
255
+ unitLength.den === 16) ||
256
+ (currentMeter[0] === 4 &&
257
+ currentMeter[1] === 2 &&
258
+ unitLength.den === 8) ||
259
+ (currentMeter[0] === 12 && currentMeter[1] === 8)
260
+ ) {
261
+ numBars = new Fraction(3, 2);
262
+ }
263
+ }
264
+ abc = sanitise(abc)
265
+ return getFirstBars(abc, numBars, true, true, { all: true });
266
+ }
267
+
268
+ module.exports = {getIncipit}
package/src/index.js CHANGED
@@ -6,6 +6,7 @@
6
6
  const parser = require('./parser.js');
7
7
  const manipulator = require('./manipulator.js');
8
8
  const sort = require('./contour-sort.js');
9
+ const incipit = require('./incipit.js');
9
10
 
10
11
  module.exports = {
11
12
  // Parser functions
@@ -15,5 +16,8 @@ module.exports = {
15
16
  ...manipulator,
16
17
 
17
18
  // Sort functions
18
- ...sort
19
+ ...sort,
20
+
21
+ // Incipit functions
22
+ ...incipit
19
23
  };
@@ -2,7 +2,6 @@ const { Fraction } = require("./math.js");
2
2
  const {
3
3
  parseABCWithBars,
4
4
  getMeter,
5
- getUnitLength,
6
5
  calculateBarDurations,
7
6
  } = require("./parser.js");
8
7
 
@@ -439,39 +438,9 @@ function getFirstBars(
439
438
  )}`;
440
439
  }
441
440
 
442
- /**
443
- * Get incipit (opening bars) of a tune for display/search purposes
444
- * @param {object} Object of the form {abc} with optional property: numBars
445
- * @param {string} params.abc - ABC notation
446
- * @param {number|Fraction} params.numBars - Number of bars to return, counting the anacrucis if there is one. (default:2)
447
- * @returns {string} - ABC incipit
448
- */
449
- function getIncipit({
450
- abc,
451
- numBars, //, part=null
452
- } = {}) {
453
- if (!numBars) {
454
- numBars = 2;
455
- const currentMeter = getMeter(abc);
456
- const unitLength = getUnitLength(abc);
457
- if (
458
- (currentMeter[0] === 4 &&
459
- currentMeter[1] === 4 &&
460
- unitLength.den === 16) ||
461
- (currentMeter[0] === 4 &&
462
- currentMeter[1] === 2 &&
463
- unitLength.den === 8) ||
464
- (currentMeter[0] === 12 && currentMeter[1] === 8)
465
- ) {
466
- numBars = new Fraction(3, 2);
467
- }
468
- }
469
- return getFirstBars(abc, numBars, true, true, { all: true });
470
- }
471
441
 
472
442
  module.exports = {
473
443
  getFirstBars,
474
- getIncipit,
475
444
  hasAnacrucis,
476
445
  toggleMeter_4_4_to_4_2,
477
446
  toggleMeter_6_8_to_12_8,