chore:little fixes and formating and linting and patches

This commit is contained in:
2026-03-31 15:50:54 +02:00
parent a1ce71ffb6
commit 9b197abcfa
815 changed files with 22960 additions and 8982 deletions

View File

@@ -58,20 +58,39 @@ const FEATURES = [
slug: 'funnels',
url: '/features/funnels',
// "conversion funnel(s)" links to funnels, not conversion
patterns: ['conversion funnels', 'conversion funnel', 'funnel analysis', 'funnels', 'funnel'],
patterns: [
'conversion funnels',
'conversion funnel',
'funnel analysis',
'funnels',
'funnel',
],
},
{
slug: 'retention',
url: '/features/retention',
// "retention" alone is included but guarded by excludeBefore
patterns: ['retention analysis', 'user retention', 'retention rates', 'retention rate', 'retention'],
excludeBefore: ['data', 'unlimited'], // skip "data retention", "unlimited retention"
patterns: [
'retention analysis',
'user retention',
'retention rates',
'retention rate',
'retention',
],
excludeBefore: ['data', 'unlimited'], // skip "data retention", "unlimited retention"
excludeAfter: ['period', 'policy', 'limit', 'of data'],
},
{
slug: 'conversion',
url: '/features/conversion',
patterns: ['conversion tracking', 'conversion rates', 'conversion rate', 'conversion paths', 'conversions', 'conversion'],
patterns: [
'conversion tracking',
'conversion rates',
'conversion rate',
'conversion paths',
'conversions',
'conversion',
],
excludeBefore: ['data'],
},
];
@@ -90,39 +109,57 @@ function getSkipZones(text) {
// Fenced code blocks ```…```
const codeBlock = /```[\s\S]*?```/g;
while ((m = codeBlock.exec(text))) zones.push({ start: m.index, end: m.index + m[0].length });
while ((m = codeBlock.exec(text))) {
zones.push({ start: m.index, end: m.index + m[0].length });
}
// Inline code `…`
const inlineCode = /`[^`\n]+`/g;
while ((m = inlineCode.exec(text))) zones.push({ start: m.index, end: m.index + m[0].length });
while ((m = inlineCode.exec(text))) {
zones.push({ start: m.index, end: m.index + m[0].length });
}
// Existing markdown links [text](url)
const mdLink = /\[[^\]]*\]\([^)]*\)/g;
while ((m = mdLink.exec(text))) zones.push({ start: m.index, end: m.index + m[0].length });
while ((m = mdLink.exec(text))) {
zones.push({ start: m.index, end: m.index + m[0].length });
}
// Headings # … (entire line)
const heading = /^#{1,6}\s+.+$/gm;
while ((m = heading.exec(text))) zones.push({ start: m.index, end: m.index + m[0].length });
while ((m = heading.exec(text))) {
zones.push({ start: m.index, end: m.index + m[0].length });
}
// JSX / HTML tags (attributes may contain feature words)
const jsxTag = /<[^>]+>/g;
while ((m = jsxTag.exec(text))) zones.push({ start: m.index, end: m.index + m[0].length });
while ((m = jsxTag.exec(text))) {
zones.push({ start: m.index, end: m.index + m[0].length });
}
// import statements
const imp = /^import\s+.+$/gm;
while ((m = imp.exec(text))) zones.push({ start: m.index, end: m.index + m[0].length });
while ((m = imp.exec(text))) {
zones.push({ start: m.index, end: m.index + m[0].length });
}
// Frontmatter block
const fm = /^---[\s\S]*?---/;
if ((m = fm.exec(text))) zones.push({ start: m.index, end: m.index + m[0].length });
if ((m = fm.exec(text))) {
zones.push({ start: m.index, end: m.index + m[0].length });
}
// Markdown table rows (| … |)
const tableRow = /^\|.+\|$/gm;
while ((m = tableRow.exec(text))) zones.push({ start: m.index, end: m.index + m[0].length });
while ((m = tableRow.exec(text))) {
zones.push({ start: m.index, end: m.index + m[0].length });
}
// > blockquote lines that contain links
const bqLink = /^>\s.*\[.*\]\(.*\).*$/gm;
while ((m = bqLink.exec(text))) zones.push({ start: m.index, end: m.index + m[0].length });
while ((m = bqLink.exec(text))) {
zones.push({ start: m.index, end: m.index + m[0].length });
}
return zones;
}
@@ -146,28 +183,42 @@ function processFile(filePath, dir) {
for (const feature of FEATURES) {
// If the file already links to this feature URL, skip entirely
if (content.includes(feature.url)) continue;
if (content.includes(feature.url)) {
continue;
}
let linked = false;
for (const pattern of feature.patterns) {
if (linked) break;
if (linked) {
break;
}
const re = new RegExp(`\\b${escapeRegex(pattern)}\\b`, 'gi');
let m;
while ((m = re.exec(content))) {
// In a skip zone?
if (overlapsSkipZone(m.index, m[0].length, skipZones)) continue;
if (overlapsSkipZone(m.index, m[0].length, skipZones)) {
continue;
}
// Check excludeBefore / excludeAfter
if (feature.excludeBefore) {
const before = content.slice(Math.max(0, m.index - 20), m.index).toLowerCase();
if (feature.excludeBefore.some((w) => before.endsWith(w + ' '))) continue;
const before = content
.slice(Math.max(0, m.index - 20), m.index)
.toLowerCase();
if (feature.excludeBefore.some((w) => before.endsWith(w + ' '))) {
continue;
}
}
if (feature.excludeAfter) {
const after = content.slice(m.index + m[0].length, m.index + m[0].length + 20).toLowerCase();
if (feature.excludeAfter.some((w) => after.startsWith(' ' + w))) continue;
const after = content
.slice(m.index + m[0].length, m.index + m[0].length + 20)
.toLowerCase();
if (feature.excludeAfter.some((w) => after.startsWith(' ' + w))) {
continue;
}
}
// Build replacement
@@ -194,7 +245,9 @@ function processFile(filePath, dir) {
}
}
if (changes.length === 0) return null;
if (changes.length === 0) {
return null;
}
// Add / update the `updated` frontmatter field for articles & guides
if (DIRS_WITH_UPDATED.includes(dir)) {
@@ -223,8 +276,11 @@ function walk(dir) {
const files = [];
for (const e of entries) {
const full = path.join(dir, e.name);
if (e.isDirectory()) files.push(...walk(full));
else if (e.name.endsWith('.mdx')) files.push(full);
if (e.isDirectory()) {
files.push(...walk(full));
} else if (e.name.endsWith('.mdx')) {
files.push(full);
}
}
return files;
}
@@ -235,7 +291,9 @@ const results = [];
for (const dir of DIRS) {
const dirPath = path.join(CONTENT_DIR, dir);
if (!fs.existsSync(dirPath)) continue;
if (!fs.existsSync(dirPath)) {
continue;
}
for (const file of walk(dirPath)) {
const changes = processFile(file, dir);
@@ -247,7 +305,9 @@ for (const dir of DIRS) {
console.log('=== Internal Linking Report ===\n');
console.log(`Total files modified: ${results.length}`);
console.log(`Total links added: ${results.reduce((s, r) => s + r.changes.length, 0)}\n`);
console.log(
`Total links added: ${results.reduce((s, r) => s + r.changes.length, 0)}\n`
);
for (const r of results) {
console.log(` ${r.file}`);