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

@diskette/content

Package Overview
Dependencies
Maintainers
1
Versions
24
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install
Package was removed
Sorry, it seems this package was removed from the registry

@diskette/content

A content management library for Markdown/MDX files with automatic route generation, hierarchical navigation, and React component rendering.

latest
Source
npmnpm
Version
0.10.1
Version published
Maintainers
1
Created
Source

@diskette/content

A content management library for Markdown/MDX files with automatic route generation, hierarchical navigation, and React component rendering.

Installation

pnpm add @diskette/content

Quick Start

import { Collection } from '@diskette/content'

// Create a collection from a directory
const collection = await Collection.from('./docs')

// Get all available routes
console.log(collection.routes)
// ['/guides/introduction', '/api/reference', '/']

// Resolve content by route
const content = collection.resolve('/guides/introduction')
console.log(content.title) // "Getting Started"

// Navigate between siblings
const next = collection.getNext('/guides/introduction')
const prev = collection.getPrevious('/guides/advanced')

// Render MDX component
const Component = await content.component()

Collection Class

The Collection class is the primary interface for working with content. It automatically discovers Markdown and MDX files, generates clean routes, and provides navigation and rendering capabilities.

Creating a Collection

Collection.from(path, options?)

Creates a collection from a directory path.

import { Collection } from '@diskette/content'

const collection = await Collection.from('./content', {
	// Include patterns (default: ['**/*.mdx', '**/*.md'])
	include: ['**/*.mdx', '**/*.md'],

	// Exclude patterns
	exclude: ['**/node_modules/**'],

	// Custom ordering function
	order: (node) => node.name,

	// MDX evaluation options
	mdx: {
		// MDX compiler options
	},
})

Parameters:

  • path - Directory path to scan for content files
  • options - Configuration options (optional)

Options:

  • include - Glob patterns for files to include (default: ['**/*.mdx', '**/*.md'])
  • exclude - Glob patterns for files to exclude
  • order - Custom function to determine sort order within folders
  • mdx - MDX evaluation options passed to the compiler

Route Generation

The Collection automatically generates clean routes from file paths:

  • Removes file extensions (.md, .mdx)
  • Strips numeric prefixes (01-intro.md/intro)
  • Converts index files to directory routes (/api/index.md/api)
  • Maintains folder hierarchy
// File structure:
// content/
//   index.md           → /
//   01-guides/
//     01-intro.md      → /guides/intro
//     02-advanced.md   → /guides/advanced
//   api/
//     index.md         → /api
//     endpoints.md     → /api/endpoints

const collection = await Collection.from('./content')
console.log(collection.routes)
// ['/', '/api', '/api/endpoints', '/guides/intro', '/guides/advanced']

Content Resolution

resolve(pathOrSlugs)

Resolves content by route path or slug array.

// By absolute path
const content1 = collection.resolve('/guides/introduction')

// By relative path
const content2 = collection.resolve('guides/introduction')

// By slug array
const content3 = collection.resolve(['guides', 'introduction'])

// All return the same Content object or undefined if not found

Returns: Content object or undefined

Content Object

The resolved content object provides rich metadata and rendering capabilities:

interface Content {
	title?: string // From frontmatter
	description?: string // From frontmatter
	route: string // Generated route path
	toc: ContentToc[] // Table of contents
	content: ContentAst // Parsed AST
	matter: Matter // Parsed frontmatter data
	structure: ContentStructure // Analyzed structure
	component: (opts?) => Promise<JSX.Element> // Render function
}

Example:

const content = collection.resolve('/guides/introduction')

console.log(content.title)       // "Introduction"
console.log(content.description) // "Getting started guide"
console.log(content.route)       // "/guides/introduction"

// Table of contents from headings
content.toc.forEach(item => {
  console.log(`${item.title} (${item.url})`)
})

// Render as React component
const Component = await content.component({
  components: {
    h1: ({ children }) => <h1 className="custom">{children}</h1>
  }
})

Navigation

getNext(route) / getPrevious(route)

Navigate between sibling content within the same folder.

const current = collection.resolve('/guides/introduction')
const next = collection.getNext('/guides/introduction')
const prev = collection.getPrevious('/guides/introduction')

console.log(next?.route) // '/guides/advanced'
console.log(prev?.route) // undefined (first in folder)

Navigation Rules:

  • Only navigates within the same folder
  • Respects custom ordering
  • Returns undefined at folder boundaries
  • Skips directory nodes without index files

Tree Structure

toTree()

Generates a hierarchical tree structure of all content.

const tree = collection.toTree()

// Returns ContentTreeNode[] with proper nesting
tree.forEach((node) => {
	console.log(node.route, node.depth)
	if ('children' in node) {
		// TreeFolder - directory with index file
		node.children.forEach((child) => {
			console.log('  ', child.route, child.depth)
		})
	}
	// TreeFile - individual content file
})

Properties

routes

Get all available content routes in sorted order.

const allRoutes = collection.routes
console.log(allRoutes)
// ['/api', '/api/endpoints', '/guides/intro', '/guides/advanced']

Advanced Usage

Custom Ordering

Control how content is ordered within folders:

const collection = await Collection.from('./content', {
	// Order by frontmatter priority, then by filename
	order: (node) => {
		const matter = parseFrontmatter(node.content)
		return matter.priority ? `${matter.priority}-${node.name}` : node.name
	},
})

MDX Components

Customize MDX rendering with custom components:

const content = collection.resolve('/guides/intro')
const Component = await content.component({
  components: {
    // Custom heading component
    h1: ({ children, id }) => (
      <h1 id={id} className="text-4xl font-bold">
        <a href={`#${id}`} className="anchor">§</a>
        {children}
      </h1>
    ),

    // Custom code blocks
    pre: ({ children }) => (
      <pre className="bg-gray-100 p-4 rounded">
        {children}
      </pre>
    ),

    // Custom components
    Callout: ({ type, children }) => (
      <div className={`callout callout-${type}`}>
        {children}
      </div>
    )
  }
})

Content Structure Analysis

Access detailed content analysis:

const content = collection.resolve('/api/reference')

// Frontmatter data
console.log(content.matter.title)
console.log(content.matter.tags)

// Headings with IDs
content.structure.headings.forEach((heading) => {
	console.log(`${heading.level}: ${heading.text} (#${heading.id})`)
})

// Other structural elements
console.log(content.structure.images) // Image nodes
console.log(content.structure.links) // Link nodes
console.log(content.structure.codeBlocks) // Code block nodes

TypeScript Support

Full TypeScript support with comprehensive type definitions:

import type {
	Collection,
	Content,
	ContentOptions,
	ContentToc,
	ContentTreeNode,
	TreeFile,
	TreeFolder,
} from '@diskette/content'

// Type-safe content resolution
const content: Content | undefined = collection.resolve('/guides/intro')

// Type-safe tree traversal
const tree: ContentTreeNode[] = collection.toTree()
tree.forEach((node: TreeFile | TreeFolder) => {
	if ('children' in node) {
		// TreeFolder
		console.log(`Folder: ${node.route}`)
		node.children.forEach((child) => {
			console.log(`  Child: ${child.route}`)
		})
	} else {
		// TreeFile
		console.log(`File: ${node.route}`)
	}
})

Examples

Building a Documentation Site

import { Collection } from '@diskette/content'

const docs = await Collection.from('./docs', {
	order: (node) => {
		// Custom ordering by frontmatter order field
		const content = node.type === 'file' ? node.content : ''
		const match = content.match(/^---[\s\S]*?order:\s*(\d+)/m)
		const order = match ? match[1].padStart(3, '0') : '999'
		return `${order}-${node.name}`
	},
})

// Get all documentation routes
const routes = docs.routes

// Build navigation with prev/next
routes.forEach((route) => {
	const content = docs.resolve(route)
	const prev = docs.getPrevious(route)
	const next = docs.getNext(route)

	console.log({
		route,
		title: content.title,
		prev: prev?.title,
		next: next?.title,
	})
})

Building a Blog

import { Collection } from '@diskette/content'

const blog = await Collection.from('./posts', {
	// Order by date (newest first)
	order: (node) => {
		const content = node.type === 'file' ? node.content : ''
		const match = content.match(/^---[\s\S]*?date:\s*['"]([^'"]+)['"]/m)
		const date = match ? match[1] : '1970-01-01'
		return new Date(date).toISOString().split('T')[0]
	},
})

// Get recent posts
const recentPosts = blog.routes
	.slice(0, 10)
	.map((route) => blog.resolve(route))
	.filter(Boolean)

recentPosts.forEach((post) => {
	console.log(`${post.title} - ${post.structure.matter.date}`)
})

License

MIT

FAQs

Package last updated on 11 Aug 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