or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

api

features

charts

charts.mdconditional-formatting.mdvisualizations.md
authorization.mdchangesets.mdcharts-as-code.mdcompiler.mddashboards.mddbt.mdee-features.mdformatting.mdparameters.mdpivot.mdprojects-spaces.mdsql-runner.mdtemplating.mdwarehouse.md
index.md
tile.json

slugs.mddocs/api/utilities/specialized/

Slug Utilities

Functions for generating and manipulating URL-safe slugs, Ltree paths, and content-as-code paths.

Core Functions

/**
 * Generate a URL-safe slug from a name
 * Converts to lowercase, replaces special characters with hyphens
 * Returns random 5-character string if result is empty
 * @param name - Name to convert to slug
 * @returns URL-safe slug string
 */
function generateSlug(name: string): string;

/**
 * Convert slug to Ltree path format
 * Handles backwards compatibility with hierarchy in slugs
 * @param slug - Slug string
 * @returns Ltree path with underscores instead of hyphens
 */
function getLtreePathFromSlug(slug: string): string;

/**
 * Convert content-as-code path to Ltree path format
 * @param path - Content-as-code path with hyphens and slashes
 * @returns Ltree path with underscores and dots
 */
function getLtreePathFromContentAsCodePath(path: string): string;

/**
 * Convert Ltree path to content-as-code path format
 * @param path - Ltree path with underscores and dots
 * @returns Content-as-code path with hyphens and slashes
 */
function getContentAsCodePathFromLtreePath(path: string): string;

/**
 * Filter array of paths to only include deepest (leaf) paths
 * Removes paths that are prefixes of other paths
 * @param paths - Array of dot-separated paths
 * @returns Array containing only the deepest paths
 */
function getDeepestPaths(paths: string[]): string[];

/**
 * Check if one path is a sub-path of another
 * @param path - Parent path
 * @param subPath - Potential sub-path
 * @returns true if subPath is a direct child of path
 */
function isSubPath(parentPath: string, childPath: string): boolean;

Examples

Basic Slug Generation

import {
  generateSlug,
  getLtreePathFromSlug,
  getLtreePathFromContentAsCodePath,
  getContentAsCodePathFromLtreePath,
  getDeepestPaths,
  isSubPath,
} from '@lightdash/common';

// Generate URL-safe slug from name
const slug = generateSlug('My Dashboard Name!');
// Returns: "my-dashboard-name"

// More examples
const slug2 = generateSlug('Customer #123!!!'); // 'customer-123'
const slug3 = generateSlug('   '); // Returns random string like 'a7k2x'

Path Conversion

import {
  getLtreePathFromSlug,
  getLtreePathFromContentAsCodePath,
  getContentAsCodePathFromLtreePath,
} from '@lightdash/common';

// Convert slug to ltree path (PostgreSQL ltree type)
const ltreePath = getLtreePathFromSlug('parent/child/item');
// Returns: "parent.child.item"

// Convert slug with hyphens
const ltreePath2 = getLtreePathFromSlug('my-dashboard');
// Returns: 'my_dashboard'

// Convert content-as-code path to ltree
const ltree = getLtreePathFromContentAsCodePath('dashboards/sales/overview.yml');
// Returns: "dashboards.sales.overview"

// Convert paths between formats
const ltreePath3 = getLtreePathFromContentAsCodePath('spaces/marketing/dashboards');
// Returns: 'spaces.marketing.dashboards'

// Convert ltree path back to content path
const contentPath = getContentAsCodePathFromLtreePath('dashboards.sales.overview');
// Returns: "dashboards/sales/overview"

const codePath = getContentAsCodePathFromLtreePath('spaces.marketing.dashboards');
// Returns: 'spaces/marketing/dashboards'

Path Hierarchy Operations

import { getDeepestPaths, isSubPath } from '@lightdash/common';

// Get only the deepest (leaf) paths from a list
const paths = ['a.b', 'a.b.c', 'a.b.c.d', 'x.y'];
const deepest = getDeepestPaths(paths);
// Returns: ['a.b.c.d', 'x.y']

// Get deepest paths (filter out parent paths)
const paths2 = ['spaces', 'spaces.marketing', 'spaces.marketing.dashboards', 'spaces.sales'];
const deepest2 = getDeepestPaths(paths2);
// Returns: ['spaces.marketing.dashboards', 'spaces.sales']

// Check if one path is a subpath of another
if (isSubPath('a.b', 'a.b.c.d')) {
  console.log('a.b.c.d is under a.b');
}

// Check sub-path relationships
const isChild = isSubPath('spaces.marketing', 'spaces.marketing.dashboards'); // true
const isNotChild = isSubPath('spaces.marketing', 'spaces.sales'); // false

Use Cases

  • URL Generation: Create SEO-friendly URLs from dashboard, chart, and space names
  • Database Paths: Store hierarchical structures using PostgreSQL ltree format
  • Content Organization: Manage content-as-code paths for Git-backed content
  • Path Filtering: Find leaf nodes in hierarchical structures
  • Hierarchy Validation: Check parent-child relationships in content trees

Integration Examples

Dashboard Slugs

import { generateSlug } from '@lightdash/common';

// Create dashboard with URL-safe slug
const dashboard = {
  name: 'Q4 2023 Sales Report',
  slug: generateSlug('Q4 2023 Sales Report'), // 'q4-2023-sales-report'
  url: `/dashboards/q4-2023-sales-report`
};

Space Hierarchy

import { getDeepestPaths, isSubPath } from '@lightdash/common';

// Find leaf spaces in a hierarchy
const spacePaths = [
  'company',
  'company.marketing',
  'company.marketing.campaigns',
  'company.sales',
  'company.sales.reports'
];

const leafSpaces = getDeepestPaths(spacePaths);
// Returns: ['company.marketing.campaigns', 'company.sales.reports']

// Check if content belongs to a space
if (isSubPath('company.marketing', 'company.marketing.campaigns')) {
  console.log('Campaigns space is under marketing');
}

Content-as-Code Paths

import {
  getLtreePathFromContentAsCodePath,
  getContentAsCodePathFromLtreePath
} from '@lightdash/common';

// Store file path in database as ltree
const filePath = 'dashboards/sales/weekly-report.yml';
const dbPath = getLtreePathFromContentAsCodePath(filePath);
// Store: 'dashboards.sales.weekly_report' in ltree column

// Convert back when reading
const storedPath = 'dashboards.sales.weekly_report';
const originalPath = getContentAsCodePathFromLtreePath(storedPath);
// Returns: 'dashboards/sales/weekly-report'

Notes

  • Empty Names: If slug generation results in an empty string, a random 5-character string is returned
  • Ltree Format: PostgreSQL ltree type uses dots for hierarchy and underscores for spaces
  • Content Paths: Content-as-code paths use slashes for hierarchy and hyphens for spaces
  • Case Sensitivity: All slugs are converted to lowercase for consistency