wip
This commit is contained in:
32
scripts/fetch-all-posts.js
Normal file
32
scripts/fetch-all-posts.js
Normal file
@@ -0,0 +1,32 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { execSync } = require('child_process');
|
||||
|
||||
const blogDir = path.join(process.cwd(), 'data', 'blog', 'en');
|
||||
const outputDir = path.join(process.cwd(), 'reference', 'klz-cables-clone', 'posts');
|
||||
|
||||
if (!fs.existsSync(outputDir)) {
|
||||
fs.mkdirSync(outputDir, { recursive: true });
|
||||
}
|
||||
|
||||
const files = fs.readdirSync(blogDir);
|
||||
|
||||
files.forEach(file => {
|
||||
if (!file.endsWith('.mdx')) return;
|
||||
|
||||
const slug = file.replace('.mdx', '');
|
||||
const url = `https://klz-cables.com/${slug}/`;
|
||||
const outputPath = path.join(outputDir, `${slug}.html`);
|
||||
|
||||
if (fs.existsSync(outputPath)) {
|
||||
console.log(`Skipping ${slug}, already exists.`);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`Fetching ${slug}...`);
|
||||
try {
|
||||
execSync(`curl -L -s "${url}" -o "${outputPath}"`);
|
||||
} catch (e) {
|
||||
console.error(`Failed to fetch ${slug}: ${e.message}`);
|
||||
}
|
||||
});
|
||||
87
scripts/fix-mdx-frontmatter.js
Normal file
87
scripts/fix-mdx-frontmatter.js
Normal file
@@ -0,0 +1,87 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const blogDir = path.join(process.cwd(), 'data', 'blog');
|
||||
|
||||
function fixFile(filePath) {
|
||||
const content = fs.readFileSync(filePath, 'utf8');
|
||||
const lines = content.split('\n');
|
||||
|
||||
if (lines[0].trim() !== '---') {
|
||||
return; // Not a frontmatter file or already fixed/different format
|
||||
}
|
||||
|
||||
let newLines = [];
|
||||
let inFrontmatter = false;
|
||||
let frontmatterLines = [];
|
||||
let contentLines = [];
|
||||
|
||||
// Separate frontmatter and content
|
||||
if (lines[0].trim() === '---') {
|
||||
inFrontmatter = true;
|
||||
let i = 1;
|
||||
// Skip empty line after first ---
|
||||
if (lines[1].trim() === '') {
|
||||
i = 2;
|
||||
}
|
||||
|
||||
for (; i < lines.length; i++) {
|
||||
if (lines[i].trim() === '---') {
|
||||
inFrontmatter = false;
|
||||
contentLines = lines.slice(i + 1);
|
||||
break;
|
||||
}
|
||||
frontmatterLines.push(lines[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Process frontmatter lines to fix multiline strings
|
||||
let fixedFrontmatter = [];
|
||||
for (let i = 0; i < frontmatterLines.length; i++) {
|
||||
let line = frontmatterLines[i];
|
||||
|
||||
// Check for multiline indicator >-
|
||||
if (line.includes('>-')) {
|
||||
const [key, ...rest] = line.split(':');
|
||||
if (rest.join(':').trim() === '>-') {
|
||||
// It's a multiline start
|
||||
let value = '';
|
||||
let j = i + 1;
|
||||
while (j < frontmatterLines.length) {
|
||||
const nextLine = frontmatterLines[j];
|
||||
// If next line is a new key (contains : and doesn't start with space), stop
|
||||
if (nextLine.includes(':') && !nextLine.startsWith(' ')) {
|
||||
break;
|
||||
}
|
||||
value += (value ? ' ' : '') + nextLine.trim();
|
||||
j++;
|
||||
}
|
||||
fixedFrontmatter.push(`${key}: '${value.replace(/'/g, "''")}'`);
|
||||
i = j - 1; // Skip processed lines
|
||||
} else {
|
||||
fixedFrontmatter.push(line);
|
||||
}
|
||||
} else {
|
||||
fixedFrontmatter.push(line);
|
||||
}
|
||||
}
|
||||
|
||||
const newContent = `---\n${fixedFrontmatter.join('\n')}\n---\n${contentLines.join('\n')}`;
|
||||
fs.writeFileSync(filePath, newContent);
|
||||
console.log(`Fixed ${filePath}`);
|
||||
}
|
||||
|
||||
function processDir(dir) {
|
||||
const files = fs.readdirSync(dir);
|
||||
for (const file of files) {
|
||||
const filePath = path.join(dir, file);
|
||||
const stat = fs.statSync(filePath);
|
||||
if (stat.isDirectory()) {
|
||||
processDir(filePath);
|
||||
} else if (file.endsWith('.mdx')) {
|
||||
fixFile(filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
processDir(blogDir);
|
||||
102
scripts/migrate-visual-links.js
Normal file
102
scripts/migrate-visual-links.js
Normal file
@@ -0,0 +1,102 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const jsdom = require('jsdom');
|
||||
const { JSDOM } = jsdom;
|
||||
|
||||
const postsDir = path.join(process.cwd(), 'reference', 'klz-cables-clone', 'posts');
|
||||
const mdxDir = path.join(process.cwd(), 'data', 'blog', 'en');
|
||||
|
||||
const files = fs.readdirSync(postsDir);
|
||||
|
||||
files.forEach(file => {
|
||||
if (!file.endsWith('.html')) return;
|
||||
|
||||
const slug = file.replace('.html', '');
|
||||
const mdxPath = path.join(mdxDir, `${slug}.mdx`);
|
||||
|
||||
if (!fs.existsSync(mdxPath)) {
|
||||
console.log(`MDX file not found for ${slug}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const htmlContent = fs.readFileSync(path.join(postsDir, file), 'utf8');
|
||||
const dom = new JSDOM(htmlContent);
|
||||
const document = dom.window.document;
|
||||
|
||||
const vlpContainers = document.querySelectorAll('.vlp-link-container');
|
||||
|
||||
if (vlpContainers.length === 0) return;
|
||||
|
||||
console.log(`Processing ${slug} with ${vlpContainers.length} visual links`);
|
||||
|
||||
let mdxContent = fs.readFileSync(mdxPath, 'utf8');
|
||||
let modified = false;
|
||||
|
||||
vlpContainers.forEach(container => {
|
||||
const link = container.querySelector('a.vlp-link');
|
||||
const titleEl = container.querySelector('.vlp-link-title');
|
||||
const summaryEl = container.querySelector('.vlp-link-summary');
|
||||
const imgEl = container.querySelector('.vlp-link-image img');
|
||||
|
||||
if (!link) return;
|
||||
|
||||
const url = link.getAttribute('href');
|
||||
const title = titleEl ? titleEl.textContent.trim() : '';
|
||||
const summary = summaryEl ? summaryEl.textContent.trim() : '';
|
||||
const image = imgEl ? imgEl.getAttribute('src') : '';
|
||||
|
||||
// Construct the component string
|
||||
const component = `
|
||||
<VisualLinkPreview
|
||||
url="${url}"
|
||||
title="${title.replace(/"/g, '"')}"
|
||||
summary="${summary.replace(/"/g, '"')}"
|
||||
image="${image}"
|
||||
/>
|
||||
`;
|
||||
|
||||
// Try to find the link in MDX
|
||||
// It could be [Title](URL) or just URL or <a href="URL">...</a>
|
||||
// We'll try to find the URL and replace the paragraph containing it if it looks like a standalone link
|
||||
// Or just append it if we can't find it easily? No, that's risky.
|
||||
|
||||
// Strategy: Look for the URL.
|
||||
// If found in `[...](url)`, replace the whole markdown link.
|
||||
// If found in `href="url"`, replace the anchor tag.
|
||||
|
||||
const markdownLinkRegex = new RegExp(`\\[.*?\\]\\(${escapeRegExp(url)}\\)`, 'g');
|
||||
const plainUrlRegex = new RegExp(`(?<!\\()${escapeRegExp(url)}(?!\\))`, 'g'); // URL not in parens
|
||||
|
||||
if (markdownLinkRegex.test(mdxContent)) {
|
||||
mdxContent = mdxContent.replace(markdownLinkRegex, component);
|
||||
modified = true;
|
||||
} else if (plainUrlRegex.test(mdxContent)) {
|
||||
// Be careful not to replace inside other attributes
|
||||
// This is a bit loose, but might work for standalone URLs
|
||||
// Better to check if it's a standalone line?
|
||||
// Let's just replace it.
|
||||
mdxContent = mdxContent.replace(plainUrlRegex, component);
|
||||
modified = true;
|
||||
} else {
|
||||
console.log(`Could not find link for ${url} in ${slug}`);
|
||||
// Maybe the URL in MDX is slightly different (e.g. trailing slash)?
|
||||
// Or maybe it's not there at all.
|
||||
// Let's try without trailing slash
|
||||
const urlNoSlash = url.replace(/\/$/, '');
|
||||
const markdownLinkRegex2 = new RegExp(`\\[.*?\\]\\(${escapeRegExp(urlNoSlash)}\\)`, 'g');
|
||||
if (markdownLinkRegex2.test(mdxContent)) {
|
||||
mdxContent = mdxContent.replace(markdownLinkRegex2, component);
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (modified) {
|
||||
fs.writeFileSync(mdxPath, mdxContent);
|
||||
console.log(`Updated ${slug}`);
|
||||
}
|
||||
});
|
||||
|
||||
function escapeRegExp(string) {
|
||||
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
}
|
||||
Reference in New Issue
Block a user