Skip to content

Commit

Permalink
Improvements to support use as an ES module.
Browse files Browse the repository at this point in the history
API adjustments to support the migration of music21j to VexFlow 4.
  • Loading branch information
ronyeh committed Nov 11, 2021
1 parent 5a118ee commit 20c9b62
Show file tree
Hide file tree
Showing 9 changed files with 35 additions and 19 deletions.
17 changes: 11 additions & 6 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,17 @@ function getConfig(file, bundleStrategy = SINGLE_BUNDLE, mode = PRODUCTION_MODE)
// - `globalThis.Vex` in node JS >= 12
// - `this.Vex` in all other environments
// See: https://webpack.js.org/configuration/output/#outputglobalobject
let globalObject = `typeof window !== 'undefined' ? window : typeof globalThis !== 'undefined' ? globalThis : this`;
// However, the globalObject approach currently breaks the lazy loading of fonts.
// Unset the globalObject if we are doing lazy loading / code splitting with webpack.
//
// IMPORTANT: The outer parentheses are required! Webpack inserts this string into the final output, and
// without the parentheses, code splitting will be broken. Search for `webpackChunkVex` inside the output files.
let globalObject = `(typeof window !== 'undefined' ? window : typeof globalThis !== 'undefined' ? globalThis : this)`;

let chunkFilename = undefined;
let publicPath = 'auto';
if (bundleStrategy === CODE_SPLITTING) {
// Font files for dynamic import. See: webpackChunkName in async.ts
chunkFilename = 'vexflow-font-[name].js';
publicPath = './';
}

