mirror of
https://github.com/jimeh/commonflow.org.git
synced 2026-02-19 05:46:40 +00:00
fix: spec TOC
This commit is contained in:
@@ -9,15 +9,17 @@
|
|||||||
document.documentElement.classList.add("dark");
|
document.documentElement.classList.add("dark");
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
</script><link rel="stylesheet" href="/_astro/index.DViPM5fQ.css"></head> <body class="min-h-screen flex flex-col items-center justify-center p-8"> <div class="text-center"> <h1 class="text-[8rem] sm:text-[12rem] font-display font-bold leading-none
|
</script><link rel="stylesheet" href="/_astro/index.BpjWaW-v.css"></head> <body class="min-h-screen flex flex-col items-center justify-center p-8"> <div class="text-center"> <h1 class="text-[8rem] sm:text-[12rem] font-display font-bold leading-none
|
||||||
text-[var(--color-border-strong)]
|
text-gray-300 dark:text-gray-700">
|
||||||
dark:text-[var(--color-dark-border-strong)]">
|
|
||||||
404
|
404
|
||||||
</h1> <p class="text-xl mb-2 text-[var(--color-text-secondary)]
|
</h1> <p class="text-xl mb-2 text-gray-600 dark:text-gray-400">
|
||||||
dark:text-[var(--color-dark-text-secondary)]">
|
|
||||||
Page not found
|
Page not found
|
||||||
</p> <p class="text-[var(--color-text-muted)] dark:text-[var(--color-dark-text-muted)]">
|
</p> <p class="text-gray-500 dark:text-gray-500">
|
||||||
The page you're looking for doesn't exist.
|
The page you're looking for doesn't exist.
|
||||||
</p> <a href="/" class="inline-block mt-8 btn btn-primary">
|
</p> <a href="/" class="inline-flex items-center justify-center gap-2 mt-8
|
||||||
|
px-5 py-2.5 text-sm font-medium rounded-lg
|
||||||
|
transition-all cursor-pointer
|
||||||
|
bg-sky-600 text-white
|
||||||
|
hover:bg-sky-500 hover:-translate-y-0.5 hover:shadow-md">
|
||||||
Go to homepage
|
Go to homepage
|
||||||
</a> </div> </body></html>
|
</a> </div> </body></html>
|
||||||
1
docs/_astro/index.BpjWaW-v.css
Normal file
1
docs/_astro/index.BpjWaW-v.css
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
301
docs/index.html
301
docs/index.html
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -132,6 +132,11 @@ const { terminology, specification, tocItems } = Astro.props;
|
|||||||
color: #737373;
|
color: #737373;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Scroll margin for anchored spec sections */
|
||||||
|
.spec-content :global(ol > li[id]) {
|
||||||
|
scroll-margin-top: calc(var(--header-height) + 2rem);
|
||||||
|
}
|
||||||
|
|
||||||
.spec-content :global(li) {
|
.spec-content :global(li) {
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
color: #525252;
|
color: #525252;
|
||||||
|
|||||||
@@ -96,6 +96,20 @@ function escapeRegex(str: string): string {
|
|||||||
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Spec section titles in order (used for both ToC and anchor injection)
|
||||||
|
const SPEC_SECTION_TITLES = [
|
||||||
|
"TL;DR",
|
||||||
|
"The Master Branch",
|
||||||
|
"Change Branches",
|
||||||
|
"Pull Requests",
|
||||||
|
"Versioning",
|
||||||
|
"Releases",
|
||||||
|
"Short-Term Release Branches",
|
||||||
|
"Long-term Release Branches",
|
||||||
|
"Bug Fixes & Rollback",
|
||||||
|
"Git Best Practices",
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract the numbered spec sections (1. TL;DR, 2. The Master Branch, etc.)
|
* Extract the numbered spec sections (1. TL;DR, 2. The Master Branch, etc.)
|
||||||
*/
|
*/
|
||||||
@@ -107,24 +121,8 @@ function extractSpecSections(specContent: string): SpecSection[] {
|
|||||||
const olMatch = specContent.match(/<ol[^>]*>([\s\S]*?)<\/ol>/i);
|
const olMatch = specContent.match(/<ol[^>]*>([\s\S]*?)<\/ol>/i);
|
||||||
if (!olMatch) return sections;
|
if (!olMatch) return sections;
|
||||||
|
|
||||||
// Split by top-level list items
|
|
||||||
// We need to handle nested lists carefully
|
|
||||||
const sectionTitles = [
|
|
||||||
"TL;DR",
|
|
||||||
"The Master Branch",
|
|
||||||
"Change Branches",
|
|
||||||
"Pull Requests",
|
|
||||||
"Versioning",
|
|
||||||
"Releases",
|
|
||||||
"Short-Term Release Branches",
|
|
||||||
"Long-term Release Branches",
|
|
||||||
"Bug Fixes & Rollback",
|
|
||||||
"Git Best Practices",
|
|
||||||
];
|
|
||||||
|
|
||||||
// Find each section by looking for the title pattern
|
// Find each section by looking for the title pattern
|
||||||
for (let i = 0; i < sectionTitles.length; i++) {
|
for (const title of SPEC_SECTION_TITLES) {
|
||||||
const title = sectionTitles[i];
|
|
||||||
const id = slugify(title);
|
const id = slugify(title);
|
||||||
|
|
||||||
// For the content, we'll just use the title for navigation
|
// For the content, we'll just use the title for navigation
|
||||||
@@ -139,6 +137,27 @@ function extractSpecSections(specContent: string): SpecSection[] {
|
|||||||
return sections;
|
return sections;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add anchor IDs to spec section list items.
|
||||||
|
* Finds top-level <li> elements that start with section titles and adds IDs.
|
||||||
|
*/
|
||||||
|
function addSpecSectionAnchors(specContent: string): string {
|
||||||
|
let result = specContent;
|
||||||
|
|
||||||
|
for (const title of SPEC_SECTION_TITLES) {
|
||||||
|
const id = `spec-${slugify(title)}`;
|
||||||
|
// Match <li> followed by the section title (possibly with whitespace)
|
||||||
|
// The title appears right after <li> in the rendered HTML
|
||||||
|
const pattern = new RegExp(
|
||||||
|
`(<li>)(\\s*${escapeRegex(title)})`,
|
||||||
|
"i"
|
||||||
|
);
|
||||||
|
result = result.replace(pattern, `<li id="${id}">$2`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract FAQ items from the FAQ section HTML
|
* Extract FAQ items from the FAQ section HTML
|
||||||
*/
|
*/
|
||||||
@@ -187,18 +206,13 @@ function extractFAQItems(faqContent: string): FAQItem[] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build table of contents from parsed sections
|
* Build table of contents from parsed sections.
|
||||||
|
* Only includes sections rendered in SpecSection (Terminology + Specification).
|
||||||
|
* Introduction/Summary are in AboutSection and excluded from this ToC.
|
||||||
*/
|
*/
|
||||||
function buildTocItems(parsed: Partial<ParsedSpec>): TocItem[] {
|
function buildTocItems(parsed: Partial<ParsedSpec>): TocItem[] {
|
||||||
const items: TocItem[] = [];
|
const items: TocItem[] = [];
|
||||||
|
|
||||||
// Main sections
|
|
||||||
if (parsed.introduction) {
|
|
||||||
items.push({ id: "introduction", title: "Introduction", level: 2 });
|
|
||||||
}
|
|
||||||
if (parsed.summary) {
|
|
||||||
items.push({ id: "summary", title: "Summary", level: 2 });
|
|
||||||
}
|
|
||||||
if (parsed.terminology) {
|
if (parsed.terminology) {
|
||||||
items.push({ id: "terminology", title: "Terminology", level: 2 });
|
items.push({ id: "terminology", title: "Terminology", level: 2 });
|
||||||
}
|
}
|
||||||
@@ -256,12 +270,15 @@ export function parseSpecContent(html: string, version: string): ParsedSpec {
|
|||||||
"License",
|
"License",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const specification = extractSection(
|
const specificationRaw = extractSection(
|
||||||
content,
|
content,
|
||||||
"Git Common-Flow Specification",
|
"Git Common-Flow Specification",
|
||||||
["FAQ", "About", "License"]
|
["FAQ", "About", "License"]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Add anchor IDs to spec section list items for ToC navigation
|
||||||
|
const specification = addSpecSectionAnchors(specificationRaw);
|
||||||
|
|
||||||
const faqContent = extractSection(content, "FAQ", ["About", "License"]);
|
const faqContent = extractSection(content, "FAQ", ["About", "License"]);
|
||||||
|
|
||||||
const about = extractSection(content, "About", ["License"]);
|
const about = extractSection(content, "About", ["License"]);
|
||||||
@@ -269,7 +286,7 @@ export function parseSpecContent(html: string, version: string): ParsedSpec {
|
|||||||
const license = extractSection(content, "License", []);
|
const license = extractSection(content, "License", []);
|
||||||
|
|
||||||
// Parse subsections
|
// Parse subsections
|
||||||
const specSections = extractSpecSections(specification);
|
const specSections = extractSpecSections(specificationRaw);
|
||||||
const faq = extractFAQItems(faqContent);
|
const faq = extractFAQItems(faqContent);
|
||||||
|
|
||||||
const parsed: ParsedSpec = {
|
const parsed: ParsedSpec = {
|
||||||
|
|||||||
Reference in New Issue
Block a user