@viritura/score-engine 0.1.1-next.4 → 0.1.1-next.6

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/dist/index.js CHANGED
@@ -47,6 +47,12 @@ var DURATION_BEATS = {
47
47
  };
48
48
  var SHARP_ORDER = ["F", "C", "G", "D", "A", "E", "B"], FLAT_ORDER = ["B", "E", "A", "D", "G", "C", "F"];
49
49
 
50
+ // packages/core/src/model/text.ts
51
+ init_define_import_meta_env();
52
+ function plainTextContent(content) {
53
+ return content.map((chunk) => "text" in chunk ? chunk.text : "").join("");
54
+ }
55
+
50
56
  // packages/core/src/model/event.ts
51
57
  init_define_import_meta_env();
52
58
  function isRest(event) {
@@ -1864,9 +1870,9 @@ function interpolateBeatAnchors(bounds, beat, endX) {
1864
1870
 
1865
1871
  // packages/score-engine/src/buildInfo.ts
1866
1872
  init_define_import_meta_env();
1867
- var PACKAGE_VERSION = "0.1.1-next.4", BUNDLE_WORKER_FILE = "score-engine.worker.js";
1873
+ var PACKAGE_VERSION = "0.1.1-next.6", BUNDLE_WORKER_FILE = "score-engine.worker.js";
1868
1874
  function buildCommit() {
1869
- return "605f04579eb0a20c5485d31e073beff7216c9c0d";
1875
+ return "3839ceae5b4e815e59efdacf32a0ea0520c0bbb8";
1870
1876
  }
1871
1877
  function bundledAssetBase() {
1872
1878
  let moduleUrl = import.meta.url;
@@ -2255,6 +2261,48 @@ init_define_import_meta_env();
2255
2261
 
2256
2262
  // packages/format/src/mnx/parseGlobal.ts
2257
2263
  init_define_import_meta_env();
2264
+
2265
+ // packages/format/src/mnx/textContent.ts
2266
+ init_define_import_meta_env();
2267
+ var FONTS = /* @__PURE__ */ new Set(["serif", "sans-serif", "monospace"]), FONT_STYLES = /* @__PURE__ */ new Set(["normal", "italic", "oblique"]), DECORATIONS = /* @__PURE__ */ new Set(["underline", "overline", "strikethrough"]), ENCLOSURES = /* @__PURE__ */ new Set(["box", "circle"]), MAX_SIZE = 12, MIN_WEIGHT = 1, MAX_WEIGHT = 1e3;
2268
+ function parseStyle(raw) {
2269
+ if (!raw || typeof raw != "object" || Array.isArray(raw)) return;
2270
+ let value = raw, style = {};
2271
+ typeof value.font == "string" && FONTS.has(value.font) && (style.font = value.font);
2272
+ let size = value.size;
2273
+ typeof size == "number" && Number.isFinite(size) && size > 0 && size <= MAX_SIZE && (style.size = size);
2274
+ let weight = value.weight;
2275
+ if ((weight === "normal" || weight === "bold" || typeof weight == "number" && Number.isFinite(weight) && weight >= MIN_WEIGHT && weight <= MAX_WEIGHT) && (style.weight = weight), typeof value.fontStyle == "string" && FONT_STYLES.has(value.fontStyle) && (style.fontStyle = value.fontStyle), Array.isArray(value.decorations)) {
2276
+ let decorations = value.decorations.filter(
2277
+ (item) => typeof item == "string" && DECORATIONS.has(item)
2278
+ ), unique = [...new Set(decorations)];
2279
+ unique.length > 0 && (style.decorations = unique);
2280
+ }
2281
+ return typeof value.enclosure == "string" && ENCLOSURES.has(value.enclosure) && (style.enclosure = value.enclosure), typeof value.color == "string" && (style.color = value.color), Object.keys(style).length > 0 ? style : void 0;
2282
+ }
2283
+ function parseChunk(raw) {
2284
+ if (!raw || typeof raw != "object" || Array.isArray(raw)) return;
2285
+ let value = raw, style = parseStyle(value.style);
2286
+ if (typeof value.text == "string") {
2287
+ let run = { text: value.text };
2288
+ return style && (run.style = style), run;
2289
+ }
2290
+ let glyphs = value.glyphs;
2291
+ if (Array.isArray(glyphs) && glyphs.every((name) => typeof name == "string")) {
2292
+ let run = { glyphs };
2293
+ style && (run.style = style);
2294
+ let smuflStyle = parseStyle(value.smuflStyle);
2295
+ return smuflStyle && (run.smuflStyle = smuflStyle), run;
2296
+ }
2297
+ }
2298
+ function parseTextContent(raw) {
2299
+ if (typeof raw == "string") return raw.length > 0 ? [{ text: raw }] : void 0;
2300
+ if (!Array.isArray(raw)) return;
2301
+ let chunks = raw.map(parseChunk).filter((chunk) => chunk !== void 0);
2302
+ return chunks.length > 0 ? chunks : void 0;
2303
+ }
2304
+
2305
+ // packages/format/src/mnx/parseGlobal.ts
2258
2306
  function parseGlobalSounds(raw) {
2259
2307
  let out = {};
2260
2308
  for (let key of Object.keys(raw)) {
@@ -2285,9 +2333,9 @@ function parseGlobalMeasure(raw) {
2285
2333
  if (viritura) {
2286
2334
  if (viritura.senzaMisura && measure.time && (measure.time.display = "senzaMisura"), viritura.rehearsalMark) {
2287
2335
  let rm = viritura.rehearsalMark;
2288
- measure.rehearsalMark = { text: rm.text }, rm.style && (measure.rehearsalMark.style = rm.style), applyManualPlacement(measure.rehearsalMark, rm);
2336
+ measure.rehearsalMark = { text: parseTextContent(rm.text) ?? [] }, rm.style && (measure.rehearsalMark.style = rm.style), applyManualPlacement(measure.rehearsalMark, rm);
2289
2337
  }
2290
- viritura.coda && (measure.coda = parseCoda(viritura.coda)), viritura.jump && (measure.jump = parseJump(viritura.jump)), viritura.gradualTempo && (measure.gradualTempo = parseGradualTempo(viritura.gradualTempo)), viritura.chordSymbols && (measure.chordSymbols = viritura.chordSymbols.map(parseChordSymbol));
2338
+ viritura.coda && (measure.coda = parseCoda(viritura.coda)), viritura.jump && (measure.jump = parseJump(viritura.jump)), applyMarkerTextExtension(measure, viritura.markerText), viritura.gradualTempo && (measure.gradualTempo = parseGradualTempo(viritura.gradualTempo)), viritura.chordSymbols && (measure.chordSymbols = viritura.chordSymbols.map(parseChordSymbol));
2291
2339
  }
2292
2340
  return measure;
2293
2341
  }
@@ -2325,7 +2373,11 @@ function parseTempo(raw) {
2325
2373
  };
2326
2374
  raw.location && (tempo.location = parseRhythmicPosition(raw.location));
2327
2375
  let viritura = raw._x?.viritura;
2328
- return viritura && (typeof viritura.text == "string" && (tempo.text = viritura.text), typeof viritura.showMetronomeMark == "boolean" && (tempo.showMetronomeMark = viritura.showMetronomeMark), typeof viritura.showText == "boolean" && (tempo.showText = viritura.showText), applyManualPlacement(tempo, viritura)), tempo;
2376
+ if (viritura) {
2377
+ let text = parseTextContent(viritura.text);
2378
+ text !== void 0 && (tempo.text = text), typeof viritura.showMetronomeMark == "boolean" && (tempo.showMetronomeMark = viritura.showMetronomeMark), typeof viritura.showText == "boolean" && (tempo.showText = viritura.showText), applyManualPlacement(tempo, viritura);
2379
+ }
2380
+ return tempo;
2329
2381
  }
2330
2382
  function parseTempoNoteValue(raw) {
2331
2383
  let tnv = {
@@ -2410,7 +2462,7 @@ function parseChordSymbol(raw) {
2410
2462
  }
2411
2463
  function parseTextExpression(raw) {
2412
2464
  let expr = {
2413
- text: raw.text,
2465
+ text: parseTextContent(raw.text) ?? [],
2414
2466
  position: parseRhythmicPosition(raw.position)
2415
2467
  };
2416
2468
  raw.placement && (expr.placement = raw.placement), raw.staff !== void 0 && (expr.staff = raw.staff), raw.voice && (expr.voice = raw.voice);
@@ -2439,6 +2491,22 @@ function parseJump(raw) {
2439
2491
  location: parseRhythmicPosition(raw.location)
2440
2492
  };
2441
2493
  }
2494
+ function parseMarkerText(raw, owner) {
2495
+ let content = parseTextContent(raw.content);
2496
+ if (!content) throw new Error(`markerText.${owner} must contain at least one text or glyph run.`);
2497
+ return { content, placement: raw.placement };
2498
+ }
2499
+ function applyMarkerTextExtension(measure, raw) {
2500
+ if (!raw) return;
2501
+ let owners = { segno: measure.segno, coda: measure.coda, fine: measure.fine, jump: measure.jump };
2502
+ for (let key of ["segno", "coda", "fine", "jump"]) {
2503
+ let text = raw[key];
2504
+ if (!text) continue;
2505
+ let owner = owners[key];
2506
+ if (!owner) throw new Error(`markerText.${key} requires a ${key} on the same measure.`);
2507
+ owner.text = parseMarkerText(text, key);
2508
+ }
2509
+ }
2442
2510
  function parseCoda(raw) {
2443
2511
  let coda = {
2444
2512
  location: parseRhythmicPosition(raw.location)
@@ -3453,7 +3521,7 @@ function detectToCodaMeasureIndex(score) {
3453
3521
  for (let part of score.parts)
3454
3522
  for (let i = 0; i < part.measures.length; i++) {
3455
3523
  let expressions = part.measures[i]?.expressions;
3456
- if (!(!expressions || expressions.length === 0) && expressions.some((expr) => /\bto\s*coda\b/i.test(expr.text)))
3524
+ if (!(!expressions || expressions.length === 0) && expressions.some((expr) => /\bto\s*coda\b/i.test(plainTextContent(expr.text))))
3457
3525
  return i;
3458
3526
  }
3459
3527
  return -1;
@@ -4180,7 +4248,7 @@ function emitCc(ctx, time, cc, value) {
4180
4248
  function applyMeasureTechniques(expressions, ctx, state, caps, ratioForStaff = () => 1) {
4181
4249
  if (!expressions || expressions.length === 0) return state;
4182
4250
  let marks = expressions.map((e) => ({
4183
- action: classifyTechniqueText(e.text),
4251
+ action: classifyTechniqueText(plainTextContent(e.text)),
4184
4252
  beat: fractionToBeats(e.position.fraction) * ratioForStaff(e.staff)
4185
4253
  })).filter((m) => m.action !== null).sort((a, b) => a.beat - b.beat), { program, muted } = state;
4186
4254
  for (let mark of marks) {
@@ -4553,7 +4621,7 @@ function collectMeasureDynamicGroups(pm, originalMeasureIndex, measureStartBeat,
4553
4621
  }
4554
4622
  function collectMeasureGradualTexts(pm, originalMeasureIndex, measureStartBeat, model, expandedIdx, gradualTexts, staffMeterTable) {
4555
4623
  for (let index = 0; index < (pm.expressions?.length ?? 0); index++) {
4556
- let expression = pm.expressions[index], dir = gradualTextDirection(expression.text);
4624
+ let expression = pm.expressions[index], dir = gradualTextDirection(plainTextContent(expression.text));
4557
4625
  dir && gradualTexts.push({
4558
4626
  id: `text-gradual-${expandedIdx}-${index}`,
4559
4627
  startTime: model.timeAtBeat(