abcjs 6.2.2 → 6.3.0

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.
Files changed (66) hide show
  1. package/README.md +4 -0
  2. package/RELEASE.md +78 -0
  3. package/abc2xml_239/abc2xml.html +769 -0
  4. package/abc2xml_239/abc2xml.py +2248 -0
  5. package/abc2xml_239/abc2xml_changelog.html +124 -0
  6. package/abc2xml_239/lazy-river.abc +26 -0
  7. package/abc2xml_239/lazy-river.xml +3698 -0
  8. package/abc2xml_239/mean-to-me.abc +22 -0
  9. package/abc2xml_239/mean-to-me.xml +2954 -0
  10. package/abc2xml_239/pyparsing.py +3672 -0
  11. package/abc2xml_239/pyparsing.pyc +0 -0
  12. package/dist/abcjs-basic-min.js +2 -2
  13. package/dist/abcjs-basic.js +909 -485
  14. package/dist/abcjs-basic.js.map +1 -1
  15. package/dist/abcjs-plugin-min.js +2 -2
  16. package/index.js +2 -0
  17. package/package.json +1 -1
  18. package/plugin.js +1 -1
  19. package/src/api/abc_tablatures.js +51 -13
  20. package/src/api/abc_tunebook_svg.js +5 -3
  21. package/src/parse/abc_parse_directive.js +17 -16
  22. package/src/parse/abc_parse_header.js +22 -19
  23. package/src/parse/abc_parse_music.js +18 -53
  24. package/src/parse/abc_parse_settings.js +165 -0
  25. package/src/parse/abc_tokenizer.js +72 -7
  26. package/src/parse/tune-builder.js +60 -1
  27. package/src/synth/create-synth.js +4 -0
  28. package/src/synth/place-note.js +6 -0
  29. package/src/synth/play-event.js +7 -5
  30. package/src/synth/synth-controller.js +6 -2
  31. package/src/tablatures/instruments/string-patterns.js +11 -0
  32. package/src/tablatures/instruments/{guitar/guitar-patterns.js → tab-string-patterns.js} +6 -6
  33. package/src/tablatures/instruments/{violin/tab-violin.js → tab-string.js} +13 -11
  34. package/src/tablatures/tab-absolute-elements.js +19 -9
  35. package/src/tablatures/tab-renderer.js +24 -10
  36. package/src/test/abc_parser_lint.js +1 -0
  37. package/src/write/creation/abstract-engraver.js +9 -2
  38. package/src/write/creation/add-chord.js +102 -82
  39. package/src/write/creation/add-text-if.js +2 -2
  40. package/src/write/creation/decoration.js +16 -8
  41. package/src/write/creation/elements/bottom-text.js +62 -47
  42. package/src/write/creation/elements/rich-text.js +51 -0
  43. package/src/write/creation/elements/top-text.js +37 -11
  44. package/src/write/creation/glyphs.js +2 -2
  45. package/src/write/draw/absolute.js +4 -1
  46. package/src/write/draw/draw.js +13 -4
  47. package/src/write/draw/glissando.js +1 -0
  48. package/src/write/draw/non-music.js +3 -1
  49. package/src/write/draw/relative.js +1 -1
  50. package/src/write/draw/set-paper-size.js +1 -1
  51. package/src/write/draw/tempo.js +1 -1
  52. package/src/write/draw/text.js +10 -0
  53. package/src/write/draw/tie.js +9 -1
  54. package/src/write/engraver-controller.js +58 -11
  55. package/src/write/helpers/classes.js +1 -1
  56. package/src/write/helpers/get-font-and-attr.js +8 -1
  57. package/src/write/helpers/get-text-size.js +8 -1
  58. package/src/write/interactive/selection.js +6 -0
  59. package/src/write/layout/layout.js +33 -3
  60. package/src/write/svg.js +30 -0
  61. package/temp.txt +50 -0
  62. package/types/index.d.ts +74 -26
  63. package/version.js +1 -1
  64. package/.github/workflows/tests.yml +0 -29
  65. package/src/tablatures/instruments/guitar/tab-guitar.js +0 -48
  66. package/src/tablatures/instruments/violin/violin-patterns.js +0 -23
