-
-
Notifications
You must be signed in to change notification settings - Fork 13
docs: improve marketing positioning for ubiquity #465
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
7674cd8
12f81af
daf0062
5129943
ffb6d23
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,113 @@ | ||||||||||
| /** | ||||||||||
| * This TypeScript code exports a function named 'updateContents' which generates | ||||||||||
| * a table of contents from the README.md headers. | ||||||||||
| * @param {ReadmeSection} sectionToken - The sectionToken representing the section of the README to update. | ||||||||||
| * @param {Inputs} inputs - The Inputs class instance. | ||||||||||
| */ | ||||||||||
| import { ReadmeSection } from '../constants.js'; | ||||||||||
| import type Inputs from '../inputs.js'; | ||||||||||
| import LogTask from '../logtask/index.js'; | ||||||||||
|
|
||||||||||
| /** | ||||||||||
| * Converts a header text to a GitHub-compatible anchor link. | ||||||||||
| * @param {string} text - The header text to convert. | ||||||||||
| * @returns {string} The anchor link. | ||||||||||
| */ | ||||||||||
| function headerToAnchor(text: string): string { | ||||||||||
| return text | ||||||||||
| .toLowerCase() | ||||||||||
| .replace(/[^\w\s-]/g, '') // Remove special characters except hyphens | ||||||||||
| .replace(/\s+/g, '-') // Replace spaces with hyphens | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [eslint] <unicorn/prefer-string-replace-all> reported by reviewdog 🐶
Suggested change
|
||||||||||
| .replace(/-+/g, '-') // Collapse multiple hyphens | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [eslint] <unicorn/prefer-string-replace-all> reported by reviewdog 🐶
Suggested change
|
||||||||||
| .replace(/^-|-$/g, ''); // Remove leading/trailing hyphens | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [eslint] <unicorn/prefer-string-replace-all> reported by reviewdog 🐶
Suggested change
|
||||||||||
| } | ||||||||||
|
|
||||||||||
| /** | ||||||||||
| * Extracts headers from markdown content, excluding those in code blocks. | ||||||||||
| * @param {string} content - The markdown content. | ||||||||||
| * @returns {Array<{level: number, text: string}>} Array of header objects. | ||||||||||
| */ | ||||||||||
| function extractHeaders(content: string): Array<{ level: number; text: string }> { | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [eslint] <@typescript-eslint/array-type> reported by reviewdog 🐶
Suggested change
|
||||||||||
| const headers: Array<{ level: number; text: string }> = []; | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [eslint] <@typescript-eslint/array-type> reported by reviewdog 🐶
Suggested change
|
||||||||||
| const lines = content.split('\n'); | ||||||||||
| let inCodeBlock = false; | ||||||||||
|
|
||||||||||
| for (const line of lines) { | ||||||||||
| // Track code block state | ||||||||||
| if (line.trim().startsWith('```')) { | ||||||||||
| inCodeBlock = !inCodeBlock; | ||||||||||
| continue; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // Skip if inside code block | ||||||||||
| if (inCodeBlock) { | ||||||||||
| continue; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // Match markdown headers (## Header) | ||||||||||
| const headerMatch = /^(#{2,6})\s+(.+)$/.exec(line); | ||||||||||
| if (headerMatch) { | ||||||||||
| const level = headerMatch[1].length; | ||||||||||
| let text = headerMatch[2].trim(); | ||||||||||
|
|
||||||||||
| // Remove inline images and other markdown formatting from header text | ||||||||||
| text = text.replace(/<img[^>]*>/g, '').trim(); | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [eslint] <unicorn/prefer-string-replace-all> reported by reviewdog 🐶
Suggested change
|
||||||||||
| // Remove markdown links but keep the text | ||||||||||
| text = text.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1'); | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [eslint] <unicorn/prefer-string-replace-all> reported by reviewdog 🐶
Suggested change
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
|
|
||||||||||
| if (text) { | ||||||||||
| headers.push({ level, text }); | ||||||||||
| } | ||||||||||
| } | ||||||||||
| } | ||||||||||
|
|
||||||||||
| return headers; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| export default function updateContents( | ||||||||||
| sectionToken: ReadmeSection, | ||||||||||
| inputs: Inputs, | ||||||||||
| ): Record<string, string> { | ||||||||||
| const log = new LogTask(sectionToken); | ||||||||||
| log.start(); | ||||||||||
|
|
||||||||||
| const content: string[] = []; | ||||||||||
| const readmeContent = inputs.readmeEditor.getReadmeContent(); | ||||||||||
|
|
||||||||||
| // Extract headers from README | ||||||||||
| const headers = extractHeaders(readmeContent); | ||||||||||
|
|
||||||||||
| // Filter out the title (h1) and contents section itself | ||||||||||
| const tocHeaders = headers.filter( | ||||||||||
| (h) => h.level >= 2 && !h.text.toLowerCase().includes('contents'), | ||||||||||
| ); | ||||||||||
|
|
||||||||||
| if (tocHeaders.length === 0) { | ||||||||||
| log.info('No headers found for table of contents'); | ||||||||||
| const ret: Record<string, string> = {}; | ||||||||||
| ret[sectionToken] = ''; | ||||||||||
| return ret; | ||||||||||
| } | ||||||||||
|
Comment on lines
+85
to
+90
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Clear the TOC section when no headers are found. 🐛 Proposed fix if (tocHeaders.length === 0) {
log.info('No headers found for table of contents');
+ inputs.readmeEditor.updateSection(sectionToken, '');
const ret: Record<string, string> = {};
ret[sectionToken] = '';
return ret;
}🤖 Prompt for AI Agents |
||||||||||
|
|
||||||||||
| log.info(`Generating table of contents with ${tocHeaders.length} entries`); | ||||||||||
|
|
||||||||||
| // Find minimum header level for proper indentation | ||||||||||
| const minLevel = Math.min(...tocHeaders.map((h) => h.level)); | ||||||||||
|
|
||||||||||
| // Generate TOC entries | ||||||||||
| content.push('## Table of Contents'); | ||||||||||
| content.push(''); | ||||||||||
|
Comment on lines
+98
to
+99
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚫 [eslint] <unicorn/prefer-single-call> reported by reviewdog 🐶
Suggested change
|
||||||||||
|
|
||||||||||
| for (const header of tocHeaders) { | ||||||||||
| const indent = ' '.repeat(header.level - minLevel); | ||||||||||
| const anchor = headerToAnchor(header.text); | ||||||||||
| content.push(`${indent}- [${header.text}](#${anchor})`); | ||||||||||
| } | ||||||||||
|
Comment on lines
+97
to
+105
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Handle duplicate headings to avoid broken TOC links. 🐛 Proposed fix // Generate TOC entries
content.push('## Table of Contents');
content.push('');
+ const slugCounts = new Map<string, number>();
for (const header of tocHeaders) {
const indent = ' '.repeat(header.level - minLevel);
- const anchor = headerToAnchor(header.text);
- content.push(`${indent}- [${header.text}](#${anchor})`);
+ const baseAnchor = headerToAnchor(header.text);
+ const count = slugCounts.get(baseAnchor) ?? 0;
+ slugCounts.set(baseAnchor, count + 1);
+ const anchor = count === 0 ? baseAnchor : `${baseAnchor}-${count}`;
+ content.push(`${indent}- [${header.text}](#${anchor})`);
}🤖 Prompt for AI Agents |
||||||||||
|
|
||||||||||
| inputs.readmeEditor.updateSection(sectionToken, content); | ||||||||||
| log.success(); | ||||||||||
|
|
||||||||||
| const ret: Record<string, string> = {}; | ||||||||||
| ret[sectionToken] = content.join('\n'); | ||||||||||
| return ret; | ||||||||||
| } | ||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚫 [eslint] <unicorn/prefer-string-replace-all> reported by reviewdog 🐶
Prefer
String#replaceAll()overString#replace().