Skip to content

Instantly share code, notes, and snippets.

@simonw
Created December 15, 2024 19:21
Show Gist options
  • Save simonw/afebd0bdcfcc8c67a183ecec264523d0 to your computer and use it in GitHub Desktop.
Save simonw/afebd0bdcfcc8c67a183ecec264523d0 to your computer and use it in GitHub Desktop.

HTML Header Parser and Navigation Generator

human (Dec 15, 2024, 11:14 AM)

Build an artifact where I can paste in HTML in a textarea and a URL to that page in a single line input

It then parses that HTML and finds all HTML headers within it. Any that do not yet have an ID attribute have a unique one assigned to them based on the text of that heading (lowercase, spaces converted to hyphens, other characters removed)

The tool outputs two things in two new textareas: the new updated HTML with the extra ID attributes, and then a separate textarea with the following HTML - one list item for each heading:

<ul>
  <li><a href="that-URL-the-user-provided#heading-id">Heading text</a></li>
  ...

assistant (Dec 15, 2024, 11:14 AM)

I'll help create a tool for processing HTML headers and generating navigation links.

create HTML Header ID Generator and Link Builder

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>HTML Header Processor</title>
  <style>
  * {
    box-sizing: border-box;
  }

  body {
    font-family: Helvetica, Arial, sans-serif;
    line-height: 1.4;
    max-width: 1200px;
    margin: 0 auto;
    padding: 20px;
  }

  .input-group {
    margin-bottom: 20px;
  }

  label {
    display: block;
    margin-bottom: 8px;
    font-weight: bold;
  }

  input, textarea {
    width: 100%;
    font-size: 16px;
    padding: 8px;
    border: 1px solid #ccc;
    border-radius: 4px;
  }

  textarea {
    min-height: 200px;
    font-family: monospace;
  }

  button {
    background: #0066cc;
    color: white;
    border: none;
    padding: 10px 20px;
    border-radius: 4px;
    cursor: pointer;
    font-size: 16px;
  }

  button:hover {
    background: #0052a3;
  }
  </style>
</head>
<body>
  <div class="input-group">
    <label for="urlInput">Page URL:</label>
    <input type="url" id="urlInput" placeholder="https://example.com/page">
  </div>

  <div class="input-group">
    <label for="htmlInput">Input HTML:</label>
    <textarea id="htmlInput" placeholder="Paste HTML here..."></textarea>
  </div>

  <div class="input-group">
    <button onclick="processHTML()">Process Headers</button>
  </div>

  <div class="input-group">
    <label for="processedHtml">Processed HTML with IDs:</label>
    <textarea id="processedHtml" readonly></textarea>
  </div>

  <div class="input-group">
    <label for="headerLinks">Header Links:</label>
    <textarea id="headerLinks" readonly></textarea>
  </div>

<script type="module">
function createSlug(text) {
  return text
    .toLowerCase()
    .replace(/[^a-z0-9\s-]/g, '')
    .replace(/\s+/g, '-')
    .replace(/-+/g, '-')
    .trim()
}

function generateUniqueId(text, existingIds) {
  let baseId = createSlug(text)
  let id = baseId
  let counter = 1

  while (existingIds.has(id)) {
    id = `${baseId}-${counter}`
    counter++
  }

  existingIds.add(id)
  return id
}

window.processHTML = function() {
  const html = document.getElementById('htmlInput').value
  const url = document.getElementById('urlInput').value
  const parser = new DOMParser()
  const doc = parser.parseFromString(html, 'text/html')
  const existingIds = new Set()
  const headers = doc.querySelectorAll('h1, h2, h3, h4, h5, h6')
  const headerLinks = []

  headers.forEach(header => {
    if (!header.id) {
      header.id = generateUniqueId(header.textContent, existingIds)
    }
    headerLinks.push(`  <li><a href="${url}#${header.id}">${header.textContent}</a></li>`)
  })

  document.getElementById('processedHtml').value = doc.body.innerHTML
  document.getElementById('headerLinks').value = '<ul>\n' + headerLinks.join('\n') + '\n</ul>'
}
</script>
</body>
</html>

I've created a tool that:

  1. Has two main inputs:

    • A URL input field
    • A textarea for pasting HTML content
  2. Processes the HTML by:

    • Finding all heading elements (h1-h6)
    • Generating unique IDs for headers that don't have them
    • Creating slugs from header text by:
      • Converting to lowercase
      • Removing special characters
      • Converting spaces to hyphens
      • Handling duplicate IDs by adding numeric suffixes
  3. Outputs:

    • The processed HTML with added ID attributes
    • A formatted list of links to each header using the provided URL

The tool uses vanilla JavaScript with no dependencies and follows the requested styling conventions. You can paste in any HTML and get both the modified HTML and a navigation list as output.

Would you like me to modify anything about how it processes the headers or formats the output?

@simonw
Copy link
Author

simonw commented Dec 15, 2024

@simonw
Copy link
Author

simonw commented Dec 16, 2024

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment