API Examples

Code examples for using the Notations library

Practical code examples demonstrating how to use the Notations library in different scenarios.

Basic Parsing

import * as N from "notations";

const source = `
\\cycle("|4|2|2|")
\\beatDuration(4)
Sw: S R G M P D N S.
Sh: sa ri ga ma pa dha ni sa
`;

const [notation, beatLayout, errors] = N.load(source);

if (errors.length > 0) {
  console.error("Parse errors:", errors);
} else {
  console.log("Parsed successfully!");
  console.log("Cycle:", notation.currentCycle);
  console.log("Beat duration:", notation.currentAPB);
}

Rendering Notation

import * as N from "notations";

// Parse the notation
const [notation, beatLayout, errors] = N.load(source);

if (errors.length === 0) {
  // Create a view
  const container = document.getElementById("notation-output");
  const view = N.Carnatic.createNotationView(container);

  // Render the notation
  view.setNotation(notation, beatLayout);
}

Dynamic Notation Editor

import * as N from "notations";

const textarea = document.getElementById("editor");
const output = document.getElementById("output");
const errors = document.getElementById("errors");

let view = null;

function renderNotation() {
  const source = textarea.value;
  const [notation, beatLayout, parseErrors] = N.load(source);

  if (parseErrors.length > 0) {
    // Display errors
    errors.innerHTML = parseErrors
      .map(e => `Line ${e.line}, Col ${e.column}: ${e.message}`)
      .join('
'); errors.style.display = 'block'; } else { // Clear errors errors.style.display = 'none'; // Create view if needed if (!view) { view = N.Carnatic.createNotationView(output); } // Render notation view.setNotation(notation, beatLayout); } } // Update on input textarea.addEventListener('input', renderNotation); // Initial render renderNotation();

Analyzing Notation Structure

import * as N from "notations";

const [notation, beatLayout, errors] = N.load(source);

if (errors.length === 0) {
  // Count notes
  let noteCount = 0;
  notation.blocks.forEach(block => {
    block.lines.forEach(line => {
      Object.values(line.roles).forEach(role => {
        role.atoms.forEach(atom => {
          if (atom.type === "Literal") {
            noteCount++;
          }
        });
      });
    });
  });

  console.log("Total notes:", noteCount);

  // List all roles
  const roleNames = notation.roles.map(r => r.name);
  console.log("Roles:", roleNames);

  // Get cycle information
  console.log("Cycle pattern:", notation.currentCycle);
  console.log("Atoms per beat:", notation.currentAPB);
}

Server-Side Rendering

// Node.js example
const N = require('notations');
const fs = require('fs');

// Read notation from file
const source = fs.readFileSync('composition.txt', 'utf8');

// Parse notation
const [notation, beatLayout, errors] = N.load(source);

if (errors.length > 0) {
  console.error('Parse errors:');
  errors.forEach(e => {
    console.error(`  Line ${e.line}, Col ${e.column}: ${e.message}`);
  });
  process.exit(1);
}

// Process notation data
const output = {
  title: notation.metadata.title || 'Untitled',
  cycle: notation.currentCycle,
  beatDuration: notation.currentAPB,
  roles: notation.roles.map(r => r.name),
  blockCount: notation.blocks.length
};

// Write to JSON
fs.writeFileSync('output.json', JSON.stringify(output, null, 2));

console.log('Notation processed successfully');

Batch Processing

import * as N from "notations";
import * as fs from "fs/promises";
import * as path from "path";

async function processNotationFiles(directory) {
  const files = await fs.readdir(directory);
  const results = [];

  for (const file of files) {
    if (file.endsWith('.txt')) {
      const fullPath = path.join(directory, file);
      const source = await fs.readFile(fullPath, 'utf8');

      const [notation, beatLayout, errors] = N.load(source);

      results.push({
        file: file,
        success: errors.length === 0,
        errors: errors.length,
        blocks: notation?.blocks.length || 0
      });
    }
  }

  return results;
}

// Usage
processNotationFiles('./notations').then(results => {
  console.log('Processing complete:');
  results.forEach(r => {
    console.log(`  ${r.file}: ${r.success ? 'OK' : 'ERRORS'}`);
  });
});

Custom Error Handling

import * as N from "notations";

function parseNotationSafely(source) {
  try {
    const [notation, beatLayout, errors] = N.load(source);

    if (errors.length > 0) {
      throw new Error(
        'Parse errors:\n' +
        errors.map(e =>
          `Line ${e.line}, Column ${e.column}: ${e.message}`
        ).join('\n')
      );
    }

    return { notation, beatLayout };
  } catch (error) {
    console.error('Failed to parse notation:', error.message);
    throw error;
  }
}

// Usage
try {
  const { notation, beatLayout } = parseNotationSafely(source);
  // Use notation and beatLayout
} catch (error) {
  // Handle error gracefully
  displayErrorToUser(error.message);
}

Working with Metadata

import * as N from "notations";

const source = `
---
title: "Mohana Varnam"
raga: "Bhairavi"
composer: "Papanasam Sivan"
---

\\cycle("|4|2|2|")
\\beatDuration(4)
Sw: S R G M P D N S.
`;

const parser = new N.Parser();
parser.parse(source);

console.log('Metadata:', parser.metadata);
// Output: { title: "Mohana Varnam", raga: "Bhairavi", ... }

const [notation, beatLayout, errors] = N.load(source);
console.log('Title:', notation.metadata.title);

Filtering and Transforming

import * as N from "notations";

const [notation, beatLayout, errors] = N.load(source);

if (errors.length === 0) {
  // Extract only swara role
  const swaraLines = notation.blocks.flatMap(block =>
    block.lines.map(line => line.roles['Sw'])
  ).filter(role => role !== undefined);

  console.log('Swara lines:', swaraLines.length);

  // Count spaces
  let spaceCount = 0;
  notation.blocks.forEach(block => {
    block.lines.forEach(line => {
      Object.values(line.roles).forEach(role => {
        role.atoms.forEach(atom => {
          if (atom.type === "Space") {
            spaceCount++;
          }
        });
      });
    });
  });

  console.log('Total spaces:', spaceCount);
}

See Also