import { CollationRule, XMLCollator } from './XMLCollator' const charCodesFor = (str: string): number[] => [...str].map((char: string) => char.charCodeAt(0)) const neumeRule: CollationRule = { 'syllable': [ (e: Element): number[] => { // a is defined by the text of the syllable // and by the amount of neumes it contains. const syl = e.querySelector('syl') return [...charCodesFor(syl?.textContent || '')] }, { 'neume': [ (e: Element): number[] => { // a is defined by its type (punctum, clivis ...), which can // be deduced from its internal melodic structure. const intms = Array.from(e.querySelectorAll('nc[intm]')).map(e => e.getAttribute('intm') === 'd' ? -1 : 1) if (intms.length !== 0) { return intms } // in case of dealing with a neume without any indication of direction // (virga or punctum), consider its pitch instead as defining const charCodes = charCodesFor(e.querySelector('nc[pname]')?.getAttribute('pname') || '') return charCodes }, { 'nc': (e: Element): number[] => { // s are compared based on their pitch names (@pname) // @accid.ges and possible children () are not // considered defining. const charCode = charCodesFor(e.getAttribute('pname') || '')[0] return [ charCode ] } } ] } ] } export class NeumeCollator extends XMLCollator { constructor() { super(neumeRule, () => {}) this.accumulateTag('manifestation') } }