Skip to content

Commit

Permalink
thing
Browse files Browse the repository at this point in the history
Signed-off-by: ClaytonTDM <[email protected]>
  • Loading branch information
ClaytonTDM committed Oct 8, 2024
1 parent f4d2676 commit 0fbbd2f
Show file tree
Hide file tree
Showing 3 changed files with 248 additions and 1 deletion.
44 changes: 44 additions & 0 deletions .github/workflows/gifToWebp.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: GIF to WebP Conversion

on:
push:
branches:
- main # or your default branch name

jobs:
convert-and-commit:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18'

- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y imagemagick
sudo apt-get install -y webp
curl -L https://github.com/ImageOptim/gifski/releases/download/1.11.0/gifski_1.11.0_amd64.deb -o gifski.deb
sudo dpkg -i gifski.deb
- name: Run conversion script
run: |
node gif-to-webp-converter.js
- name: Commit changes
run: |
git config --local user.email "[email protected]"
git config --local user.name "GitHub Action"
git add -A
git diff --quiet && git diff --staged --quiet || git commit -m "Convert GIF files to WebP"
- name: Push changes
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: ${{ github.ref }}
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
convert.js
ffmpeg*
node_modules/
package.json
Expand Down
204 changes: 204 additions & 0 deletions convert.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
const fs = require("fs").promises;
const path = require("path");
const { execFile } = require("child_process");
const util = require("util");
const execFilePromise = util.promisify(execFile);

const gifskiPath = "gifski";
const convertPath = "convert";
const identifyPath = "identify";

const textFileExtensions = [
".txt",
".md",
".json",
".xml",
".html",
".htm",
".css",
".js",
".ts",
".jsx",
".tsx",
".vue",
".php",
".py",
".rb",
".java",
".c",
".cpp",
".h",
".cs",
".go",
".rs",
".swift",
".kt",
".kts",
".scala",
".sh",
".bash",
".yaml",
".yml",
".toml",
".ini",
".cfg",
".conf",
];

async function isAnimatedGif(filePath) {
try {
const { stdout } = await execFilePromise("identify", [
"-format",
"%n\n",
filePath,
]);
const frameCount = parseInt(stdout.trim(), 10);
return frameCount > 1;
} catch (error) {
console.error(`Error checking if GIF is animated: ${error.message}`);
return false;
}
}

async function getGifLoopCount(filePath) {
try {
const { stdout } = await execFilePromise(identifyPath, [
"-format",
"%L",
filePath,
]);
const loopCount = parseInt(stdout.trim(), 10);
return isNaN(loopCount) ? 0 : loopCount;
} catch (error) {
console.error(`Error getting GIF loop count: ${error.message}`);
return 0;
}
}

async function convertGifToWebp(inputPath, outputPath) {
try {
const animated = await isAnimatedGif(inputPath);
if (animated) {
const loopCount = await getGifLoopCount(inputPath);
const loopArg =
loopCount === 0 ? "--repeat=0" : `--repeat=${loopCount - 1}`;
await execFilePromise(gifskiPath, [
"--quality=100",
loopArg,
"--output",
outputPath,
inputPath,
]);
} else {
await execFilePromise(convertPath, [
inputPath,
"-define",
"webp:lossless=true",
outputPath,
]);
}
console.log(`Converted ${inputPath} to ${outputPath}`);
return true;
} catch (error) {
console.error(`Error converting ${inputPath}: ${error.message}`);
if (error.code === "ENOENT") {
console.error(
"The required executable was not found. Please make sure gifski and ImageMagick are installed and the paths are correct."
);
}
return false;
}
}

async function isTextFile(filePath) {
const ext = path.extname(filePath).toLowerCase();
if (textFileExtensions.includes(ext)) {
return true;
}

try {
const buffer = await fs.readFile(filePath);
const fileString = buffer.toString("utf8", 0, 1000); // Read first 1000 bytes
return /^[\x20-\x7E\r\n]*$/.test(fileString);
} catch (error) {
console.error(`Error checking if file is text: ${error.message}`);
return false;
}
}

async function replaceInFile(filePath, replacements) {
try {
if (await isTextFile(filePath)) {
let data = await fs.readFile(filePath, "utf8");
let changed = false;
for (const { oldName, newName } of replacements) {
const regex = new RegExp(oldName, "g");
const newData = data.replace(regex, newName);
if (newData !== data) {
data = newData;
changed = true;
}
}
if (changed) {
await fs.writeFile(filePath, data, "utf8");
console.log(`Updated references in ${filePath}`);
}
}
} catch (error) {
console.error(`Error updating ${filePath}: ${error.message}`);
}
}

async function processDirectory(directoryPath, allConvertedFiles = []) {
try {
const entries = await fs.readdir(directoryPath, {
withFileTypes: true,
});
const convertedFiles = [];

for (const entry of entries) {
const fullPath = path.join(directoryPath, entry.name);

if (entry.isDirectory()) {
await processDirectory(fullPath, allConvertedFiles);
} else if (entry.isFile()) {
if (path.extname(entry.name).toLowerCase() === ".gif") {
const outputPath = path.join(
path.dirname(fullPath),
`${path.basename(fullPath, ".gif")}.webp`
);
const success = await convertGifToWebp(
fullPath,
outputPath
);
if (success) {
convertedFiles.push({
oldName: entry.name,
newName: path.basename(outputPath),
});
}
} else {
await replaceInFile(fullPath, allConvertedFiles);
}
}
}

allConvertedFiles.push(...convertedFiles);

return allConvertedFiles;
} catch (error) {
console.error(
`Error processing directory ${directoryPath}: ${error.message}`
);
return allConvertedFiles;
}
}

async function main() {
const rootDirectory = ".";
console.log(`Starting conversion process in ${rootDirectory}`);
await processDirectory(rootDirectory);
console.log("Conversion process completed");
}

main().catch((error) => console.error("An error occurred:", error));

0 comments on commit 0fbbd2f

Please sign in to comment.