forked from flow/vue3js-app-proposal-for-sdk-claude
Export metadata edits (title, composer, source, encrypter) via patchScore
This commit is contained in:
parent
720a0b6b25
commit
097d4488ef
@ -47,7 +47,7 @@ export const PaneCP = {
|
|||||||
try {
|
try {
|
||||||
const raw = await fetchScoreText(props.store.credentials);
|
const raw = await fetchScoreText(props.store.credentials);
|
||||||
props.store.rawScoreText = raw;
|
props.store.rawScoreText = raw;
|
||||||
const patched = patchScore(raw, props.store.scoreModel.instruments, props.store.scoreModel.bars);
|
const patched = patchScore(raw, props.store.scoreModel.instruments, props.store.scoreModel.bars, props.store.scoreModel.info);
|
||||||
await putScoreText(patched, props.store.credentials);
|
await putScoreText(patched, props.store.credentials);
|
||||||
props.store.synthesisStatus = { frozen: false, currently_rendered_notes: 0, notes_in_total: 0 };
|
props.store.synthesisStatus = { frozen: false, currently_rendered_notes: 0, notes_in_total: 0 };
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@ -141,6 +141,31 @@ export function exportInstrument(instr) {
|
|||||||
// Replace dirty instrument blocks and dirty bar _meta blocks.
|
// Replace dirty instrument blocks and dirty bar _meta blocks.
|
||||||
// Voice note content in bar documents is left verbatim.
|
// Voice note content in bar documents is left verbatim.
|
||||||
|
|
||||||
|
const META_KEYS = ['title', 'composer', 'source', 'encrypter'];
|
||||||
|
|
||||||
|
function patchMetadata(text, info) {
|
||||||
|
if (!info) return text;
|
||||||
|
const lines = text.split('\n');
|
||||||
|
const replaced = new Set();
|
||||||
|
|
||||||
|
const out = lines.map(line => {
|
||||||
|
for (const key of META_KEYS) {
|
||||||
|
if (line.startsWith(key + ':') && info[key] != null && info[key] !== '') {
|
||||||
|
replaced.add(key);
|
||||||
|
return `${key}: ${info[key]}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return line;
|
||||||
|
});
|
||||||
|
|
||||||
|
const prepend = META_KEYS
|
||||||
|
.filter(k => !replaced.has(k) && info[k] != null && info[k] !== '')
|
||||||
|
.map(k => `${k}: ${info[k]}`);
|
||||||
|
if (prepend.length) out.unshift(...prepend);
|
||||||
|
|
||||||
|
return out.join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
function patchInstrumentHeader(text, instruments) {
|
function patchInstrumentHeader(text, instruments) {
|
||||||
const lines = text.split('\n');
|
const lines = text.split('\n');
|
||||||
const result = [];
|
const result = [];
|
||||||
@ -217,11 +242,11 @@ function patchBarMeta(doc, bar) {
|
|||||||
return out.join('\n');
|
return out.join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function patchScore(rawScoreText, instruments, bars = []) {
|
export function patchScore(rawScoreText, instruments, bars = [], info = null) {
|
||||||
const SEP = '\n---\n';
|
const SEP = '\n---\n';
|
||||||
const [header, ...barDocs] = rawScoreText.split(SEP);
|
const [header, ...barDocs] = rawScoreText.split(SEP);
|
||||||
|
|
||||||
const patchedHeader = patchInstrumentHeader(header, instruments);
|
const patchedHeader = patchInstrumentHeader(patchMetadata(header, info), instruments);
|
||||||
|
|
||||||
if (!barDocs.length) return patchedHeader;
|
if (!barDocs.length) return patchedHeader;
|
||||||
|
|
||||||
|
|||||||
@ -403,6 +403,32 @@ ok('clean bar unchanged', barPatched.includes('beats_per_minute: 100'));
|
|||||||
ok('clean bar voice preserved', barPatched.includes('- D4 4'));
|
ok('clean bar voice preserved', barPatched.includes('- D4 4'));
|
||||||
ok('document separators preserved', (barPatched.match(/\n---\n/g) ?? []).length === 2);
|
ok('document separators preserved', (barPatched.match(/\n---\n/g) ?? []).length === 2);
|
||||||
|
|
||||||
|
// ── patchScore metadata ────────────────────────────────────────────────────
|
||||||
|
section('patchScore metadata');
|
||||||
|
const META_SCORE = `title: Old Title
|
||||||
|
composer: Old Composer
|
||||||
|
source: Some Book
|
||||||
|
|
||||||
|
instrument alpha:
|
||||||
|
character:
|
||||||
|
A: "1:0,10;1,0"
|
||||||
|
`;
|
||||||
|
const updatedInfo = { title: 'New Title', composer: 'New Composer', source: '', encrypter: 'Me' };
|
||||||
|
const metaPatched = patchScore(META_SCORE, [], [], updatedInfo);
|
||||||
|
ok('existing title replaced', metaPatched.includes('title: New Title'));
|
||||||
|
ok('existing composer replaced', metaPatched.includes('composer: New Composer'));
|
||||||
|
ok('empty value leaves existing line', metaPatched.includes('source: Some Book'));
|
||||||
|
ok('new key prepended', metaPatched.includes('encrypter: Me'));
|
||||||
|
ok('instrument block untouched', metaPatched.includes('instrument alpha:'));
|
||||||
|
|
||||||
|
const META_SCORE_NO_TITLE = `composer: Bach\n\ninstrument ki:\n character:\n`;
|
||||||
|
const noTitlePatched = patchScore(META_SCORE_NO_TITLE, [], [], { title: 'Fugue', composer: 'Bach' });
|
||||||
|
ok('missing title prepended', noTitlePatched.includes('title: Fugue'));
|
||||||
|
ok('existing composer not duplicated', (noTitlePatched.match(/^composer:/mg) ?? []).length === 1);
|
||||||
|
|
||||||
|
const nullInfoPatched = patchScore(META_SCORE, [], [], null);
|
||||||
|
ok('null info leaves metadata unchanged', nullInfoPatched.includes('title: Old Title'));
|
||||||
|
|
||||||
// ── Summary ────────────────────────────────────────────────────────────────
|
// ── Summary ────────────────────────────────────────────────────────────────
|
||||||
console.log(`\n══ ${pass} passed, ${fail} failed ══\n`);
|
console.log(`\n══ ${pass} passed, ${fail} failed ══\n`);
|
||||||
process.exit(fail > 0 ? 1 : 0);
|
process.exit(fail > 0 ? 1 : 0);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user