New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

@echoes-io/utils

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@echoes-io/utils

Utilities and types for Echoes - Multi-POV storytelling platform. Provides shared timeline configuration, content parsing, word counting, and validation schemas.

latest
Source
npmnpm
Version
1.4.0
Version published
Maintainers
1
Created
Source

@echoes-io/utils

Utilities and types for Echoes - a multi-POV digital storytelling platform.

Overview

This package provides shared utilities used across the Echoes ecosystem:

  • Web application (Next.js)
  • CLI tools
  • MCP server
  • LaTeX/PDF builder

Installation

npm install @echoes-io/utils

Features

Markdown Parser

Parse markdown files with YAML frontmatter to extract chapter metadata and content.

import { parseMarkdown, stripMarkdown } from '@echoes-io/utils';

const markdown = `---
pov: "alice"
title: "First Meeting"
date: "2024-01-01"
timeline: "main"
arc: "introduction"
episode: 1
part: 1
chapter: 1
summary: "Alice meets Bob for the first time"
location: "coffee shop"
outfit: "red dress"
kink: "slow burn"
---

# Chapter 1

Alice walked into the coffee shop...`;

const { metadata, content } = parseMarkdown(markdown);
console.log(metadata.pov); // "alice"
console.log(content); // "# Chapter 1\n\nAlice walked..."

// Remove markdown syntax
const plainText = stripMarkdown(content);
console.log(plainText); // "Chapter 1\n\nAlice walked..."

Functions:

  • parseMarkdown() - Extract frontmatter and content from markdown
  • stripMarkdown() - Remove markdown syntax from text

Metadata Fields:

  • pov - Point of view character
  • title - Chapter title
  • date - Chapter date
  • timeline - Timeline identifier
  • arc - Story arc
  • episode, part, chapter - Numeric identifiers
  • summary - Brief description
  • location - Setting location
  • outfit - Character outfit (optional)
  • kink - Content tags (optional)

Text Statistics

Calculate word count and reading statistics from markdown content.

import { getTextStats } from '@echoes-io/utils';

const markdown = `
# Chapter Title

This is **bold** and *italic* text with [a link](https://example.com).
`;

const stats = getTextStats(markdown);
console.log(stats);
// {
//   words: 9,
//   characters: 52,
//   charactersNoSpaces: 43,
//   paragraphs: 1,
//   sentences: 1,
//   readingTimeMinutes: 1
// }

Features:

  • Automatically removes markdown syntax using stripMarkdown()
  • Removes HTML tags and comments
  • Removes frontmatter YAML
  • Counts words, characters (with/without spaces), paragraphs, sentences
  • Calculates reading time (based on 200 words/minute)

Path Utilities

Generate chapter files following Echoes naming conventions.

import { generateChapterFile } from '@echoes-io/utils';

const metadata = {
  pov: 'Alice',
  title: 'First Meeting',
  date: '2024-01-01',
  timeline: 'main',
  arc: 'Introduction Arc',
  episode: 1,
  part: 1,
  chapter: 5,
  summary: 'Alice meets Bob for the first time',
  location: 'Coffee Shop',
  outfit: 'Red dress',
  kink: 'Slow burn'
};

const file = generateChapterFile(metadata, 'Alice walked into the coffee shop...');

console.log(file.path);
// → content/introduction-arc/ep01-first-meeting/ep01-ch005-alice-first-meeting.md

console.log(file.content);
// → ---
//   pov: "Alice"
//   title: "First Meeting"
//   episode: 1
//   chapter: 5
//   ...
//   ---
//   
//   Alice walked into the coffee shop...

File Structure Convention:

content/
├── <arc-name>/
│   └── <ep01-episode-title>/
│       └── <ep01-ch001-pov-title>.md

Features:

  • Automatic path generation from metadata
  • Complete file with frontmatter and content
  • Handles special characters in titles (slugification)
  • Proper padding for episode (01) and chapter (001) numbers

Content Publishing Workflow

This repository provides a reusable GitHub Actions workflow for processing and publishing timeline content.

Usage in Timeline Repositories

  • Create workflow file in your timeline repo at .github/workflows/publish.yml:
name: Publish Timeline Content

on:
  push:
    branches: [main]
    paths: ['content/**/*.md']
  workflow_dispatch:

jobs:
  publish:
    uses: echoes-io/utils/.github/workflows/publish-content.yml@main
    with:
      timeline-name: 'main'  # Change this for each timeline
      content-path: 'content/'
      web-app-url: 'https://your-web-app.com'
    secrets:
      WEB_APP_TOKEN: ${{ secrets.WEB_APP_TOKEN }}
  • Add secret in your timeline repo:

    • Go to Settings → Secrets and variables → Actions
    • Add WEB_APP_TOKEN with your web app authentication token
  • Organize content in your timeline repo:

timeline-repo/
├── content/
│   ├── arc1/
│   │   ├── chapter1.md
│   │   └── chapter2.md
│   └── arc2/
│       └── chapter3.md
└── .github/workflows/publish.yml

What the Workflow Does

  • Processes all .md files in the specified directory
  • Extracts frontmatter metadata using parseMarkdown()
  • Calculates text statistics using getTextStats()
  • Uploads processed content to your web app via API
  • Triggers automatically on content changes or manually

API Payload Format

The workflow sends processed content as JSON:

[
  {
    "file": "content/arc1/chapter1.md",
    "metadata": {
      "pov": "alice",
      "title": "First Meeting",
      "timeline": "main",
      "arc": "introduction",
      "episode": 1,
      "part": 1,
      "chapter": 1
    },
    "content": "# Chapter 1\n\nContent here...",
    "stats": {
      "words": 150,
      "readingTimeMinutes": 1
    },
    "lastModified": "2024-01-01T12:00:00.000Z"
  }
]

Project Structure

utils/
├── lib/              # Source code
│   ├── index.ts      # Public API exports
│   ├── types.ts      # TypeScript interfaces
│   ├── markdown-parser.ts  # Markdown parsing & stripping
│   ├── text-stats.ts # Text statistics calculation
│   └── path-utils.ts # Chapter file generation
├── test/             # Tests
│   ├── index.test.ts
│   ├── markdown-parser.test.ts
│   ├── text-stats.test.ts
│   └── path-utils.test.ts
└── package.json

Development

Scripts

# Run tests
npm test

# Run tests with coverage
npm run test:coverage

# Lint code
npm run lint

# Fix linting issues
npm run lint:format

# Release (automated via GitHub Actions)
npm run release

Commit Convention

This project uses Conventional Commits for automated versioning:

  • feat: - New features (minor version bump)
  • fix: - Bug fixes (patch version bump)
  • feat!: or BREAKING CHANGE: - Breaking changes (major version bump)
  • docs:, style:, refactor:, test:, chore: - No version bump

Examples:

git commit -m "feat: add stripMarkdown function"
git commit -m "fix: handle empty frontmatter correctly"
git commit -m "feat!: change parseMarkdown return type"

Tech Stack

  • Language: TypeScript (strict mode)
  • Testing: Vitest
  • Linting: Biome
  • Git Hooks: Husky + lint-staged

Adding New Utilities

  • Create file in lib/
  • Create test in test/
  • Export from index.ts
  • Run tests: npm test
  • Lint: npm run lint:format

Dependencies

Runtime

  • gray-matter - Parse YAML frontmatter from markdown
  • remove-markdown - Strip markdown syntax for text analysis

Development

  • typescript - Type checking and compilation
  • vitest - Testing framework
  • @biomejs/biome - Linting and formatting
  • husky - Git hooks
  • lint-staged - Pre-commit linting

License

MIT

Keywords

echoes

FAQs

Package last updated on 12 Dec 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts