-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #62 from vtexdocs/fix/image-script
fix: images script
- Loading branch information
Showing
2,434 changed files
with
14,890 additions
and
8,306 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,39 +1,80 @@ | ||
// This script has an error: it passes absolute paths to the function updateImages. So the updated image links are wrong. This can be fixed manually using VSCode search. | ||
const fs = require('fs').promises; // Use the promise-based version of fs | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const { updateImages } = require('./update-images.js'); // Ensure this returns a promise or is async | ||
|
||
const targetDir = path.join(__dirname, '../docs'); | ||
let articleNumber = 0; | ||
let allArticles = []; | ||
const docsDirEN = path.join(__dirname, '../docs/en/'); | ||
const docsDirPT = path.join(__dirname, '../docs/pt/'); | ||
const docsDirES = path.join(__dirname, '../docs/es/'); | ||
|
||
async function iterateFiles(dir) { | ||
const files = await fs.readdir(dir, { withFileTypes: true }); | ||
const { updateImages } = require('./update-images.js'); | ||
|
||
for (const file of files) { | ||
const fullPath = path.join(dir, file.name).replace(/\\/g, '/'); | ||
const MAX_CONCURRENT_FILES = 100; | ||
|
||
if (file.isDirectory()) { | ||
// If it's a directory, recursively search it | ||
await iterateFiles(fullPath); | ||
} else if (file.isFile() && (file.name.endsWith('.md') || file.name.endsWith('.mdx'))) { | ||
// If it's a .md or .mdx file, do something with it | ||
articleNumber++; | ||
allArticles.push(fullPath); | ||
let activeFiles = 0; | ||
let fileQueue = []; | ||
|
||
// Function to process each Markdown file | ||
async function processFile(filePath) { | ||
try { | ||
// console.log(`Updating images for: ${filePath}`); | ||
await updateImages(filePath); // Wait for updateImages to finish before proceeding | ||
// console.log(`Finished updating images for: ${filePath}`); | ||
} catch (error) { | ||
console.error(`Error processing file: ${filePath}`, error); | ||
} finally { | ||
activeFiles--; | ||
if (fileQueue.length > 0) { | ||
const nextFile = fileQueue.shift(); | ||
await processFile(nextFile); | ||
} | ||
} | ||
} | ||
} | ||
|
||
async function processArticles() { | ||
for (const article of allArticles) { | ||
console.log(`Updating images for: ${article}`); | ||
await updateImages(article); // Wait for updateImages to finish before proceeding | ||
console.log(`Finished updating images for: ${article}`); | ||
} | ||
// Function to recursively process files in directories | ||
async function processDirectory(dirPath) { | ||
try { | ||
const files = fs.readdirSync(dirPath); | ||
|
||
for (const file of files) { | ||
const filePath = path.join(dirPath, file); | ||
const stats = fs.statSync(filePath); | ||
|
||
if (stats.isDirectory()) { | ||
await processDirectory(filePath); | ||
} else if (path.extname(file) === '.md') { | ||
if (activeFiles < MAX_CONCURRENT_FILES) { | ||
activeFiles++; | ||
await processFile(filePath); | ||
} else { | ||
fileQueue.push(filePath); | ||
} | ||
} | ||
} | ||
} catch (error) { | ||
console.error('Error processing directory:', error); | ||
} | ||
} | ||
|
||
// Start iterating from the target directory and process articles sequentially | ||
async function updateAllImages() { | ||
console.log("Updating all images..."); | ||
await processDirectory(docsDirEN); | ||
await processDirectory(docsDirPT); | ||
await processDirectory(docsDirES); | ||
|
||
// Wait until all files are processed | ||
while (activeFiles > 0 || fileQueue.length > 0) { | ||
await new Promise(resolve => setTimeout(resolve, 100)); | ||
} | ||
|
||
console.log("Finished replacing all images in markdown files."); | ||
} | ||
|
||
(async () => { | ||
await iterateFiles(targetDir); // First gather all the articles | ||
await processArticles(); // Then process them one by one | ||
try { | ||
await updateAllImages(); | ||
} catch (error) { | ||
console.error('Error during image updates:', error); | ||
} | ||
})(); | ||
|
||
module.exports = { updateAllImages } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,78 +1,130 @@ | ||
const fs = require('fs') | ||
const path = require('path') | ||
// const frontmatter = require('front-matter') | ||
const imageDownloader = require('image-downloader') | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const imageDownloader = require('image-downloader'); | ||
const sharp = require('sharp'); | ||
|
||
const baseURL = 'https://raw.githubusercontent.com/vtexdocs/help-center-content/refs/heads/main/' | ||
const baseURL = 'https://raw.githubusercontent.com/vtexdocs/help-center-content/refs/heads/main/'; | ||
|
||
const isValidExtension = (ext) => { | ||
return /^[a-zA-Z0-9]*$/.test(ext) | ||
} | ||
const isValidExtension = (ext) => /^[a-zA-Z0-9]*$/.test(ext); | ||
|
||
const getExtension = (url) => { | ||
let dotIndex = url.length - 1 | ||
while (dotIndex >= 0 && url[dotIndex] !== '.') { | ||
dotIndex-- | ||
} | ||
let dotIndex = url.lastIndexOf('.'); | ||
if (dotIndex < 0) return 'png'; // Default to 'png' if no extension | ||
const ext = url.substring(dotIndex + 1); | ||
return isValidExtension(ext) ? ext : 'png'; | ||
}; | ||
|
||
const ext = url.substring(dotIndex + 1) | ||
if (dotIndex < 0 || !isValidExtension(ext)) return 'png' | ||
return ext | ||
} | ||
const checkAndCompressImage = async (filePath) => { | ||
try { | ||
// Ensure the file is a GIF | ||
const fileExt = path.extname(filePath).toLowerCase(); | ||
if (fileExt !== '.gif') { | ||
console.log(`Skipping non-GIF file: ${filePath}`); | ||
return filePath; // Return original path if it's not a GIF | ||
} | ||
|
||
const updateImages = async (filepath) => { | ||
const stats = fs.statSync(filePath); | ||
const fileSizeInMB = stats.size / (1024 * 1024); // Convert bytes to MB | ||
|
||
if (fileSizeInMB > 100) { // If file exceeds 100MB | ||
console.log(`File ${filePath} is over 100MB (${fileSizeInMB.toFixed(2)} MB). Compressing...`); | ||
let compressedFilePath = filePath.replace(/(\.\w+)$/, '_compressed$1'); // Add "_compressed" before the extension | ||
await sharp(filePath, {limitInputPixels: 0, animated: true }) | ||
.resize(800) | ||
.gif({ interFrameMaxError: 32 }) | ||
.toFile(compressedFilePath); | ||
|
||
// Check if original file exists and delete it | ||
if (fs.existsSync(filePath)) { | ||
fs.unlinkSync(filePath); // Delete the original file | ||
console.log(`Original file deleted: ${filePath}`); | ||
fs.renameSync(compressedFilePath, filePath); | ||
console.log(`File renamed: ${filePath}`); | ||
} else { | ||
console.log(`Original file not found, skipping deletion: ${filePath}`); | ||
} | ||
|
||
console.log ('Running update-images.js') | ||
return filePath; // Return compressed file path | ||
} else { | ||
console.log(`File ${filePath} is within the size limit (${fileSizeInMB.toFixed(2)} MB).`); | ||
return filePath; // Return original file path if no compression needed | ||
} | ||
} catch (error) { | ||
console.error(`Error checking or compressing file ${filePath}:`, error.message); | ||
return filePath; // Return original path if there's an error | ||
} | ||
}; | ||
|
||
const updateImages = async (filepath) => { | ||
if (!filepath) { | ||
console.error('Received undefined filePath in updateImages'); | ||
return; // Early return if filePath is undefined | ||
return; | ||
} | ||
|
||
const resolvedFilepath = path.resolve(filepath); // Ensure the path is absolute | ||
console.log(`Processing images in this file: ${resolvedFilepath}`); | ||
|
||
if (!fs.existsSync(resolvedFilepath)) { | ||
console.error(`File not found: ${resolvedFilepath}`); | ||
return; | ||
} | ||
const content = fs.readFileSync(filepath, 'utf-8') | ||
|
||
const images = [] | ||
let imageIndex = 1 | ||
|
||
const content = fs.readFileSync(resolvedFilepath, 'utf-8'); | ||
|
||
const images = []; | ||
let imageIndex = 1; | ||
|
||
const replaceURL = (match, extra, url) => { | ||
const isMarkdownBlock = match.startsWith('![') | ||
if (url.startsWith(baseURL)) return match | ||
const isMarkdownBlock = match.startsWith('!['); | ||
if (url.startsWith(baseURL)) return match; // Skip processing for already processed URLs | ||
|
||
if (url.startsWith('//')) { | ||
url = `https:${url}` | ||
url = `https:${url}`; | ||
} | ||
|
||
let newURL = '' | ||
const ext = getExtension(url) | ||
|
||
const newfilepath = `${filepath.split('.')[0]}_${imageIndex}.${ext}` | ||
const ext = getExtension(url); | ||
const parsedPath = path.parse(resolvedFilepath); // Safely parse the path | ||
const newFilepath = parsedPath.dir + '/' + `${parsedPath.name}_${imageIndex}.${ext}`; // Create new file path | ||
|
||
images.push({ | ||
filepath: path.resolve(newfilepath), | ||
url | ||
}) | ||
|
||
newURL = `${baseURL}${filepath.split('.')[0]}_${imageIndex}.${ext}` | ||
imageIndex++ | ||
|
||
return isMarkdownBlock ? `![${extra}](${newURL})` : `<img ${extra}src="${newURL}"` | ||
} | ||
filepath: path.resolve(newFilepath), | ||
url, | ||
}); | ||
|
||
const encodedFilepath = encodeURI(path.relative('.', newFilepath).replace(/\\/g, "/")); | ||
const newURL = `${baseURL}${encodedFilepath}`; | ||
|
||
const newContent = content | ||
imageIndex++; | ||
|
||
return isMarkdownBlock ? `![${extra}](${newURL})` : `<img ${extra}src="${newURL}"`; | ||
}; | ||
|
||
let newContent = content | ||
.replace(/\!\[(.*)\]\((.*)\)/g, replaceURL) | ||
.replace(/<img (.*)src="(.*)"/g, replaceURL) | ||
.replace(/<img (.*)src="(.*)"/g, replaceURL); | ||
|
||
try { | ||
for (let i = 0; i < images.length; i++) { | ||
await imageDownloader.image({ | ||
url: images[i].url, | ||
dest: images[i].filepath | ||
}) | ||
for (const image of images) { | ||
console.log(`Downloading image from: ${image.url} to ${image.filepath}`); | ||
await imageDownloader.image({ | ||
url: image.url, | ||
dest: image.filepath, | ||
}); | ||
|
||
// Check and compress the image if needed | ||
let compressedFilePath = await checkAndCompressImage(image.filepath); | ||
} | ||
|
||
fs.writeFileSync(filepath, newContent) | ||
|
||
fs.writeFileSync(resolvedFilepath, newContent); | ||
console.log(`Updated file: ${resolvedFilepath}`); | ||
} catch (err) { | ||
console.log("Couldn't download some of the images, leaving file as it is...\n\t",filepath) | ||
console.error(`Error updating images for: ${resolvedFilepath}`, err); | ||
} | ||
} | ||
}; | ||
|
||
const filepath = process.argv[2] | ||
updateImages(filepath) | ||
if (require.main === module) { | ||
const filepath = process.argv[2]; // run with this command: node docs-utils/update-images.js "{fullFilePath}" | ||
updateImages(filepath); | ||
} | ||
|
||
module.exports = { updateImages }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file added
BIN
+26.2 MB
...ts/2024-02-07-offer-status-module-for-integrations-with-vtex-marketplaces_1.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 28 additions & 0 deletions
28
...024-10-21-shopping-season-get-your-store-ready-with-our-best-practices-guide.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
--- | ||
title: 'Shopping Season: Get your store ready with our Best Practices Guide' | ||
id: AUjUgR4FNyv5oVyhrSLT2 | ||
status: PUBLISHED | ||
createdAt: 2024-10-21T20:58:45.914Z | ||
updatedAt: 2024-10-21T21:09:41.612Z | ||
publishedAt: 2024-10-21T21:09:41.612Z | ||
contentType: updates | ||
productTeam: Others | ||
author: 2Gy429C47ie3tL9XUEjeFL | ||
slugEN: 2024-10-21-shopping-season-get-your-store-ready-with-our-best-practices-guide | ||
locale: en | ||
legacySlug: shopping-season-get-your-store-ready-with-our-best-practices-guide | ||
announcementImageID: '' | ||
announcementSynopsisEN: "Follow our recommendations and exclusive tips to make the most out of this year's Black Friday." | ||
--- | ||
|
||
__Black Friday__ is coming. Despite its official date (__November 29__), many stores will start their campaigns a lot earlier. To make sure you'll make the most out of one of the main events on the retail calendar, start prepping soon. | ||
|
||
As in previous years, we came up with a guide with recommendations and exclusive tips that will help you ensure your store's health and sales. | ||
|
||
The guide is available to all our clients and partners and may be accessed through the homepage of your Admin or directly through the URL | ||
|
||
``` | ||
https://{accountName}.myvtex.com/admin/shopping-season | ||
``` | ||
|
||
Simply replace `{accountName}` with your store's [account name](https://help.vtex.com/en/tutorial/o-que-e-account-name--i0mIGLcg3QyEy8OCicEoC#). |
Oops, something went wrong.