Skip to content

Commit

Permalink
More readability improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
andrii-balitskyi committed Aug 2, 2024
1 parent 4f3c9a1 commit 203a022
Showing 1 changed file with 40 additions and 27 deletions.
67 changes: 40 additions & 27 deletions generate-readme-toc.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
import fs from 'fs/promises'

const README_FILE = 'README.rst'
const CONTENTS_HEADING = 'Contents'
const CONTENTS_UNDERLINE = '--------'
const TOC_INDENT_LEVELS = {
'-': 1,
'~': 2,
'^': 3,
}
const HEADING_UNDERLINE_REGEX = /^[-~^]+$/

async function generateTableOfContents(content) {
const lines = content.split('\n')
const headings = []
Expand All @@ -10,68 +20,71 @@ async function generateTableOfContents(content) {
const line = lines[i].trim()
const nextLine = lines[i + 1]?.trim() || ''

if (line === 'Contents' && nextLine.startsWith('--------')) {
if (line === CONTENTS_HEADING && nextLine.startsWith(CONTENTS_UNDERLINE)) {
contentsHeadingIndex = i
parsingHeadings = true // Start parsing headings after the "Contents" section
i++ // Skip the underline
continue
}

if (parsingHeadings && nextLine && nextLine.match(/^[-~^]+$/)) {
const level =
nextLine[0] === '-'
? 1
: nextLine[0] === '~'
? 2
: nextLine[0] === '^'
? 3
: 0
if (
parsingHeadings &&
nextLine &&
nextLine.match(HEADING_UNDERLINE_REGEX)
) {
const level = TOC_INDENT_LEVELS[nextLine[0]] || 0

if (level > 0 && line) {
headings.push({ text: line, level })
}
i++ // Skip the underline

i++
}
}

// Generate table of contents
const toc = [''] // Start with an empty line after the "Contents" section
const toc = ['']
headings.forEach((heading) => {
const indent = ' '.repeat(heading.level - 1)

toc.push(`${indent}* \`${heading.text} <${heading.text}_>\`_`)
toc.push('') // Add a newline after each item
toc.push('')
})

return { toc, contentsHeadingIndex }
}

function findTocEndIndex(lines, startIndex) {
return lines.findIndex(
(line, index) =>
index > startIndex + 2 &&
!line.trim().startsWith('*') &&
line.trim() !== '',
)
}

async function updateReadme() {
try {
const content = await fs.readFile('README.rst', 'utf8')
const content = await fs.readFile(README_FILE, 'utf8')
const { toc, contentsHeadingIndex } = await generateTableOfContents(content)

if (contentsHeadingIndex === -1) {
console.error('Contents heading not found in the README.')
process.exit(1)
throw new Error('Contents heading not found in the README.')
}

const lines = content.split('\n')
const tocTableEndIndex = lines.findIndex(
(line, index) =>
index > contentsHeadingIndex + 2 &&
!line.trim().startsWith('*') &&
line.trim() !== '',
)
const tocEndIndex = findTocEndIndex(lines, contentsHeadingIndex)

const newContent = [
...lines.slice(0, contentsHeadingIndex + 2), // Include readme content before "Contents" heading, the heading itself and its underline
...lines.slice(0, contentsHeadingIndex + 2), // Include content before "Contents" heading, the heading itself and its underline
...toc,
...lines.slice(tocTableEndIndex), // Include all content after the previous TOC
...lines.slice(tocEndIndex),
].join('\n')

await fs.writeFile('README.rst', newContent)
console.log('Table of Contents has been updated in README.rst')
await fs.writeFile(README_FILE, newContent)
console.log(`Table of Contents has been updated in ${README_FILE}`)
} catch (error) {
console.error('Error processing file:', error)
console.error('Error updating README:', error.message)
process.exit(1)
}
}
Expand Down

0 comments on commit 203a022

Please sign in to comment.