return {
Expand All @@ -76,7 +80,7 @@ function getConfig(file, bundleStrategy = SINGLE_BUNDLE, mode = PRODUCTION_MODE)
export: 'default',
},
globalObject: globalObject,
publicPath: 'auto',
publicPath: publicPath,
},
resolve: {
extensions: ['.ts', '...'],
Expand Down Expand Up @@ -217,11 +221,12 @@ module.exports = (grunt) => {
// We take a JS file that sets globalThis.Vex, and turn it into a ES module.
// To do this, we extract all the classes from Vex.Flow, and re-export them.
// We also export Vex both as a named export and as a default export.
// THIS IS A HACK, so we should figure out how to use webpack to export both ESM and CJS.
const exports = `
const Vex = globalThis['Vex'];
const Flow = Vex.Flow;
const { Accidental, Annotation, Articulation, BarNote, Beam, Bend, BoundingBox, BoundingBoxComputation, ChordSymbol, Clef, ClefNote, Crescendo, Curve, Dot, EasyScore, Element, Factory, Font, Formatter, Fraction, FretHandFinger, GhostNote, Glyph, GlyphNote, GraceNote, GraceNoteGroup, GraceTabNote, KeyManager, KeySignature, KeySigNote, Modifier, ModifierContext, MultiMeasureRest, Music, Note, NoteHead, NoteSubGroup, Ornament, Parser, PedalMarking, Registry, RenderContext, Renderer, RepeatNote, Stave, Barline, StaveConnector, StaveHairpin, StaveLine, StaveModifier, StaveNote, Repetition, StaveTempo, StaveText, StaveTie, Volta, Stem, StringNumber, Stroke, System, Tables, TabNote, TabSlide, TabStave, TabTie, TextBracket, TextDynamics, TextFormatter, TextNote, TickContext, TimeSignature, TimeSigNote, Tremolo, Tuning, Tuplet, Vibrato, VibratoBracket, Voice } = Vex.Flow;
export { Accidental, Annotation, Articulation, BarNote, Beam, Bend, BoundingBox, BoundingBoxComputation, ChordSymbol, Clef, ClefNote, Crescendo, Curve, Dot, EasyScore, Element, Factory, Font, Formatter, Fraction, FretHandFinger, GhostNote, Glyph, GlyphNote, GraceNote, GraceNoteGroup, GraceTabNote, KeyManager, KeySignature, KeySigNote, Modifier, ModifierContext, MultiMeasureRest, Music, Note, NoteHead, NoteSubGroup, Ornament, Parser, PedalMarking, Registry, RenderContext, Renderer, RepeatNote, Stave, Barline, StaveConnector, StaveHairpin, StaveLine, StaveModifier, StaveNote, Repetition, StaveTempo, StaveText, StaveTie, Volta, Stem, StringNumber, Stroke, System, Tables, TabNote, TabSlide, TabStave, TabTie, TextBracket, TextDynamics, TextFormatter, TextNote, TickContext, TimeSignature, TimeSigNote, Tremolo, Tuning, Tuplet, Vibrato, VibratoBracket, Voice };
const { Accidental, Annotation, Articulation, BarNote, Beam, Bend, BoundingBox, BoundingBoxComputation, ChordSymbol, Clef, ClefNote, Crescendo, Curve, Dot, EasyScore, Element, Factory, Font, Formatter, Fraction, FretHandFinger, GhostNote, Glyph, GlyphNote, GraceNote, GraceNoteGroup, GraceTabNote, KeyManager, KeySignature, KeySigNote, Modifier, ModifierContext, MultiMeasureRest, Music, Note, NoteHead, NoteSubGroup, Ornament, Parser, PedalMarking, Registry, RenderContext, Renderer, RepeatNote, Stave, Barline, StaveConnector, StaveHairpin, StaveLine, StaveModifier, StaveNote, Repetition, StaveTempo, StaveText, StaveTie, Volta, Stem, StringNumber, Stroke, System, Tables, TabNote, TabSlide, TabStave, TabTie, TextBracket, TextDynamics, TextFormatter, TextNote, TickContext, TimeSignature, TimeSigNote, Tremolo, Tuning, Tuplet, Vibrato, VibratoBracket, Voice, BarlineType, ModifierPosition } = Vex.Flow;
export { Accidental, Annotation, Articulation, BarNote, Beam, Bend, BoundingBox, BoundingBoxComputation, ChordSymbol, Clef, ClefNote, Crescendo, Curve, Dot, EasyScore, Element, Factory, Font, Formatter, Fraction, FretHandFinger, GhostNote, Glyph, GlyphNote, GraceNote, GraceNoteGroup, GraceTabNote, KeyManager, KeySignature, KeySigNote, Modifier, ModifierContext, MultiMeasureRest, Music, Note, NoteHead, NoteSubGroup, Ornament, Parser, PedalMarking, Registry, RenderContext, Renderer, RepeatNote, Stave, Barline, StaveConnector, StaveHairpin, StaveLine, StaveModifier, StaveNote, Repetition, StaveTempo, StaveText, StaveTie, Volta, Stem, StringNumber, Stroke, System, Tables, TabNote, TabSlide, TabStave, TabTie, TextBracket, TextDynamics, TextFormatter, TextNote, TickContext, TimeSignature, TimeSigNote, Tremolo, Tuning, Tuplet, Vibrato, VibratoBracket, Voice, BarlineType, ModifierPosition };
export { Vex, Flow };
export default Vex;`;
// Append our magic exports. :-)
Expand Down
1 change: 0 additions & 1 deletion demos/node/svg.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

const Vex = require('../../build/vexflow-debug');
const { JSDOM } = require('jsdom');
const fs = require('fs');

const VF = Vex.Flow;

Expand Down
4 changes: 2 additions & 2 deletions src/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -507,8 +507,8 @@ export class Factory {
}

StaveTie(params: {
from: Note | null;
to: Note | null;
from?: Note | null;
to?: Note | null;
first_indices?: number[];
last_indices?: number[];
text?: string;
Expand Down
9 changes: 7 additions & 2 deletions src/flow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { GraceTabNote } from './gracetabnote';
import { KeyManager } from './keymanager';
import { KeySignature } from './keysignature';
import { KeySigNote } from './keysignote';
import { Modifier } from './modifier';
import { Modifier, ModifierPosition } from './modifier';
import { ModifierContext } from './modifiercontext';
import { MultiMeasureRest } from './multimeasurerest';
import { Music } from './music';
Expand All @@ -43,7 +43,7 @@ import { RenderContext } from './rendercontext';
import { Renderer } from './renderer';
import { RepeatNote } from './repeatnote';
import { Stave } from './stave';
import { Barline } from './stavebarline';
import { Barline, BarlineType } from './stavebarline';
import { StaveConnector } from './staveconnector';
import { StaveHairpin } from './stavehairpin';
import { StaveLine } from './staveline';
Expand Down Expand Up @@ -156,6 +156,11 @@ export class Flow {
static Voice = Voice;
static Volta = Volta;

// enums need to be exported too!
static BarlineType = BarlineType;
static ModifierPosition = ModifierPosition;
// ... more to come ...

// VERSION and BUILD are set by webpack string-replace-loader. See: Gruntfile.js.
static VERSION: string = '_VEX_VERSION_';
static BUILD: string = '_VEX_BUILD_';
Expand Down
4 changes: 4 additions & 0 deletions src/formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1025,4 +1025,8 @@ export class Formatter {
L('Formatting voices to width: ', justifyWidth);
return this.format(voices, justifyWidth, options);
}

getTickContext(tick: number): TickContext | undefined {
return this.tickContexts?.map[tick];
}
}
4 changes: 2 additions & 2 deletions src/stave.ts
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ export class Stave extends Element {
}

// Bar Line functions
setBegBarType(type: number): this {
setBegBarType(type: number | BarlineType): this {
// Only valid bar types at beginning of stave is none, single or begin repeat
const { SINGLE, REPEAT_BEGIN, NONE } = BarlineType;
if (type === SINGLE || type === REPEAT_BEGIN || type === NONE) {
Expand All @@ -442,7 +442,7 @@ export class Stave extends Element {
return this;
}

setEndBarType(type: number): this {
setEndBarType(type: number | BarlineType): this {
// Repeat end not valid at end of stave
if (type !== BarlineType.REPEAT_BEGIN) {
(this.modifiers[1] as Barline).setType(type);
Expand Down
7 changes: 5 additions & 2 deletions src/stavetie.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@ import { FontInfo } from './font';
import { Note } from './note';
import { RuntimeError } from './util';

// For backwards compatibility with 3.0.9, first_note and/or last_note can be undefined or null.
// We prefer undefined instead of null.
// However, some of our test cases used to pass in null, so maybe there is client code relying on it.
export interface TieNotes {
first_note: Note | null;
last_note: Note | null;
first_note?: Note | null;
last_note?: Note | null;
first_indices?: number[];
last_indices?: number[];
}
Expand Down
4 changes: 4 additions & 0 deletions tests/barline_tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ function enums(): void {
// VexFlow 4.0 renamed Barline.type => BarlineType.
// The old way still works, for backwards compatibility.
equal(Barline.type, BarlineType);

const a = BarlineType['DOUBLE'];
const b = BarlineType.DOUBLE;
equal(a, b);
}

function simple(options: TestOptions): void {
Expand Down
4 changes: 0 additions & 4 deletions tests/stavetie_tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ const noEndNote1 = createTest(['(cb4 e#4 a4)/2, (d4 e4 f4)', { stem: 'down' }],
stave.addEndClef('treble');
f.StaveTie({
from: notes[1],
to: null,
first_indices: [2],
last_indices: [2],
text: 'slow.',
Expand All @@ -88,7 +87,6 @@ const noEndNote1 = createTest(['(cb4 e#4 a4)/2, (d4 e4 f4)', { stem: 'down' }],
const noEndNote2 = createTest(['(cb4 e#4 a4)/2, (d4 e4 f4)', { stem: 'down' }], (f, notes) => {
f.StaveTie({
from: notes[1],
to: null,
first_indices: [2],
last_indices: [2],
text: 'slow.',
Expand All @@ -98,7 +96,6 @@ const noEndNote2 = createTest(['(cb4 e#4 a4)/2, (d4 e4 f4)', { stem: 'down' }],
const noStartNote1 = createTest(['(cb4 e#4 a4)/2, (d4 e4 f4)', { stem: 'down' }], (f, notes, stave) => {
stave.addClef('treble');
f.StaveTie({
from: null,
to: notes[0],
first_indices: [2],
last_indices: [2],
Expand All @@ -108,7 +105,6 @@ const noStartNote1 = createTest(['(cb4 e#4 a4)/2, (d4 e4 f4)', { stem: 'down' }]

const noStartNote2 = createTest(['(cb4 e#4 a4)/2, (d4 e4 f4)', { stem: 'down' }], (f, notes) => {
f.StaveTie({
from: null,
to: notes[0],
first_indices: [2],
last_indices: [2],
Expand Down

0 comments on commit 20c9b62

Please sign in to comment.