Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

abcjs

Package Overview
Dependencies
Maintainers
1
Versions
116
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

abcjs - npm Package Compare versions

Comparing version 6.2.3 to 6.3.0

src/tablatures/instruments/tab-string-patterns.js

2

index.js

@@ -60,2 +60,3 @@ /**!

var getMidiFile = require('./src/synth/get-midi-file');
var midiRenderer = require('./src/synth/abc_midi_renderer');

@@ -75,2 +76,3 @@ abcjs.synth = {

sequence: sequence,
midiRenderer: midiRenderer,
};

@@ -77,0 +79,0 @@

2

package.json
{
"name": "abcjs",
"version": "6.2.3",
"version": "6.3.0",
"description": "Renderer for abc music notation",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -251,5 +251,5 @@ /**!

var abcjs = {
plugin: Plugin
plugin: plugin
};
module.exports = abcjs;

@@ -13,2 +13,6 @@ ![abcjs](https://paulrosen.github.io/abcjs/img/abcjs_comp_extended_08.svg)

## Announcement: version 6.3.0
Most users won't see any difference, but there was some changes to the underlying SVG structure for the top (the title, etc.) and bottom (the notes, etc.) text, so if your code depends on particular classes then this might be a breaking change. Hopefully the new structure will be clearer and will allow css to target particular parts easier.
## Announcement: version 6.2.2

@@ -15,0 +19,0 @@

@@ -8,4 +8,3 @@ /*

*/
var ViolinTablature = require('../tablatures/instruments/violin/tab-violin');
var GuitarTablature = require('../tablatures/instruments/guitar/tab-guitar');
var StringTablature = require('../tablatures/instruments/tab-string');

@@ -16,6 +15,7 @@ /* extend the table below when adding a new instrument plugin */

var pluginTab = {
'violin': 'ViolinTab',
'fiddle': 'ViolinTab',
'mandolin': 'ViolinTab',
'guitar': 'GuitarTab'
'violin': { name: 'StringTab', defaultTuning: ['G,', 'D', 'A', 'e'], isTabBig: false, tabSymbolOffset: 0},
'fiddle': { name: 'StringTab', defaultTuning: ['G,', 'D', 'A', 'e'], isTabBig: false, tabSymbolOffset: 0},
'mandolin': { name: 'StringTab', defaultTuning: ['G,', 'D', 'A', 'e'], isTabBig: false, tabSymbolOffset: 0},
'guitar': { name: 'StringTab', defaultTuning: ['E,', 'A,', 'D', 'G' , 'B' , 'e'], isTabBig: true, tabSymbolOffset: 0},
'fiveString': { name: 'StringTab', defaultTuning: ['C,', 'G,', 'D', 'A', 'e'], isTabBig: false, tabSymbolOffset: -.95},
};

@@ -71,3 +71,3 @@

if (tabName) {
plugin = this.plugins[tabName];
plugin = this.plugins[tabName.name];
}

@@ -85,2 +85,3 @@ if (plugin) {

instance: null,
tabType: tabName,
};

@@ -110,12 +111,46 @@ // proceed with tab plugin init

*/
layoutTablatures: function (renderer, abcTune) {
layoutTablatures: function layoutTablatures(renderer, abcTune) {
var tabs = abcTune.tablatures;
// chack tabs request for each staffs
var staffLineCount = 0;
// Clear the suppression flag
if (tabs && (tabs.length > 0)){
var nTabs = tabs.length;
for (var kk=0;kk<nTabs;++kk){
if (tabs[kk] && tabs[kk].params.firstStaffOnly){
tabs[kk].params.suppress = false;
}
}
}
for (var ii = 0; ii < abcTune.lines.length; ii++) {
var line = abcTune.lines[ii];
if (line.staff){
staffLineCount++;
}
// MAE 27Nov2023
// If tab param "firstStaffOnly", remove the tab label after the first staff
if (staffLineCount > 1){
if (tabs && (tabs.length > 0)){
var nTabs = tabs.length;
for (var kk=0;kk<nTabs;++kk){
if (tabs[kk].params.firstStaffOnly){
// Set the staff draw suppression flag
tabs[kk].params.suppress = true;
}
}
}
}
var curStaff = line.staff;
if (curStaff) {
var maxStaves = curStaff.length
for (var jj = 0; jj < curStaff.length; jj++) {
if (tabs[jj]) {
// tablature requested for staff
if (tabs[jj] && jj < maxStaves) {
// tablature requested for staff
var tabPlugin = tabs[jj];

@@ -129,3 +164,4 @@ if (tabPlugin.instance == null) {

tabPlugin.params,
jj
jj,
tabPlugin.tabType
);

@@ -147,4 +183,3 @@ }

if (!this.inited) {
this.register(new ViolinTablature());
this.register(new GuitarTablature());
this.register(new StringTablature());
this.inited = true;

@@ -151,0 +186,0 @@ }

@@ -687,23 +687,23 @@ var parseCommon = require('./abc_common');

parseDirective.parseFontChangeLine = function(textstr) {
// We don't want to match two dollar signs, so change those temporarily
textstr = textstr.replace(/\$\$/g,"\x03")
var textParts = textstr.split('$');
if (textParts.length > 1 && multilineVars.setfont) {
var textarr = [ { text: textParts[0] }];
var textarr = [ ];
if (textParts[0] !== '') // did the original string start with `$`?
textarr.push({ text: textParts[0] })
for (var i = 1; i < textParts.length; i++) {
if (textParts[i][0] === '0')
textarr.push({ text: textParts[i].substring(1) });
else if (textParts[i][0] === '1' && multilineVars.setfont[1])
textarr.push({font: multilineVars.setfont[1], text: textParts[i].substring(1) });
else if (textParts[i][0] === '2' && multilineVars.setfont[2])
textarr.push({font: multilineVars.setfont[2], text: textParts[i].substring(1) });
else if (textParts[i][0] === '3' && multilineVars.setfont[3])
textarr.push({font: multilineVars.setfont[3], text: textParts[i].substring(1) });
else if (textParts[i][0] === '4' && multilineVars.setfont[4])
textarr.push({font: multilineVars.setfont[4], text: textParts[i].substring(1) });
else
textarr[textarr.length-1].text += '$' + textParts[i];
textarr.push({ text: textParts[i].substring(1).replace(/\x03/g,"$$") });
else {
var whichFont = parseInt(textParts[i][0],10)
if (multilineVars.setfont[whichFont])
textarr.push({font: multilineVars.setfont[whichFont], text: textParts[i].substring(1).replace(/\x03/g,"$$") });
else
textarr[textarr.length-1].text += '$' + textParts[i].replace(/\x03/g,"$$");
}
}
if (textarr.length > 1)
return textarr;
return textarr;
}
return textstr;
return textstr.replace(/\x03/g,"$$");
};

@@ -752,2 +752,3 @@

case "jazzchords":tune.formatting.jazzchords = true;break;
case "accentAbove":tune.formatting.accentAbove = true;break;
case "germanAlphabet":tune.formatting.germanAlphabet = true;break;

@@ -944,3 +945,3 @@ case "landscape":multilineVars.landscape = true;break;

var sfNum = parseInt(sfTokens[1].token);
if (sfNum >= 1 && sfNum <= 4) {
if (sfNum >= 1 && sfNum <= 9) {
if (!multilineVars.setfont)

@@ -947,0 +948,0 @@ multilineVars.setfont = [];

@@ -14,11 +14,8 @@ // abc_parse_header.js: parses a the header fields from a string representing ABC Music Notation into a usable internal structure.

this.setTitle = function(title) {
this.setTitle = function(title, origSize) {
if (multilineVars.hasMainTitle)
tuneBuilder.addSubtitle(tokenizer.translateString(tokenizer.stripComment(title)), { startChar: multilineVars.iChar, endChar: multilineVars.iChar+title.length+2}); // display secondary title
tuneBuilder.addSubtitle(title, { startChar: multilineVars.iChar, endChar: multilineVars.iChar+origSize+2}); // display secondary title
else
{
var titleStr = tokenizer.translateString(tokenizer.theReverser(tokenizer.stripComment(title)));
if (multilineVars.titlecaps)
titleStr = titleStr.toUpperCase();
tuneBuilder.addMetaText("title", titleStr, { startChar: multilineVars.iChar, endChar: multilineVars.iChar+title.length+2});
tuneBuilder.addMetaText("title", title, { startChar: multilineVars.iChar, endChar: multilineVars.iChar+origSize+2});
multilineVars.hasMainTitle = true;

@@ -375,6 +372,7 @@ }

case "[P:":
var part = parseDirective.parseFontChangeLine(line.substring(i+3, e))
if (startLine || tune.lines.length <= tune.lineNum)
multilineVars.partForNextLine = { title: line.substring(i+3, e), startChar: startChar, endChar: endChar };
multilineVars.partForNextLine = { title: part, startChar: startChar, endChar: endChar };
else
tuneBuilder.appendElement('part', startChar, endChar, {title: line.substring(i+3, e)});
tuneBuilder.appendElement('part', startChar, endChar, {title: part});
return [ e-i+1+ws ];

@@ -482,8 +480,10 @@ case "[L:":

var field = metaTextHeaders[line[0]];
if (field !== undefined) {
if (field === 'unalignedWords')
tuneBuilder.addMetaTextArray(field, parseDirective.parseFontChangeLine(tokenizer.translateString(tokenizer.stripComment(line.substring(2)))), { startChar: multilineVars.iChar, endChar: multilineVars.iChar+line.length});
else
tuneBuilder.addMetaText(field, tokenizer.translateString(tokenizer.stripComment(line.substring(2))), { startChar: multilineVars.iChar, endChar: multilineVars.iChar+line.length});
return {};
var origSize = line.length-2
var restOfLine = tokenizer.translateString(tokenizer.stripComment(line.substring(2)))
if (field === 'unalignedWords' || field === 'notes') {
// These fields can be multi-line
tuneBuilder.addMetaTextArray(field, parseDirective.parseFontChangeLine(restOfLine), { startChar: multilineVars.iChar, endChar: multilineVars.iChar+line.length});
} else if (field !== undefined) {
// these fields are single line
tuneBuilder.addMetaText(field, parseDirective.parseFontChangeLine(restOfLine), { startChar: multilineVars.iChar, endChar: multilineVars.iChar+line.length});
} else {

@@ -495,7 +495,8 @@ var startChar = multilineVars.iChar;

case 'H':
tuneBuilder.addMetaText("history", tokenizer.translateString(tokenizer.stripComment(line.substring(2))), { startChar: multilineVars.iChar, endChar: multilineVars.iChar+line.length});
// History is a little different because once it starts it continues until another header field is encountered
tuneBuilder.addMetaTextArray("history", parseDirective.parseFontChangeLine(restOfLine), { startChar: multilineVars.iChar, endChar: multilineVars.iChar+line.length});
line = tokenizer.peekLine()
while (line && line[1] !== ':') {
tokenizer.nextLine()
tuneBuilder.addMetaText("history", tokenizer.translateString(tokenizer.stripComment(line)), { startChar: multilineVars.iChar, endChar: multilineVars.iChar+line.length});
tuneBuilder.addMetaTextArray("history", parseDirective.parseFontChangeLine(tokenizer.translateString(tokenizer.stripComment(line))), { startChar: multilineVars.iChar, endChar: multilineVars.iChar+line.length});
line = tokenizer.peekLine()

@@ -525,5 +526,5 @@ }

if (multilineVars.is_in_header)
tuneBuilder.addMetaText("partOrder", tokenizer.translateString(tokenizer.stripComment(line.substring(2))), { startChar: multilineVars.iChar, endChar: multilineVars.iChar+line.length});
tuneBuilder.addMetaText("partOrder", parseDirective.parseFontChangeLine(restOfLine), { startChar: multilineVars.iChar, endChar: multilineVars.iChar+line.length});
else
multilineVars.partForNextLine = { title: tokenizer.translateString(tokenizer.stripComment(line.substring(2))), startChar: startChar, endChar: endChar};
multilineVars.partForNextLine = { title: restOfLine, startChar: startChar, endChar: endChar};
break;

@@ -541,3 +542,5 @@ case 'Q':

case 'T':
this.setTitle(line.substring(2));
if (multilineVars.titlecaps)
restOfLine = restOfLine.toUpperCase();
this.setTitle(parseDirective.parseFontChangeLine(tokenizer.theReverser(restOfLine)), origSize);
break;

@@ -544,0 +547,0 @@ case 'U':

@@ -642,10 +642,75 @@ // abc_tokenizer.js: tokenizes an ABC Music Notation string to support abc_parse.

this.theReverser = function(str) {
if (parseCommon.endsWith(str, ", The"))
return "The " + str.substring(0, str.length-5);
if (parseCommon.endsWith(str, ", A"))
return "A " + str.substring(0, str.length-3);
return str;
};
//
// MAE 10 Jan 2023 - For better handling of tunes that have tune numbers in front of them.
//
// Previous version would take:
// 21. Woman of the House, The
// and return:
// The 21. Woman of the House
//
// This fix results in:
// 21. The Woman of the House
//
// Also added additional checks and handlers for lower case ", the" and ", a" since I found several tune collections with those tune name constructs
//
// Find an optional title number at the start of a tune title
function getTitleNumber(str){
const regex = /^(\d+)\./;
// Use the exec method to search for the pattern in the string
const match = regex.exec(str);
// Check if a match is found
if (match) {
// The matched number is captured in the first group (index 1)
const foundNumber = match[1];
return foundNumber;
} else {
// Return null if no match is found
return null;
}
}
var thePatterns = [
{ match: /,\s*[Tt]he$/, replace: "The " },
{ match: /,\s*[Aa]$/, replace: "A " },
{ match: /,\s*[Aa]n$/, replace: "An " },
]
this.theReverser = function (str) {
for (var i = 0; i < thePatterns.length; i++) {
var thisPattern = thePatterns[i]
var match = str.match(thisPattern.match)
if (match) {
var theTitleNumber = getTitleNumber(str);
if (theTitleNumber){
//console.log("theReverser The titlenumber:"+theTitleNumber);
str = str.replace(theTitleNumber+".","");
str = str.trim();
}
var len = match[0].length
var result = thisPattern.replace + str.substring(0, str.length - len);
if (theTitleNumber){
result = theTitleNumber+". "+result;
}
return result;
}
}
return str;
};
this.stripComment = function(str) {

@@ -652,0 +717,0 @@ var i = str.indexOf('%');

var parseKeyVoice = require('../parse/abc_parse_key_voice');
var parseCommon = require('../parse/abc_common');
var parseDirective = require('./abc_parse_directive');

@@ -150,2 +151,5 @@ var TuneBuilder = function(tune) {

simplifyMetaText(tune)
//addRichTextToAnnotationsAndLyrics(tune)
// If the tempo was created with a string like "Allegro", then the duration of a beat needs to be set at the last moment, when it is most likely known.

@@ -882,3 +886,11 @@ if (tune.metaText.tempo && tune.metaText.tempo.bpm && !tune.metaText.tempo.duration)

} else {
tune.metaText[key] += "\n" + value;
if (typeof tune.metaText[key] === 'string' && typeof value === 'string')
tune.metaText[key] += "\n" + value;
else {
if (tune.metaText[key] === 'string')
tune.metaText[key] = [{text: tune.metaText[key]}]
if (typeof value === 'string')
value = [{text: value}]
tune.metaText[key] =tune.metaText[key].concat(value)
}
tune.metaTextInfo[key].endChar = info.endChar;

@@ -903,2 +915,49 @@ }

function isArrayOfStrings(arr) {
if (!arr) return false
if (typeof arr === "string") return false
var str = ''
for (var i = 0; i < arr.length; i++) {
if (typeof arr[i] !== 'string')
return false
}
return true
}
function simplifyMetaText(tune) {
if (isArrayOfStrings(tune.metaText.notes))
tune.metaText.notes = tune.metaText.notes.join("\n")
if (isArrayOfStrings(tune.metaText.history))
tune.metaText.history = tune.metaText.history.join("\n")
}
function addRichTextToAnnotationsAndLyrics(tune) {
var lines = tune.lines
for (var i = 0; i < lines.length; i++) {
if (lines[i].staff !== undefined) {
for (var s = 0; s < lines[i].staff.length; s++) {
for (var v = 0; v < lines[i].staff[s].voices.length; v++) {
var voice = lines[i].staff[s].voices[v];
for (var n = 0; n < voice.length; n++) {
var element = voice[n]
if (element.chord) {
for (var c = 0; c < element.chord.length; c++) {
element.chord[c].name = parseDirective.parseFontChangeLine(element.chord[c].name)
console.log(element.chord[c].name)
}
}
if (element.lyric) {
for (var l = 0; l < element.lyric.length; l++) {
element.lyric[l].syllable = parseDirective.parseFontChangeLine(element.lyric[l].syllable)
console.log(element.lyric[l].syllable)
}
}
}
}
}
}
}
}
module.exports = TuneBuilder;

@@ -24,2 +24,6 @@ var CreateSynthControl = require('./create-synth-control');

visualOptions = {};
if (visualOptions.displayPlay === undefined)
visualOptions.displayPlay = true
if (visualOptions.displayProgress === undefined)
visualOptions.displayProgress = true
self.control = new CreateSynthControl(selector, {

@@ -45,3 +49,3 @@ loopHandler: visualOptions.displayLoop ? self.toggleLoop : undefined,

self.disable(false);
self.options = audioParams;
self.options = audioParams ? audioParams : {};

@@ -200,3 +204,3 @@ if (self.control) {

var background = (ev.target.classList.contains('abcjs-midi-progress-indicator')) ? ev.target.parentNode : ev.target;
var percent = (ev.x - background.offsetLeft) / background.offsetWidth;
var percent = (ev.x - background.getBoundingClientRect().left) / background.offsetWidth;
if (percent < 0)

@@ -203,0 +207,0 @@ percent = 0;

@@ -268,2 +268,13 @@ const {noteToMidi} = require('../../synth/note-to-midi');

// MAE 27 Nov 2023
StringPatterns.prototype.suppress = function (plugin) {
var _super = plugin._super;
var suppress = _super.params.suppress;
if (suppress){
return true;
}
return false;
};
// MAE 27 Nov 2023 End
/**

@@ -270,0 +281,0 @@ * Common patterns for all string instruments

@@ -63,9 +63,18 @@ /**

};
var tabAbsolute = new AbsoluteElement(element, 0, 0, "symbol", 0);
tabAbsolute.x = absX;
var tabRelative = new RelativeElement(tabIcon, 0, 0, 7.5, "tab");
tabRelative.x = relX;
tabAbsolute.children.push(tabRelative);
if (tabAbsolute.abcelem.el_type == 'tab') {
tabRelative.pitch = tabYPos;
// Offset the TAB symbol position if specified in the tab description
tabYPos += plugin.tabSymbolOffset;
// For tablature like whistle tab where you want the TAB symbol hidden
if (!plugin.hideTabSymbol){
var tabAbsolute = new AbsoluteElement(element, 0, 0, "symbol", 0);
tabAbsolute.x = absX;
var tabRelative = new RelativeElement(tabIcon, 0, 0, 7.5, "tab");
tabRelative.x = relX;
tabAbsolute.children.push(tabRelative);
if (tabAbsolute.abcelem.el_type == 'tab') {
tabRelative.pitch = tabYPos;
}
}

@@ -72,0 +81,0 @@ return tabAbsolute;

@@ -40,8 +40,20 @@ /* eslint-disable no-debugger */

var tabName = stringSemantics.tabInfos(self.plugin);
var size = textSize.calc(tabName, 'tablabelfont', 'text instrumentname');
dest.tabNameInfos = {
textSize: size,
name: tabName
};
return size.height;
var suppress = stringSemantics.suppress(self.plugin);
var doDraw = true;
if (suppress){
doDraw = false
}
if (doDraw){
var size = textSize.calc(tabName, 'tablabelfont', 'text instrumentname');
dest.tabNameInfos = {
textSize: {height:size.height,width:size.width},
name: tabName
};
return size.height;
}
return 0
}

@@ -234,4 +246,6 @@

nameHeight = Math.max(nameHeight, 1) // If there is no label for the tab line, then there needs to be a little padding
staffGroup.staffs[this.staffIndex].top += nameHeight;
staffGroup.height += nameHeight * spacing.STEP;
// This was pushing down the top staff by the tab label height
//staffGroup.staffs[this.staffIndex].top += nameHeight;
staffGroup.staffs[this.staffIndex].top += 1;
staffGroup.height += nameHeight;
tabVoice.staff = staffGroupInfos;

@@ -247,3 +261,2 @@ var tabVoiceIndex = voices.length

module.exports = TabRenderer;

@@ -54,15 +54,15 @@ // abc_parser_lint.js: Analyzes the output of abc_parse.

var { legalAccents } = require('../parse/abc_parse_settings');
var ParserLint = function() {
"use strict";
var decorationList = { type: 'array', optional: true, items: { type: 'string', Enum: [
"trill", "lowermordent", "uppermordent", "mordent", "pralltriller", "accent",
"fermata", "invertedfermata", "tenuto", "0", "1", "2", "3", "4", "5", "+", "wedge",
"open", "thumb", "snap", "turn", "roll", "irishroll", "breath", "shortphrase", "mediumphrase", "longphrase",
"segno", "coda", "D.S.", "D.C.", "fine", "crescendo(", "crescendo)", "diminuendo(", "diminuendo)", "glissando(", "glissando)",
"p", "pp", "f", "ff", "mf", "mp", "ppp", "pppp", "fff", "ffff", "sfz", "repeatbar", "repeatbar2", "slide",
"upbow", "downbow", "staccato", "trem1", "trem2", "trem3", "trem4",
"/", "//", "///", "////", "turnx", "invertedturn", "invertedturnx", "arpeggio", "trill(", "trill)", "xstem",
"mark", "marcato", "umarcato", "D.C.alcoda", "D.C.alfine", "D.S.alcoda", "D.S.alfine", "editorial", "courtesy"
] } };
var ParserLint = function () {
'use strict';
var decorationList = {
type: 'array',
optional: true,
items: {
type: 'string',
Enum: legalAccents
}
};
var tempoProperties = {

@@ -431,2 +431,3 @@ duration: { type: "array", optional: true, output: "join", requires: [ 'bpm'], items: { type: "number"} },

properties: {
accentAbove: { type: "boolean", optional: true },
alignbars: { type: "number", optional: true },

@@ -433,0 +434,0 @@ aligncomposer: { type: "string", Enum: [ 'left', 'center','right' ], optional: true },

@@ -56,2 +56,3 @@ // abc_abstract_engraver.js: Creates a data structure suitable for printing a line of abc

this.jazzchords = !!options.jazzchords
this.accentAbove = !!options.accentAbove
this.germanAlphabet = !!options.germanAlphabet

@@ -834,3 +835,3 @@ this.reset();

if (elem.decoration) {
this.decoration.createDecoration(voice, elem.decoration, abselem.top, (notehead) ? notehead.w : 0, abselem, roomtaken, dir, abselem.bottom, elem.positioning, this.hasVocals);
this.decoration.createDecoration(voice, elem.decoration, abselem.top, (notehead) ? notehead.w : 0, abselem, roomtaken, dir, abselem.bottom, elem.positioning, this.hasVocals, this.accentAbove);
}

@@ -994,3 +995,3 @@

if (elem.decoration) {
this.decoration.createDecoration(voice, elem.decoration, 12, (thick) ? 3 : 1, abselem, 0, "down", 2, elem.positioning, this.hasVocals);
this.decoration.createDecoration(voice, elem.decoration, 12, (thick) ? 3 : 1, abselem, 0, "down", 2, elem.positioning, this.hasVocals, this.accentAbove);
}

@@ -997,0 +998,0 @@

@@ -9,95 +9,115 @@ var RelativeElement = require('./elements/relative-element');

var rel_position = elem.chord[i].rel_position;
var chords = elem.chord[i].name.split("\n");
for (var j = chords.length - 1; j >= 0; j--) { // parse these in opposite order because we place them from bottom to top.
var chord = chords[j];
var x = 0;
var y;
var font;
var klass;
if (pos === "left" || pos === "right" || pos === "below" || pos === "above" || !!rel_position) {
font = 'annotationfont';
klass = "annotation";
} else {
font = 'gchordfont';
klass = "chord";
chord = translateChord(chord, jazzchords, germanAlphabet);
var isAnnotation = pos === "left" || pos === "right" || pos === "below" || pos === "above" || !!rel_position
var font;
var klass;
if (isAnnotation) {
font = 'annotationfont';
klass = "abcjs-annotation";
} else {
font = 'gchordfont';
klass = "abcjs-chord";
}
var attr = getTextSize.attr(font, klass);
var name = elem.chord[i].name
var ret;
//console.log("chord",name)
if (typeof name === "string") {
ret = chordString(name, pos, rel_position, isAnnotation, font, klass, attr, getTextSize, abselem, elem, roomTaken, roomTakenRight, noteheadWidth, jazzchords, germanAlphabet)
roomTaken = ret.roomTaken
roomTakenRight = ret.roomTakenRight
} else {
for (var j = 0; j < name.length; j++) {
ret = chordString(name[j].text, pos, rel_position, isAnnotation, font, klass, attr, getTextSize, abselem, elem, roomTaken, roomTakenRight, noteheadWidth, jazzchords, germanAlphabet)
roomTaken = ret.roomTaken
roomTakenRight = ret.roomTakenRight
}
var attr = getTextSize.attr(font, klass);
var dim = getTextSize.calc(chord, font, klass);
var chordWidth = dim.width;
var chordHeight = dim.height / spacing.STEP;
switch (pos) {
case "left":
roomTaken += chordWidth + 7;
x = -roomTaken; // TODO-PER: This is just a guess from trial and error
y = elem.averagepitch;
abselem.addExtra(new RelativeElement(chord, x, chordWidth + 4, y, {
}
}
return { roomTaken: roomTaken, roomTakenRight: roomTakenRight };
};
function chordString(chordString, pos, rel_position, isAnnotation, font, klass, attr, getTextSize, abselem, elem, roomTaken, roomTakenRight, noteheadWidth, jazzchords, germanAlphabet) {
var chords = chordString.split("\n");
for (var j = chords.length - 1; j >= 0; j--) { // parse these in opposite order because we place them from bottom to top.
var chord = chords[j];
var x = 0;
var y;
if (!isAnnotation)
chord = translateChord(chord, jazzchords, germanAlphabet);
var dim = getTextSize.calc(chord, font, klass);
var chordWidth = dim.width;
var chordHeight = dim.height / spacing.STEP;
switch (pos) {
case "left":
roomTaken += chordWidth + 7;
x = -roomTaken; // TODO-PER: This is just a guess from trial and error
y = elem.averagepitch;
abselem.addExtra(new RelativeElement(chord, x, chordWidth + 4, y, {
type: "text",
height: chordHeight,
dim: attr,
position: "left"
}));
break;
case "right":
roomTakenRight += 4;
x = roomTakenRight;// TODO-PER: This is just a guess from trial and error
y = elem.averagepitch;
abselem.addRight(new RelativeElement(chord, x, chordWidth + 4, y, {
type: "text",
height: chordHeight,
dim: attr,
position: "right"
}));
break;
case "below":
// setting the y-coordinate to undefined for now: it will be overwritten later on, after we figure out what the highest element on the line is.
abselem.addRight(new RelativeElement(chord, 0, 0, undefined, {
type: "text",
position: "below",
height: chordHeight,
dim: attr,
realWidth: chordWidth
}));
break;
case "above":
// setting the y-coordinate to undefined for now: it will be overwritten later on, after we figure out what the highest element on the line is.
abselem.addRight(new RelativeElement(chord, 0, 0, undefined, {
type: "text",
position: "above",
height: chordHeight,
dim: attr,
realWidth: chordWidth
}));
break;
default:
if (rel_position) {
var relPositionY = rel_position.y + 3 * spacing.STEP; // TODO-PER: this is a fudge factor to make it line up with abcm2ps
abselem.addRight(new RelativeElement(chord, x + rel_position.x, 0, elem.minpitch + relPositionY / spacing.STEP, {
position: "relative",
type: "text",
height: chordHeight,
dim: attr,
position: "left"
dim: attr
}));
break;
case "right":
roomTakenRight += 4;
x = roomTakenRight;// TODO-PER: This is just a guess from trial and error
y = elem.averagepitch;
abselem.addRight(new RelativeElement(chord, x, chordWidth + 4, y, {
type: "text",
height: chordHeight,
dim: attr,
position: "right"
}));
break;
case "below":
} else {
// setting the y-coordinate to undefined for now: it will be overwritten later on, after we figure out what the highest element on the line is.
abselem.addRight(new RelativeElement(chord, 0, 0, undefined, {
type: "text",
position: "below",
height: chordHeight,
dim: attr,
realWidth: chordWidth
}));
break;
case "above":
// setting the y-coordinate to undefined for now: it will be overwritten later on, after we figure out what the highest element on the line is.
abselem.addRight(new RelativeElement(chord, 0, 0, undefined, {
type: "text",
position: "above",
height: chordHeight,
dim: attr,
realWidth: chordWidth
}));
break;
default:
if (rel_position) {
var relPositionY = rel_position.y + 3 * spacing.STEP; // TODO-PER: this is a fudge factor to make it line up with abcm2ps
abselem.addRight(new RelativeElement(chord, x + rel_position.x, 0, elem.minpitch + relPositionY / spacing.STEP, {
position: "relative",
type: "text",
var pos2 = 'above';
if (elem.positioning && elem.positioning.chordPosition)
pos2 = elem.positioning.chordPosition;
if (pos2 !== 'hidden') {
abselem.addCentered(new RelativeElement(chord, noteheadWidth / 2, chordWidth, undefined, {
type: "chord",
position: pos2,
height: chordHeight,
dim: attr
dim: attr,
realWidth: chordWidth
}));
} else {
// setting the y-coordinate to undefined for now: it will be overwritten later on, after we figure out what the highest element on the line is.
var pos2 = 'above';
if (elem.positioning && elem.positioning.chordPosition)
pos2 = elem.positioning.chordPosition;
if (pos2 !== 'hidden') {
abselem.addCentered(new RelativeElement(chord, noteheadWidth / 2, chordWidth, undefined, {
type: "chord",
position: pos2,
height: chordHeight,
dim: attr,
realWidth: chordWidth
}));
}
}
}
}
}
}
return { roomTaken: roomTaken, roomTakenRight: roomTakenRight };
};
}
module.exports = addChord;

@@ -11,6 +11,6 @@ function addTextIf(rows, params, getTextSize) {

rows.push({ move: params.marginTop });
var attr = { left: params.marginLeft, text: params.text, font: params.font, anchor: params.anchor, startChar: params.info.startChar, endChar: params.info.endChar };
var attr = { left: params.marginLeft, text: params.text, font: params.font, anchor: params.anchor, startChar: params.info.startChar, endChar: params.info.endChar, 'dominant-baseline': params['dominant-baseline'] };
if (params.absElemType)
attr.absElemType = params.absElemType;
if (!params.inGroup)
if (!params.inGroup && params.klass)
attr.klass = params.klass;

@@ -17,0 +17,0 @@ if (params.name)

@@ -17,6 +17,6 @@ // abc_decoration.js: Creates a data structure suitable for printing a line of abc

var closeDecoration = function (voice, decoration, pitch, width, abselem, roomtaken, dir, minPitch) {
var closeDecoration = function (voice, decoration, pitch, width, abselem, roomtaken, dir, minPitch, accentAbove) {
var yPos;
for (var i = 0; i < decoration.length; i++) {
if (decoration[i] === "staccato" || decoration[i] === "tenuto" || decoration[i] === "accent") {
if (decoration[i] === "staccato" || decoration[i] === "tenuto" || (decoration[i] === "accent" && !accentAbove)) {
var symbol = "scripts." + decoration[i];

@@ -127,3 +127,3 @@ if (decoration[i] === "accent") symbol = "scripts.sforzato";

var stackedDecoration = function (decoration, width, abselem, yPos, positioning, minTop, minBottom) {
var stackedDecoration = function (decoration, width, abselem, yPos, positioning, minTop, minBottom, accentAbove) {
function incrementPlacement(placement, height) {

@@ -268,2 +268,8 @@ if (placement === 'above')

break;
case "accent":
if (accentAbove) {
symbolDecoration("scripts.sforzato", positioning);
hasOne = true;
}
break;
}

@@ -342,3 +348,3 @@ }

Decoration.prototype.createDecoration = function (voice, decoration, pitch, width, abselem, roomtaken, dir, minPitch, positioning, hasVocals) {
Decoration.prototype.createDecoration = function (voice, decoration, pitch, width, abselem, roomtaken, dir, minPitch, positioning, hasVocals, accentAbove) {
if (!positioning)

@@ -352,10 +358,10 @@ positioning = { ornamentPosition: 'above', volumePosition: hasVocals ? 'above' : 'below', dynamicPosition: hasVocals ? 'above' : 'below' };

// treat staccato, accent, and tenuto first (may need to shift other markers)
var yPos = closeDecoration(voice, decoration, pitch, width, abselem, roomtaken, dir, minPitch);
var yPos = closeDecoration(voice, decoration, pitch, width, abselem, roomtaken, dir, minPitch, accentAbove);
// yPos is an object containing 'above' and 'below'. That is the placement of the next symbol on either side.
yPos.above = Math.max(yPos.above, this.minTop);
var hasOne = stackedDecoration(decoration, width, abselem, yPos, positioning.ornamentPosition, this.minTop, this.minBottom);
if (hasOne) {
var hasOne = stackedDecoration(decoration, width, abselem, yPos, positioning.ornamentPosition, this.minTop, this.minBottom, accentAbove);
//if (hasOne) {
// abselem.top = Math.max(yPos.above + 3, abselem.top); // TODO-PER: Not sure why we need this fudge factor.
}
//}
leftDecoration(decoration, abselem, roomtaken);

@@ -362,0 +368,0 @@ };

const addTextIf = require("../add-text-if");
const richText = require("./rich-text");
function BottomText(metaText, width, isPrint, paddingLeft, spacing, getTextSize) {
function BottomText(metaText, width, isPrint, paddingLeft, spacing, shouldAddClasses, getTextSize) {
this.rows = [];
if (metaText.unalignedWords && metaText.unalignedWords.length > 0)
this.unalignedWords(metaText.unalignedWords, paddingLeft, spacing, getTextSize);
this.extraText(metaText, paddingLeft, spacing, getTextSize);
this.unalignedWords(metaText.unalignedWords, paddingLeft, spacing, shouldAddClasses, getTextSize);
this.extraText(metaText, paddingLeft, spacing, shouldAddClasses, getTextSize);
if (metaText.footer && isPrint)

@@ -12,56 +13,70 @@ this.footer(metaText.footer, width, paddingLeft, getTextSize);

BottomText.prototype.unalignedWords = function (unalignedWords, paddingLeft, spacing, getTextSize) {
var klass = 'meta-bottom unaligned-words';
BottomText.prototype.unalignedWords = function (unalignedWords, marginLeft, spacing, shouldAddClasses, getTextSize) {
var klass = shouldAddClasses ? 'abcjs-unaligned-words' : ''
var defFont = 'wordsfont';
this.rows.push({ startGroup: "unalignedWords", klass: 'abcjs-meta-bottom abcjs-unaligned-words', name: "words" });
var space = getTextSize.calc("i", defFont, klass);
this.rows.push({ move: spacing.words });
addMultiLine(this.rows, '', unalignedWords, marginLeft, defFont, "unalignedWords", "unalignedWords", klass, "unalignedWords", spacing, shouldAddClasses, getTextSize)
this.rows.push({ move: space.height });
}
for (var j = 0; j < unalignedWords.length; j++) {
if (unalignedWords[j] === '')
this.rows.push({ move: space.height });
else if (typeof unalignedWords[j] === 'string') {
addTextIf(this.rows, { marginLeft: paddingLeft, text: unalignedWords[j], font: defFont, klass: klass, inGroup: true, name: "words" }, getTextSize);
function addSingleLine(rows, preface, text, marginLeft, klass, shouldAddClasses, getTextSize) {
if (text) {
if (preface) {
if (typeof text === 'string')
text = preface + text
else
text = [{text: preface}].concat(text)
}
klass = shouldAddClasses ? 'abcjs-extra-text '+klass : ''
richText(rows, text, 'historyfont', klass, "description", marginLeft, {absElemType: "extraText", anchor: 'start'}, getTextSize)
}
}
function addMultiLine(rows, preface, content, marginLeft, defFont, absElemType, groupName, klass, name, spacing, shouldAddClasses, getTextSize) {
if (content) {
klass = shouldAddClasses ? 'abcjs-extra-text '+klass : ''
var size = getTextSize.calc("A", defFont, klass);
if (typeof content === 'string') {
if (preface)
content = preface + "\n" + content
addTextIf(rows, { marginLeft: marginLeft, text: content, font: defFont, absElemType: "extraText", name: name, 'dominant-baseline': 'middle', klass: klass }, getTextSize);
//rows.push({move: size.height*3/4})
} else {
var largestY = 0;
var offsetX = 0;
for (var k = 0; k < unalignedWords[j].length; k++) {
var thisWord = unalignedWords[j][k];
var font = (thisWord.font) ? thisWord.font : defFont;
this.rows.push({
left: paddingLeft + offsetX,
text: thisWord.text,
font: font,
anchor: 'start'
});
var size = getTextSize.calc(thisWord.text, defFont, klass);
largestY = Math.max(largestY, size.height);
offsetX += size.width;
// If the phrase ends in a space, then that is not counted in the width, so we need to add that in ourselves.
if (thisWord.text[thisWord.text.length - 1] === ' ') {
offsetX += space.width;
}
rows.push({ startGroup: groupName, klass: klass, name: name });
rows.push({move: spacing.info})
if (preface) {
addTextIf(rows, { marginLeft: marginLeft, text: preface, font: defFont, absElemType: "extraText", name: name, 'dominant-baseline': 'middle' }, getTextSize);
rows.push({move: size.height*3/4})
}
this.rows.push({ move: largestY });
for (var j = 0; j < content.length; j++) {
richText(rows, content[j], defFont, '', name, marginLeft, {anchor: 'start'}, getTextSize)
// TODO-PER: Hack! the string and rich lines should have used up the same amount of space without this.
if (j < content.length-1 && typeof content[j] === 'string' && typeof content[j+1] !== 'string')
rows.push({move: size.height*3/4})
}
rows.push({ endGroup: groupName, absElemType: absElemType, startChar: -1, endChar: -1, name: name });
rows.push({move: size.height})
}
}
this.rows.push({ move: space.height * 2 });
this.rows.push({ endGroup: "unalignedWords", absElemType: "unalignedWords", startChar: -1, endChar: -1, name: "unalignedWords" });
}
BottomText.prototype.extraText = function (metaText, marginLeft, spacing, shouldAddClasses, getTextSize) {
addSingleLine(this.rows, "Book: ", metaText.book, marginLeft, 'abcjs-book', shouldAddClasses, getTextSize)
addSingleLine(this.rows, "Source: ", metaText.source, marginLeft, 'abcjs-source', shouldAddClasses, getTextSize)
addSingleLine(this.rows, "Discography: ", metaText.discography, marginLeft, 'abcjs-discography', shouldAddClasses, getTextSize)
BottomText.prototype.extraText = function (metaText, marginLeft, spacing, getTextSize) {
var extraText = "";
if (metaText.book) extraText += "Book: " + metaText.book + "\n";
if (metaText.source) extraText += "Source: " + metaText.source + "\n";
if (metaText.discography) extraText += "Discography: " + metaText.discography + "\n";
if (metaText.notes) extraText += "Notes: " + metaText.notes + "\n";
if (metaText.transcription) extraText += "Transcription: " + metaText.transcription + "\n";
if (metaText.history) extraText += "History: " + metaText.history + "\n";
if (metaText['abc-copyright']) extraText += "Copyright: " + metaText['abc-copyright'] + "\n";
if (metaText['abc-creator']) extraText += "Creator: " + metaText['abc-creator'] + "\n";
if (metaText['abc-edited-by']) extraText += "Edited By: " + metaText['abc-edited-by'] + "\n";
if (extraText.length > 0) {
addTextIf(this.rows, { marginLeft: marginLeft, text: extraText, font: 'historyfont', klass: 'meta-bottom extra-text', marginTop: spacing.info, absElemType: "extraText", name: "description" }, getTextSize);
}
addMultiLine(this.rows, 'Notes:', metaText.notes, marginLeft, 'historyfont', "extraText", "notes", 'abcjs-notes', "description", spacing, shouldAddClasses, getTextSize)
addSingleLine(this.rows, "Transcription: ", metaText.transcription, marginLeft, 'abcjs-transcription', shouldAddClasses, getTextSize)
addMultiLine(this.rows, "History:", metaText.history, marginLeft, 'historyfont', "extraText", "history", 'abcjs-history', "description", spacing, shouldAddClasses, getTextSize)
addSingleLine(this.rows, "Copyright: ", metaText['abc-copyright'], marginLeft, 'abcjs-copyright', shouldAddClasses, getTextSize)
addSingleLine(this.rows, "Creator: ", metaText['abc-creator'], marginLeft, 'abcjs-creator', shouldAddClasses, getTextSize)
addSingleLine(this.rows, "Edited By: ", metaText['abc-edited-by'], marginLeft, 'abcjs-edited-by', shouldAddClasses, getTextSize)
}

@@ -68,0 +83,0 @@

const addTextIf = require("../add-text-if");
const richText = require("./rich-text");
function TopText(metaText, metaTextInfo, formatting, lines, width, isPrint, paddingLeft, spacing, getTextSize) {
function TopText(metaText, metaTextInfo, formatting, lines, width, isPrint, paddingLeft, spacing, shouldAddClasses, getTextSize) {
this.rows = [];

@@ -21,3 +22,4 @@

if (metaText.title) {
addTextIf(this.rows, { marginLeft: tLeft, text: metaText.title, font: 'titlefont', klass: 'title meta-top', marginTop: spacing.title, anchor: tAnchor, absElemType: "title", info: metaTextInfo.title, name: "title" }, getTextSize);
var klass = shouldAddClasses ? 'abcjs-title' : ''
richText(this.rows, metaText.title, "titlefont", klass, 'title', tLeft, {marginTop: spacing.title, anchor: tAnchor, absElemType: "title", info: metaTextInfo.title}, getTextSize)
}

@@ -27,3 +29,4 @@ if (lines.length) {

while (index < lines.length && lines[index].subtitle) {
addTextIf(this.rows, { marginLeft: tLeft, text: lines[index].subtitle.text, font: 'subtitlefont', klass: 'text meta-top subtitle', marginTop: spacing.subtitle, anchor: tAnchor, absElemType: "subtitle", info: lines[index].subtitle, name: "subtitle" }, getTextSize);
var klass = shouldAddClasses ? 'abcjs-text abcjs-subtitle' : ''
richText(this.rows, lines[index].subtitle.text, "subtitlefont", klass, 'subtitle', tLeft, {marginTop: spacing.subtitle, anchor: tAnchor, absElemType: "subtitle", info: lines[index].subtitle}, getTextSize)
index++;

@@ -37,18 +40,41 @@ }

var noMove = !!(metaText.composer || metaText.origin);
addTextIf(this.rows, { marginLeft: paddingLeft, text: metaText.rhythm, font: 'infofont', klass: 'meta-top rhythm', absElemType: "rhythm", noMove: noMove, info: metaTextInfo.rhythm, name: "rhythm" }, getTextSize);
var klass = shouldAddClasses ? 'abcjs-rhythm' : ''
addTextIf(this.rows, { marginLeft: paddingLeft, text: metaText.rhythm, font: 'infofont', klass: klass, absElemType: "rhythm", noMove: noMove, info: metaTextInfo.rhythm, name: "rhythm" }, getTextSize);
}
var composerLine = "";
if (metaText.composer) composerLine += metaText.composer;
if (metaText.origin) composerLine += ' (' + metaText.origin + ')';
if (composerLine.length > 0) {
addTextIf(this.rows, { marginLeft: paddingLeft + width, text: composerLine, font: 'composerfont', klass: 'meta-top composer', anchor: "end", absElemType: "composer", info: metaTextInfo.composer, name: "composer" }, getTextSize);
var hasSimpleComposerLine = true
if (metaText.composer && typeof metaText.composer !== 'string')
hasSimpleComposerLine = false
if (metaText.origin && typeof metaText.origin !== 'string')
hasSimpleComposerLine = false
var composerLine = metaText.composer ? metaText.composer : '';
if (metaText.origin) {
if (typeof composerLine === 'string' && typeof metaText.origin === 'string')
composerLine += ' (' + metaText.origin + ')';
else if (typeof composerLine === 'string' && typeof metaText.origin !== 'string') {
composerLine = [{text:composerLine}]
composerLine.push({text:" ("})
composerLine = composerLine.concat(metaText.origin)
composerLine.push({text:")"})
} else {
composerLine.push({text:" ("})
composerLine = composerLine.concat(metaText.origin)
composerLine.push({text:")"})
}
}
if (composerLine) {
var klass = shouldAddClasses ? 'abcjs-composer' : ''
richText(this.rows, composerLine, 'composerfont', klass, "composer", paddingLeft+width, {anchor: "end", absElemType: "composer", info: metaTextInfo.composer, ingroup: true}, getTextSize)
}
}
if (metaText.author && metaText.author.length > 0) {
addTextIf(this.rows, { marginLeft: paddingLeft + width, text: metaText.author, font: 'composerfont', klass: 'meta-top author', anchor: "end", absElemType: "author", info: metaTextInfo.author, name: "author" }, getTextSize);
var klass = shouldAddClasses ? 'abcjs-author' : ''
richText(this.rows, metaText.author, 'composerfont', klass, "author", paddingLeft+width, {anchor: "end", absElemType: "author", info: metaTextInfo.author}, getTextSize)
}
if (metaText.partOrder && metaText.partOrder.length > 0) {
addTextIf(this.rows, { marginLeft: paddingLeft, text: metaText.partOrder, font: 'partsfont', klass: 'meta-top part-order', absElemType: "partOrder", info: metaTextInfo.partOrder, name: "part-order" }, getTextSize);
var klass = shouldAddClasses ? 'abcjs-part-order' : ''
richText(this.rows, metaText.partOrder, 'partsfont', klass, "part-order", paddingLeft, {absElemType: "partOrder", info: metaTextInfo.partOrder, anchor: 'start'}, getTextSize)
}

@@ -55,0 +81,0 @@ }

@@ -19,3 +19,6 @@ var drawTempo = require('./tempo');

default:
drawRelativeElement(renderer, child, bartop);
var el = drawRelativeElement(renderer, child, bartop);
if (child.type === "symbol" && child.c && child.c.indexOf('notehead') >= 0) {
el.setAttribute('class', 'abcjs-notehead')
}
}

@@ -22,0 +25,0 @@ }

@@ -9,3 +9,6 @@ var drawStaffGroup = require('./staff-group');

var selectables = new Selectables(renderer.paper, selectTypes, tuneNumber);
renderer.paper.openGroup()
var groupClasses = {}
if (classes.shouldAddClasses)
groupClasses.klass = "abcjs-meta-top"
renderer.paper.openGroup(groupClasses)
renderer.moveY(renderer.padding.top);

@@ -20,3 +23,5 @@ nonMusic(renderer, abcTune.topText, selectables);

if (abcLine.staff) {
renderer.paper.openGroup()
if (classes.shouldAddClasses)
groupClasses.klass = "abcjs-staff l" + classes.lineNumber
renderer.paper.openGroup(groupClasses)
if (abcLine.vskip) {

@@ -32,3 +37,5 @@ renderer.moveY(abcLine.vskip);

} else if (abcLine.nonMusic) {
renderer.paper.openGroup()
if (classes.shouldAddClasses)
groupClasses.klass = "abcjs-non-music"
renderer.paper.openGroup(groupClasses)
nonMusic(renderer, abcLine.nonMusic, selectables);

@@ -41,3 +48,5 @@ renderer.paper.closeGroup()

if (abcTune.bottomText && abcTune.bottomText.rows && abcTune.bottomText.rows.length > 0) {
renderer.paper.openGroup()
if (classes.shouldAddClasses)
groupClasses.klass = "abcjs-meta-bottom"
renderer.paper.openGroup(groupClasses)
renderer.moveY(24); // TODO-PER: Empirically discovered. What variable should this be?

@@ -44,0 +53,0 @@ nonMusic(renderer, abcTune.bottomText, selectables);

@@ -11,3 +11,3 @@ var drawSeparator = require('./separator');

renderer.moveY(row.move);
} else if (row.text) {
} else if (row.text || row.phrases) {
var x = row.left ? row.left : 0;

@@ -18,2 +18,4 @@ var el = renderText(renderer, {

text: row.text,
phrases: row.phrases,
'dominant-baseline': row['dominant-baseline'],
type: row.font,

@@ -20,0 +22,0 @@ klass: row.klass,

@@ -30,3 +30,3 @@ var renderText = require('./text');

var tabFont = "tabnumberfont";
var tabClass = 'tab-number';
var tabClass = 'abcjs-tab-number';
if (params.isGrace) {

@@ -33,0 +33,0 @@ tabFont = "tabgracefont";

@@ -19,3 +19,3 @@ var drawRelativeElement = require('./relative');

if (params.tempo.preString) {
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);
text = renderText(renderer, { x: x, y: y, text: params.tempo.preString, type: 'tempofont', klass: 'abcjs-tempo', anchor: "start", noClass: true, name: "pre" }, true);
size = renderer.controller.getTextSize.calc(params.tempo.preString, 'tempofont', 'tempo', text);

@@ -22,0 +22,0 @@ var preWidth = size.width;

@@ -5,2 +5,10 @@ var roundNumber = require("./round-number");

var y = params.y;
// TODO-PER: Probably need to merge the regular text and rich text better. At the least, rich text loses the font box.
if (params.phrases) {
//richTextLine = function (phrases, x, y, klass, anchor, target)
var elem = renderer.paper.richTextLine(params.phrases, params.x, params.y, params.klass, params.anchor);
return elem;
}
if (params.lane) {

@@ -19,2 +27,4 @@ var laneMargin = params.dim.font.size * 0.25;

hash.attr["text-anchor"] = params.anchor;
if (params['dominant-baseline'])
hash.attr["dominant-baseline"] = params['dominant-baseline'];
hash.attr.x = params.x;

@@ -21,0 +31,0 @@ hash.attr.y = y;

@@ -68,2 +68,4 @@ // abc_engraver_controller.js: Controls the engraving process of an ABCJS abstract syntax tree as produced by ABCJS/parse

this.jazzchords = params.jazzchords;
if (params.accentAbove)
this.accentAbove = params.accentAbove;
if (params.germanAlphabet)

@@ -127,2 +129,3 @@ this.germanAlphabet = params.germanAlphabet;

this.getTextSize = new GetTextSize(this.getFontAndAttr, this.renderer.paper);
var origJazzChords = this.jazzchords

@@ -175,2 +178,3 @@ this.setupTune(abcTune, 0);

}
this.jazzchords = origJazzChords
return ret;

@@ -184,2 +188,4 @@ };

this.jazzchords = abcTune.formatting.jazzchords;
if (abcTune.formatting.accentAbove !== undefined)
this.accentAbove = abcTune.formatting.accentAbove;

@@ -194,2 +200,3 @@ this.renderer.newTune(abcTune);

jazzchords: this.jazzchords,
accentAbove: this.accentAbove,
germanAlphabet: this.germanAlphabet

@@ -214,3 +221,3 @@ });

EngraverController.prototype.constructTuneElements = function (abcTune) {
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);
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);

@@ -242,17 +249,50 @@ // Generate the raw staff line data

}
abcTune.bottomText = new BottomText(abcTune.metaText, this.width, this.renderer.isPrint, this.renderer.padding.left, this.renderer.spacing, this.getTextSize);
abcTune.bottomText = new BottomText(abcTune.metaText, this.width, this.renderer.isPrint, this.renderer.padding.left, this.renderer.spacing, this.classes.shouldAddClasses, this.getTextSize);
};
EngraverController.prototype.engraveTune = function (abcTune, tuneNumber, lineOffset) {
var origJazzChords = this.jazzchords
var scale = this.setupTune(abcTune, tuneNumber);
// Create all of the element objects that will appear on the page.
this.constructTuneElements(abcTune);
//Set the top text now that we know the width
// Do all the positioning, both horizontally and vertically
var maxWidth = layout(this.renderer, abcTune, this.width, this.space, this.expandToWidest);
//Set the top text now that we know the width
if (this.expandToWidest && maxWidth > this.width + 1) {
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);
if ((abcTune.lines)&&(abcTune.lines.length > 0)){
var nlines = abcTune.lines.length;
//Set the top text now that we know the width
if (this.expandToWidest && maxWidth > this.width+1) {
abcTune.topText = new TopText(abcTune.metaText, abcTune.metaTextInfo, abcTune.formatting, abcTune.lines, maxWidth, this.renderer.isPrint, this.renderer.padding.left, this.renderer.spacing, this.getTextSize);
for (var i=0;i<nlines;++i){
var entry = abcTune.lines[i];
if (entry.nonMusic){
if ((entry.nonMusic.rows) && (entry.nonMusic.rows.length > 0)){
var nRows = entry.nonMusic.rows.length;
for (var j=0;j<nRows;++j){
var thisRow = entry.nonMusic.rows[j];
// Recenter the element if it's a subtitle or centered text
if (thisRow.left){
if (entry.subtitle){
thisRow.left = (maxWidth/2) + this.renderer.padding.left;
} else {
if ((entry.text)&&(entry.text.length>0)){
if (entry.text[0].center){
thisRow.left = (maxWidth/2) + this.renderer.padding.left;
}
}
}
}
}
}
}
}
}
}

@@ -262,5 +302,5 @@

if (abcTune.tablatures) {
tablatures.layoutTablatures(this.renderer, abcTune);
tablatures.layoutTablatures(this.renderer, abcTune);
}
// Do all the writing to the SVG

@@ -270,10 +310,11 @@ var ret = draw(this.renderer, this.classes, abcTune, this.width, maxWidth, this.responsive, scale, this.selectTypes, tuneNumber, lineOffset);

this.selectables = ret.selectables;
if (this.oneSvgPerLine) {
var div = this.renderer.paper.svg.parentNode
this.svgs = splitSvgIntoLines(this.renderer, div, abcTune.metaText.title, this.responsive)
var div = this.renderer.paper.svg.parentNode;
this.svgs = splitSvgIntoLines(this.renderer, div, abcTune.metaText.title, this.responsive);
} else {
this.svgs = [this.renderer.paper.svg];
this.svgs = [this.renderer.paper.svg];
}
setupSelection(this, this.svgs);
this.jazzchords = origJazzChords
};

@@ -280,0 +321,0 @@

@@ -82,3 +82,3 @@ var Classes = function Classes(options) {

if (c && c.length > 0) ret.push(c);
if (c === "tab-number") // TODO-PER-HACK! straighten out the tablature
if (c === "abcjs-tab-number") // TODO-PER-HACK! straighten out the tablature
return ret.join(' ')

@@ -85,0 +85,0 @@ if (c === "text instrument-name")

@@ -17,2 +17,9 @@ var GetFontAndAttr = function GetFontAndAttr(formatting, classes) {

GetFontAndAttr.prototype.getFamily = function (type) {
if (type[0] === '"' && type[type.length-1] === '"') {
return type.substring(1, type.length-1)
}
return type
};
GetFontAndAttr.prototype.calc = function (type, klass) {

@@ -34,3 +41,3 @@ var font;

"font-size": font.size, 'font-style': font.style,
"font-family": font.face, 'font-weight': font.weight, 'text-decoration': font.decoration,
"font-family": this.getFamily(font.face), 'font-weight': font.weight, 'text-decoration': font.decoration,
'class': this.classes.generate(klass)

@@ -37,0 +44,0 @@ };

@@ -14,2 +14,9 @@ var GetTextSize = function GetTextSize(getFontAndAttr, svg) {

GetTextSize.prototype.getFamily = function (type) {
if (type[0] === '"' && type[type.length-1] === '"') {
return type.substring(1, type.length-1)
}
return type
};
GetTextSize.prototype.calc = function (text, type, klass, el) {

@@ -32,3 +39,3 @@ var hash;

"font-style": type.style,
"font-family": type.face,
"font-family": this.getFamily(type.face),
"font-weight": type.weight,

@@ -35,0 +42,0 @@ "text-decoration": type.decoration,

@@ -214,2 +214,32 @@ // abc_voice_element.js: Definition of the VoiceElement class.

Svg.prototype.richTextLine = function (phrases, x, y, klass, anchor, target) {
var el = document.createElementNS(svgNS, 'text');
el.setAttribute("stroke", "none");
el.setAttribute("class", klass);
el.setAttribute("x", x);
el.setAttribute("y", y);
el.setAttribute("text-anchor", anchor);
el.setAttribute("dominant-baseline", "middle");
for (var i = 0; i < phrases.length; i++) {
var phrase = phrases[i]
var tspan = document.createElementNS(svgNS, 'tspan');
var attrs = Object.keys(phrase.attrs)
for (var j = 0; j < attrs.length; j++) {
var value = phrase.attrs[attrs[j]]
if (value !== '')
tspan.setAttribute(attrs[j], value)
}
tspan.textContent = phrase.content;
el.appendChild(tspan);
}
if (target)
target.appendChild(el);
else
this.append(el);
return el;
}
Svg.prototype.guessWidth = function (text, attr) {

@@ -216,0 +246,0 @@ var svg = this.createDummySvg();

@@ -265,2 +265,3 @@ declare module 'abcjs' {

export interface AbcVisualParams {
accentAbove?: boolean;
add_classes?: boolean;

@@ -321,4 +322,4 @@ afterParsing?: AfterParsing;

el: Selector;
cursorControl: CursorControl;
options: SynthOptions;
cursorControl?: CursorControl;
options?: SynthOptions;
}

@@ -341,3 +342,3 @@

pitch: number;
instrument: number;
instrument: string;
start: number;

@@ -852,2 +853,3 @@ end: number;

setTiming: (bpm?: number, measuresOfDelay? : number) => void;
setupEvents: (startingDelay: number, timeDivider:number, startingBpm: number, warp?: number) => Array<NoteTimingEvent>;
setUpAudio: (options: SynthOptions) => AudioTracks;

@@ -1033,7 +1035,27 @@ makeVoicesArray: () => Array<Selectable[]>

export interface AudioTrack {
cmd: AudioTrackCommand;
[param: string]: any; // TODO - make this a union
export interface AudioTrackProgramItem {
cmd: 'program';
channel: number;
instrument: number;
}
export interface AudioTrackNoteItem {
cmd: 'note';
duration: number;
endChar: number;
endType?: "staccato"|"tenuto";
gap: number;
instrument: number;
pitch: number;
start: number;
startChar: number;
volume: number;
}
export interface AudioTrackTextItem {
cmd: 'text';
type: 'name';
text: string;
}
export type AudioTrack = Array<AudioTrackProgramItem|AudioTrackNoteItem|AudioTrackTextItem>
export interface AudioTracks {

@@ -1165,2 +1187,3 @@ tempo: number;

getIsRunning(): boolean
getAudioBuffer(): AudioBuffer | undefined
}

@@ -1197,2 +1220,18 @@

export interface MidiRenderer {
setTempo(bpm: number): void
setGlobalInfo(bpm: number, name: string, key:KeySignature, time:MeterFraction): void
startTrack(): void
endTrack(): void
setText(type: string, text: string):void
setInstrument(instrument: number):void
setChannel(channel:number, pan?: number):void
startNote(pitch:number, loudness:number, cents?:number):void
endNote(pitch:number):void
addRest(length:number):void
getData():string
embed(parent:Element, noplayer:boolean):void
}
export namespace synth {

@@ -1212,2 +1251,3 @@ let instrumentIndexToName: [string]

export function sequence(visualObj: TuneObject, options: AbcVisualParams): AudioSequence
export function midiRenderer(): MidiRenderer
}

@@ -1214,0 +1254,0 @@

@@ -1,3 +0,3 @@

var version = '6.2.3';
var version = '6.3.0';
module.exports = version;

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc