npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@keepmhwn/mark-over

v0.1.0

Published

Transform text within markup tags (HTML) via callbacks while preserving structure

Readme

mark-over

Transform text content within HTML markup while preserving structure

License: MIT

A lightweight library that allows you to transform text content within HTML elements while maintaining the original HTML structure. Perfect for internationalization, text manipulation, or any scenario where you need to modify text content without breaking your markup.

Features

  • 🎯 Preserve Structure - Maintains HTML structure while transforming text
  • 🔄 Async Support - Works with both synchronous and asynchronous transformations
  • 🌐 Universal - Works in both Node.js and browser environments
  • 📦 Zero Dependencies (browser mode) - Lightweight for browser usage
  • 🎨 Tag Awareness - Access element information (tag name, id, classes) during transformation
  • ⚙️ Configurable - Skip specific tags that shouldn't be transformed

Installation

npm install @keepmhwn/mark-over
yarn add @keepmhwn/mark-over
pnpm add @keepmhwn/mark-over

Usage

Node.js Example

import { markOver } from "@keepmhwn/mark-over";
// or explicitly: import { markOver } from "@keepmhwn/mark-over/node";

const html = "<div><h1>Hello</h1><p>World</p></div>";

const result = await markOver(
  {
    html: html,
  },
  (taggedText) => {
    // Transform each text node
    return taggedText.text.toUpperCase();
  }
);

console.log(result);
// Output: <div><h1>HELLO</h1><p>WORLD</p></div>

Browser Example

import { markOver } from "@keepmhwn/mark-over";
// or explicitly: import { markOver } from "@keepmhwn/mark-over/browser";

const html = "<div><h1>Hello</h1><p>World</p></div>";

const result = await markOver(
  {
    html: html,
  },
  (taggedText) => {
    return taggedText.text.toUpperCase();
  }
);

console.log(result);
// Output: <div><h1>HELLO</h1><p>WORLD</p></div>

Note: The default import (@keepmhwn/mark-over) automatically selects the correct implementation based on your environment. Use /browser or /node for explicit control.

Translation Example

import { markOver } from "@keepmhwn/mark-over";

const translations = {
  Hello: "안녕하세요",
  World: "세계",
  Welcome: "환영합니다",
};

const html = `
  <div>
    <h1>Hello</h1>
    <p>Welcome to the World</p>
  </div>
`;

const result = await markOver(
  {
    html: html,
  },
  (taggedText) => {
    // Translate each word
    return taggedText.text
      .split(" ")
      .map((word) => translations[word] || word)
      .join(" ");
  }
);

Using Tag Information

import { markOver } from "@keepmhwn/mark-over";

const html = `
  <div>
    <h1 id="title" class="header">Product Name</h1>
    <p class="description">Description text</p>
    <span class="price">$99.99</span>
  </div>
`;

const result = await markOver(
  {
    html: html,
  },
  (taggedText) => {
    // Access element information
    const { text, tag } = taggedText;

    // Different transformation based on tag
    if (tag.name === "H1") {
      return text.toUpperCase();
    }

    // Different transformation based on class
    if (tag.classList?.includes("price")) {
      return `💰 ${text}`;
    }

    return text;
  }
);

Async Transformation (e.g., API calls)

import { markOver } from "@keepmhwn/mark-over";

async function translateText(text: string): Promise<string> {
  // Call translation API
  const response = await fetch("https://api.example.com/translate", {
    method: "POST",
    body: JSON.stringify({ text, target: "ko" }),
  });
  const data = await response.json();
  return data.translatedText;
}

const html = "<div><p>Hello World</p></div>";

const result = await markOver(
  {
    html: html,
  },
  async (taggedText) => {
    // Async transformation
    return await translateText(taggedText.text);
  }
);

Skip Specific Tags

import { markOver } from "@keepmhwn/mark-over";

const html = `
  <div>
    <p>Translate this</p>
    <code>const x = 42;</code>
    <pre>function example() {}</pre>
  </div>
`;

const result = await markOver(
  {
    html: html,
    skipTags: ["CODE", "PRE"], // Don't transform code blocks
  },
  (taggedText) => {
    return taggedText.text.toUpperCase();
  }
);

// CODE and PRE tags remain unchanged

API

Import Paths

  • @keepmhwn/mark-over - Auto-detects environment (recommended)
  • @keepmhwn/mark-over/node - Explicitly for Node.js
  • @keepmhwn/mark-over/browser - Explicitly for browsers

markOver(options, transform)

Transforms text content within HTML markup.

Parameters

  • options: BrowserMarkOverOptions | NodeMarkOverOptions

    • html: string - HTML string to transform
    • skipTags: string[] (optional) - Array of tag names to skip (default: ["STYLE", "SCRIPT", "CODE", "PRE", "SVG"])
  • transform: (taggedText: TaggedText) => string | Promise<string> - Transformation function

    • taggedText: Object containing:
      • text: string - The text content
      • tag: Object with element information:
        • name: string - Tag name (e.g., "DIV", "P", "SPAN")
        • id: string | null - Element ID
        • classList: string[] | null - Array of class names
      • key: number - Unique identifier

Returns

Promise<string> - Transformed HTML string

TypeScript

This library is written in TypeScript and includes type definitions.

import { markOver, type TaggedText } from "@keepmhwn/mark-over";
// or: import { markOver, type NodeMarkOverOptions, type TaggedText } from "@keepmhwn/mark-over/node";
// or: import { markOver, type BrowserMarkOverOptions, type TaggedText } from "@keepmhwn/mark-over/browser";

const result = await markOver(
  {
    html: "<p>Hello</p>",
  },
  (taggedText: TaggedText): string => {
    return taggedText.text.toUpperCase();
  }
);

Use Cases

  • 🌍 Internationalization (i18n) - Translate HTML content while preserving structure
  • 📝 Text Processing - Apply text transformations (uppercase, lowercase, etc.)
  • 🔍 Content Analysis - Extract and analyze text with context
  • 🎨 Dynamic Styling - Add markup based on text content
  • 🤖 AI Text Enhancement - Process text through AI APIs while maintaining HTML structure
  • 🔐 Content Sanitization - Transform or filter text content

Default Skip Tags

By default, the following tags are skipped to preserve technical content:

  • STYLE - CSS styles
  • SCRIPT - JavaScript code
  • CODE - Inline code
  • PRE - Preformatted text
  • SVG - SVG elements

You can override this by providing your own skipTags array.

License

MIT © minhwan(keepmhwn)

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Issues

If you find a bug or have a feature request, please open an issue.

Author

minhwan(keepmhwn)