@@ -11,6 +11,7 @@ function drawGlissando(renderer, params, selectables) {
11
11
  var rightY = renderer.calcY(params.anchor2.heads[0].pitch)
12
12
  var leftX = params.anchor1.x + params.anchor1.w / 2
13
13
  var rightX = params.anchor2.x + params.anchor2.w / 2
14
+
14
15
  var len = lineLength(leftX, leftY, rightX, rightY)
15
16
  var marginLeft = params.anchor1.w / 2 + margin
16
17
  var marginRight = params.anchor2.w / 2 + margin
@@ -8,12 +8,14 @@ function nonMusic(renderer, obj, selectables) {
8
8
  renderer.absolutemoveY(row.absmove);
9
9
  } else if (row.move) {
10
10
  renderer.moveY(row.move);
11
- } else if (row.text) {
11
+ } else if (row.text || row.phrases) {
12
12
  var x = row.left ? row.left : 0;
13
13
  var el = renderText(renderer, {
14
14
  x: x,
15
15
  y: renderer.y,
16
16
  text: row.text,
17
+ phrases: row.phrases,
18
+ 'dominant-baseline': row['dominant-baseline'],
17
19
  type: row.font,
18
20
  klass: row.klass,
19
21
  name: row.name,
@@ -27,7 +27,7 @@ function drawRelativeElement(renderer, params, bartop) {
27
27
  case "tabNumber":
28
28
  var hAnchor = "middle";
29
29
  var tabFont = "tabnumberfont";
30
- var tabClass = 'tab-number';
30
+ var tabClass = 'abcjs-tab-number';
31
31
  if (params.isGrace) {
32
32
  tabFont = "tabgracefont";
33
33
  y += 2.5;
@@ -1,5 +1,5 @@
1
1
  function setPaperSize(renderer, maxwidth, scale, responsive) {
2
- var w = (maxwidth + renderer.padding.right) * scale;
2
+ var w = (maxwidth + renderer.padding.left + renderer.padding.right) * scale;
3
3
  var h = (renderer.y + renderer.padding.bottom) * scale;
4
4
  if (renderer.isPrint)
5
5
  h = Math.max(h, 1056); // 11in x 72pt/in x 1.33px/pt
@@ -16,7 +16,7 @@ function drawTempo(renderer, params) {
16
16
  var text;
17
17
  var size;
18
18
  if (params.tempo.preString) {
19
- text = renderText(renderer, { x: x, y: y, text: params.tempo.preString, type: 'tempofont', klass: 'abcjs-tempo', anchor: "start", noClass: true, "dominant-baseline": "ideographic", name: "pre" }, true);
19
+ text = renderText(renderer, { x: x, y: y, text: params.tempo.preString, type: 'tempofont', klass: 'abcjs-tempo', anchor: "start", noClass: true, name: "pre" }, true);
20
20
  size = renderer.controller.getTextSize.calc(params.tempo.preString, 'tempofont', 'tempo', text);
21
21
  var preWidth = size.width;
22
22
  var charWidth = preWidth / params.tempo.preString.length; // Just get some average number to increase the spacing.
@@ -2,6 +2,14 @@ var roundNumber = require("./round-number");
2
2
 
3
3
  function renderText(renderer, params, alreadyInGroup) {
4
4
  var y = params.y;
5
+
6
+ // TODO-PER: Probably need to merge the regular text and rich text better. At the least, rich text loses the font box.
7
+ if (params.phrases) {
8
+ //richTextLine = function (phrases, x, y, klass, anchor, target)
9
+ var elem = renderer.paper.richTextLine(params.phrases, params.x, params.y, params.klass, params.anchor);
10
+ return elem;
11
+ }
12
+
5
13
  if (params.lane) {
6
14
  var laneMargin = params.dim.font.size * 0.25;
7
15
  y += (params.dim.font.size + laneMargin) * params.lane;
@@ -15,6 +23,8 @@ function renderText(renderer, params, alreadyInGroup) {
15
23
  hash = renderer.controller.getFontAndAttr.calc(params.type, params.klass);
16
24
  if (params.anchor)
17
25
  hash.attr["text-anchor"] = params.anchor;
26
+ if (params['dominant-baseline'])
27
+ hash.attr["dominant-baseline"] = params['dominant-baseline'];
18
28
  hash.attr.x = params.x;
19
29
  hash.attr.y = y;
20
30
  if (!params.centerVertically)
@@ -17,7 +17,15 @@ function drawTie(renderer, params, linestartx, lineendx, selectables) {
17
17
  klass = "abcjs-hint";
18
18
  var fudgeY = params.fixedY ? 1.5 : 0; // TODO-PER: This just compensates for drawArc, which contains too much knowledge of ties and slurs.
19
19
  var el = drawArc(renderer, params.startX, params.endX, params.startY + fudgeY, params.endY + fudgeY, params.above, klass, params.isTie, params.dotted);
20
- selectables.wrapSvgEl({ el_type: "slur", startChar: -1, endChar: -1 }, el);
20
+ var startChar = -1
21
+ // This gets the start and end points of the contents of the slur. We assume that the parenthesis are just to the outside of that.
22
+ if (params.anchor1 && !params.isTie)
23
+ startChar = params.anchor1.parent.abcelem.startChar - 1
24
+ var endChar = -1
25
+ if (params.anchor2 && !params.isTie)
26
+ endChar = params.anchor2.parent.abcelem.endChar + 1
27
+
28
+ selectables.wrapSvgEl({ el_type: "slur", startChar: startChar, endChar: endChar }, el);
21
29
  return [el];
22
30
  }
23
31
 
@@ -40,6 +40,7 @@ var EngraverController = function (paper, params) {
40
40
  this.responsive = params.responsive;
41
41
  this.space = 3 * spacing.SPACE;
42
42
  this.initialClef = params.initialClef;
43
+ this.expandToWidest = !!params.expandToWidest;
43
44
  this.scale = params.scale ? parseFloat(params.scale) : 0;
44
45
  this.classes = new Classes({ shouldAddClasses: params.add_classes });
45
46
  if (!(this.scale > 0.1))
@@ -64,6 +65,8 @@ var EngraverController = function (paper, params) {
64
65
  this.renderer.showDebug = params.showDebug;
65
66
  if (params.jazzchords)
66
67
  this.jazzchords = params.jazzchords;
68
+ if (params.accentAbove)
69
+ this.accentAbove = params.accentAbove;
67
70
  if (params.germanAlphabet)
68
71
  this.germanAlphabet = params.germanAlphabet;
69
72
  if (params.lineThickness)
@@ -122,6 +125,7 @@ EngraverController.prototype.getMeasureWidths = function (abcTune) {
122
125
  this.reset();
123
126
  this.getFontAndAttr = new GetFontAndAttr(abcTune.formatting, this.classes);
124
127
  this.getTextSize = new GetTextSize(this.getFontAndAttr, this.renderer.paper);
128
+ var origJazzChords = this.jazzchords
125
129
 
126
130
  this.setupTune(abcTune, 0);
127
131
  this.constructTuneElements(abcTune);
@@ -169,6 +173,7 @@ EngraverController.prototype.getMeasureWidths = function (abcTune) {
169
173
  } else
170
174
  needNewSection = true;
171
175
  }
176
+ this.jazzchords = origJazzChords
172
177
  return ret;
173
178
  };
174
179
 
@@ -177,6 +182,8 @@ EngraverController.prototype.setupTune = function (abcTune, tuneNumber) {
177
182
 
178
183
  if (abcTune.formatting.jazzchords !== undefined)
179
184
  this.jazzchords = abcTune.formatting.jazzchords;
185
+ if (abcTune.formatting.accentAbove !== undefined)
186
+ this.accentAbove = abcTune.formatting.accentAbove;
180
187
 
181
188
  this.renderer.newTune(abcTune);
182
189
  this.engraver = new AbstractEngraver(this.getTextSize, tuneNumber, {
@@ -186,6 +193,7 @@ EngraverController.prototype.setupTune = function (abcTune, tuneNumber) {
186
193
  percmap: abcTune.formatting.percmap,
187
194
  initialClef: this.initialClef,
188
195
  jazzchords: this.jazzchords,
196
+ accentAbove: this.accentAbove,
189
197
  germanAlphabet: this.germanAlphabet
190
198
  });
191
199
  this.engraver.setStemHeight(this.renderer.spacing.stemHeight);
@@ -205,7 +213,7 @@ EngraverController.prototype.setupTune = function (abcTune, tuneNumber) {
205
213
  };
206
214
 
207
215
  EngraverController.prototype.constructTuneElements = function (abcTune) {
208
- abcTune.topText = new TopText(abcTune.metaText, abcTune.metaTextInfo, abcTune.formatting, abcTune.lines, this.width, this.renderer.isPrint, this.renderer.padding.left, this.renderer.spacing, this.getTextSize);
216
+ abcTune.topText = new TopText(abcTune.metaText, abcTune.metaTextInfo, abcTune.formatting, abcTune.lines, this.width, this.renderer.isPrint, this.renderer.padding.left, this.renderer.spacing, this.classes.shouldAddClasses, this.getTextSize);
209
217
 
210
218
  // Generate the raw staff line data
211
219
  var i;
@@ -232,35 +240,74 @@ EngraverController.prototype.constructTuneElements = function (abcTune) {
232
240
  abcLine.nonMusic = new Separator(abcLine.separator.spaceAbove, abcLine.separator.lineLength, abcLine.separator.spaceBelow);
233
241
  }
234
242
  }
235
- abcTune.bottomText = new BottomText(abcTune.metaText, this.width, this.renderer.isPrint, this.renderer.padding.left, this.renderer.spacing, this.getTextSize);
243
+ abcTune.bottomText = new BottomText(abcTune.metaText, this.width, this.renderer.isPrint, this.renderer.padding.left, this.renderer.spacing, this.classes.shouldAddClasses, this.getTextSize);
236
244
  };
237
245
 
238
246
  EngraverController.prototype.engraveTune = function (abcTune, tuneNumber, lineOffset) {
239
- var scale = this.setupTune(abcTune, tuneNumber);
240
247
 
248
+ var origJazzChords = this.jazzchords
249
+ var scale = this.setupTune(abcTune, tuneNumber);
250
+
241
251
  // Create all of the element objects that will appear on the page.
242
252
  this.constructTuneElements(abcTune);
243
-
253
+
254
+ //Set the top text now that we know the width
255
+
244
256
  // Do all the positioning, both horizontally and vertically
245
- var maxWidth = layout(this.renderer, abcTune, this.width, this.space);
257
+ var maxWidth = layout(this.renderer, abcTune, this.width, this.space, this.expandToWidest);
258
+
259
+ //Set the top text now that we know the width
260
+ if (this.expandToWidest && maxWidth > this.width + 1) {
261
+
262
+ abcTune.topText = new TopText(abcTune.metaText, abcTune.metaTextInfo, abcTune.formatting, abcTune.lines, maxWidth, this.renderer.isPrint, this.renderer.padding.left, this.renderer.spacing, this.classes.shouldAddClasses, this.getTextSize);
263
+
264
+ if ((abcTune.lines)&&(abcTune.lines.length > 0)){
265
+ var nlines = abcTune.lines.length;
266
+
267
+ for (var i=0;i<nlines;++i){
268
+ var entry = abcTune.lines[i];
269
+ if (entry.nonMusic){
270
+ if ((entry.nonMusic.rows) && (entry.nonMusic.rows.length > 0)){
271
+ var nRows = entry.nonMusic.rows.length;
272
+ for (var j=0;j<nRows;++j){
273
+ var thisRow = entry.nonMusic.rows[j];
274
+ // Recenter the element if it's a subtitle or centered text
275
+ if (thisRow.left){
276
+ if (entry.subtitle){
277
+ thisRow.left = (maxWidth/2) + this.renderer.padding.left;
278
+ } else {
279
+ if ((entry.text)&&(entry.text.length>0)){
280
+ if (entry.text[0].center){
281
+ thisRow.left = (maxWidth/2) + this.renderer.padding.left;
282
+ }
283
+ }
284
+ }
285
+ }
286
+ }
287
+ }
288
+ }
289
+ }
290
+ }
291
+ }
246
292
 
247
293
  // Deal with tablature for staff
248
294
  if (abcTune.tablatures) {
249
- tablatures.layoutTablatures(this.renderer, abcTune);
295
+ tablatures.layoutTablatures(this.renderer, abcTune);
250
296
  }
251
-
297
+
252
298
  // Do all the writing to the SVG
253
299
  var ret = draw(this.renderer, this.classes, abcTune, this.width, maxWidth, this.responsive, scale, this.selectTypes, tuneNumber, lineOffset);
254
300
  this.staffgroups = ret.staffgroups;
255
301
  this.selectables = ret.selectables;
256
-
257
302
  if (this.oneSvgPerLine) {
258
- var div = this.renderer.paper.svg.parentNode
259
- this.svgs = splitSvgIntoLines(this.renderer, div, abcTune.metaText.title, this.responsive)
303
+ var div = this.renderer.paper.svg.parentNode;
304
+ this.svgs = splitSvgIntoLines(this.renderer, div, abcTune.metaText.title, this.responsive);
260
305
  } else {
261
- this.svgs = [this.renderer.paper.svg];
306
+ this.svgs = [this.renderer.paper.svg];
262
307
  }
263
308
  setupSelection(this, this.svgs);
309
+
310
+ this.jazzchords = origJazzChords
264
311
  };
265
312
 
266
313
  function splitSvgIntoLines(renderer, output, title, responsive) {
@@ -79,7 +79,7 @@ Classes.prototype.generate = function (c) {
79
79
  return "";
80
80
  var ret = [];
81
81
  if (c && c.length > 0) ret.push(c);
82
- if (c === "tab-number") // TODO-PER-HACK! straighten out the tablature
82
+ if (c === "abcjs-tab-number") // TODO-PER-HACK! straighten out the tablature
83
83
  return ret.join(' ')
84
84
  if (c === "text instrument-name")
85
85
  return "abcjs-text abcjs-instrument-name"
@@ -14,6 +14,13 @@ GetFontAndAttr.prototype.updateFonts = function (fontOverrides) {
14
14
  this.formatting.vocalfont = fontOverrides.vocalfont;
15
15
  };
16
16
 
17
+ GetFontAndAttr.prototype.getFamily = function (type) {
18
+ if (type[0] === '"' && type[type.length-1] === '"') {
19
+ return type.substring(1, type.length-1)
20
+ }
21
+ return type
22
+ };
23
+
17
24
  GetFontAndAttr.prototype.calc = function (type, klass) {
18
25
  var font;
19
26
  if (typeof type === 'string') {
@@ -30,7 +37,7 @@ GetFontAndAttr.prototype.calc = function (type, klass) {
30
37
 
31
38
  var attr = {
32
39
  "font-size": font.size, 'font-style': font.style,
33
- "font-family": font.face, 'font-weight': font.weight, 'text-decoration': font.decoration,
40
+ "font-family": this.getFamily(font.face), 'font-weight': font.weight, 'text-decoration': font.decoration,
34
41
  'class': this.classes.generate(klass)
35
42
  };
36
43
  return { font: font, attr: attr };
@@ -11,6 +11,13 @@ GetTextSize.prototype.attr = function (type, klass) {
11
11
  return this.getFontAndAttr.calc(type, klass);
12
12
  };
13
13
 
14
+ GetTextSize.prototype.getFamily = function (type) {
15
+ if (type[0] === '"' && type[type.length-1] === '"') {
16
+ return type.substring(1, type.length-1)
17
+ }
18
+ return type
19
+ };
20
+
14
21
  GetTextSize.prototype.calc = function (text, type, klass, el) {
15
22
  var hash;
16
23
  // This can be passed in either a string or a font. If it is a string it names one of the standard fonts.
@@ -28,7 +35,7 @@ GetTextSize.prototype.calc = function (text, type, klass, el) {
28
35
  attr: {
29
36
  "font-size": type.size,
30
37
  "font-style": type.style,
31
- "font-family": type.face,
38
+ "font-family": this.getFamily(type.face),
32
39
  "font-weight": type.weight,
33
40
  "text-decoration": type.decoration,
34
41
  "class": this.getFontAndAttr.classes.generate(klass)
@@ -127,6 +127,8 @@ function keyboardSelection(ev) {
127
127
  }
128
128
 
129
129
  function findElementInHistory(selectables, el) {
130
+ if (!el)
131
+ return -1;
130
132
  for (var i = 0; i < selectables.length; i++) {
131
133
  if (el.dataset.index === selectables[i].svgEl.dataset.index)
132
134
  return i;
@@ -195,9 +197,13 @@ function getBestMatchCoordinates(dim, ev, scale) {
195
197
 
196
198
  function getTarget(target) {
197
199
  // This searches up the dom for the first item containing the attribute "selectable", or stopping at the SVG.
200
+ if (!target)
201
+ return null;
198
202
  if (target.tagName === "svg")
199
203
  return target;
200
204
 
205
+ if (!target.getAttribute)
206
+ return null;
201
207
  var found = target.getAttribute("selectable");
202
208
  while (!found) {
203
209
  if (!target.parentElement)
@@ -3,7 +3,7 @@ var setUpperAndLowerElements = require('./set-upper-and-lower-elements');
3
3
  var layoutStaffGroup = require('./staff-group');
4
4
  var getLeftEdgeOfStaff = require('./get-left-edge-of-staff');
5
5
 
6
- var layout = function (renderer, abctune, width, space) {
6
+ var layout = function (renderer, abctune, width, space, expandToWidest) {
7
7
  var i;
8
8
  var abcLine;
9
9
  // Adjust the x-coordinates to their absolute positions
@@ -11,8 +11,14 @@ var layout = function (renderer, abctune, width, space) {
11
11
  for (i = 0; i < abctune.lines.length; i++) {
12
12
  abcLine = abctune.lines[i];
13
13
  if (abcLine.staff) {
14
- setXSpacing(renderer, width, space, abcLine.staffGroup, abctune.formatting, i === abctune.lines.length - 1, false);
15
- if (abcLine.staffGroup.w > maxWidth) maxWidth = abcLine.staffGroup.w;
14
+ // console.log("=== line", i)
15
+ var thisWidth = setXSpacing(renderer, maxWidth, space, abcLine.staffGroup, abctune.formatting, i === abctune.lines.length - 1, false);
16
+ // console.log(thisWidth, maxWidth)
17
+ if (Math.round(thisWidth) > Math.round(maxWidth)) { // to take care of floating point weirdness
18
+ maxWidth = thisWidth
19
+ if (expandToWidest)
20
+ i = -1 // do the calculations over with the new width
21
+ }
16
22
  }
17
23
  }
18
24
 
@@ -41,15 +47,39 @@ var setXSpacing = function (renderer, width, space, staffGroup, formatting, isLa
41
47
  var leftEdge = getLeftEdgeOfStaff(renderer, staffGroup.getTextSize, staffGroup.voices, staffGroup.brace, staffGroup.bracket);
42
48
  var newspace = space;
43
49
  for (var it = 0; it < 8; it++) { // TODO-PER: shouldn't need multiple passes, but each pass gets it closer to the right spacing. (Only affects long lines: normal lines break out of this loop quickly.)
50
+ // console.log("iteration", it)
51
+ // dumpGroup("before", staffGroup)
44
52
  var ret = layoutStaffGroup(newspace, renderer, debug, staffGroup, leftEdge);
53
+ // dumpGroup("after",staffGroup)
45
54
  newspace = calcHorizontalSpacing(isLastLine, formatting.stretchlast, width + renderer.padding.left, staffGroup.w, newspace, ret.spacingUnits, ret.minSpace, renderer.padding.left + renderer.padding.right);
46
55
  if (debug)
47
56
  console.log("setXSpace", it, staffGroup.w, newspace, staffGroup.minspace);
48
57
  if (newspace === null) break;
49
58
  }
50
59
  centerWholeRests(staffGroup.voices);
60
+ return staffGroup.w - leftEdge
51
61
  };
52
62
 
63
+ // function dumpGroup(label, staffGroup) {
64
+ // var output = {
65
+ // line: staffGroup.line,
66
+ // w: staffGroup.w,
67
+ // voice: {
68
+ // i: staffGroup.voices[0].i,
69
+ // minx: staffGroup.voices[0].minx,
70
+ // nextx: staffGroup.voices[0].nextx,
71
+ // spacingduration: staffGroup.voices[0].spacingduration,
72
+ // w: staffGroup.voices[0].w,
73
+ // children: [],
74
+ // }
75
+ // }
76
+ // for (var i = 0; i < staffGroup.voices[0].children.length; i++) {
77
+ // var child = staffGroup.voices[0].children[i]
78
+ // output.voice.children.push({ fixedW: child.fixed.w, w: child.w, x: child.x, type: child.type })
79
+ // }
80
+ // console.log(label,output)
81
+ // }
82
+
53
83
  function calcHorizontalSpacing(isLastLine, stretchLast, targetWidth, lineWidth, spacing, spacingUnits, minSpace, padding) {
54
84
  if (isLastLine) {
55
85
  if (stretchLast === undefined) {
package/src/write/svg.js CHANGED
@@ -211,6 +211,36 @@ Svg.prototype.text = function (text, attr, target) {
211
211
  return el;
212
212
  };
213
213
 
214
+ Svg.prototype.richTextLine = function (phrases, x, y, klass, anchor, target) {
215
+ var el = document.createElementNS(svgNS, 'text');
216
+ el.setAttribute("stroke", "none");
217
+ el.setAttribute("class", klass);
218
+ el.setAttribute("x", x);
219
+ el.setAttribute("y", y);
220
+ el.setAttribute("text-anchor", anchor);
221
+ el.setAttribute("dominant-baseline", "middle");
222
+
223
+ for (var i = 0; i < phrases.length; i++) {
224
+ var phrase = phrases[i]
225
+ var tspan = document.createElementNS(svgNS, 'tspan');
226
+ var attrs = Object.keys(phrase.attrs)
227
+ for (var j = 0; j < attrs.length; j++) {
228
+ var value = phrase.attrs[attrs[j]]
229
+ if (value !== '')
230
+ tspan.setAttribute(attrs[j], value)
231
+ }
232
+ tspan.textContent = phrase.content;
233
+
234
+ el.appendChild(tspan);
235
+ }
236
+
237
+ if (target)
238
+ target.appendChild(el);
239
+ else
240
+ this.append(el);
241
+ return el;
242
+ }
243
+
214
244
  Svg.prototype.guessWidth = function (text, attr) {
215
245
  var svg = this.createDummySvg();
216
246
  var el = this.text(text, attr, svg);
package/temp.txt ADDED
@@ -0,0 +1,50 @@
1
+ ## Features
2
+
3
+ ### Tablature
4
+ * Add tab feature `hideTabSymbol`
5
+ * Add 5-string tab named "fiveString"
6
+ * Make "mandolin" and "fiddle" synonyms for "violin" in tablature.
7
+
8
+ ### Synth
9
+ * change the default synth control options for "play" and "progress" to be true
10
+ * expose the MIDI creator function
11
+ * Add a `getIsRunning()` function to enable play/pause
12
+ * allow passing in soundfont and debug callback when playing an event directly.
13
+
14
+ ### Rich Text
15
+ * allow up to 9 custom fonts in `%%setfont`
16
+ * for rich text fields, escape two dollar signs
17
+ * allow rich text in all non-music fields
18
+ * give all non-music fields a unique class
19
+
20
+ ### Miscellaneous
21
+ * add abcjs-notehead class to note heads;
22
+ * add `accentAbove` parameter
23
+ * handle numbered tune names in the reverser
24
+ * support reversing tune names with ", a" and ", an", with a variable amount of whitespace and case-insensitive
25
+ * Add Glissando Synonyms
26
+ * Put start and end char on slurs so they can be selected.
27
+ * Add `expandToWidest` option
28
+
29
+ ## Bugs
30
+ * fix placement of tab staff when there is no label
31
+ * fix font placement bugs
32
+ * remove spurious quotes in font name in svg attribute
33
+ * Fix the name of the `abcjs-tab-number` class
34
+ * fix crash when skipping a staff when creating tablature
35
+ * Fix tab staff height when there is a label
36
+ * Fix for crash when rendering multiple tab staves
37
+ * Offset breath mark to the right
38
+ * Center text when using `expandToWidest` set true
39
+ * fix placement of triangle notehead
40
+ * `afterParsing` now works with line wrapping.
41
+ * Add paddingleft to the size of the SVG - it was cut off if the padding was larger than the default.
42
+ * Guard against crash when the synth note wasn't loaded.
43
+ * protect against spurious mouse click in selection
44
+ * Fix bug in Firefox that cuts off the last line of the SVG
45
+
46
+ ## Documentation
47
+ * add missing typescript types
48
+ * fix synth control types
49
+ * fixed some typescript types in the TimingCallbacks
50
+ * TimingEvent is now NoteTimingEvent