diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..d8a3c25 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,8 @@ +language: node_js +node_js: +- 14 +cache: + directories: + - node_modules +script: +- npm test \ No newline at end of file diff --git a/lib/cleanseStyles.js b/lib/cleanseStyles.js new file mode 100644 index 0000000..70b0fc9 --- /dev/null +++ b/lib/cleanseStyles.js @@ -0,0 +1,108 @@ +var fs = require('fs') + +//finds used classes in the html files and adds them to a class list +function createClassList(htmlFile, classes){ + return new Promise((resolve, reject) => { + if(htmlFile.includes("class=")){ + let htmlArr = htmlFile.split("class=") + for(let i=1; i<=htmlArr.length; i++){ + let delim = `"` + if(htmlArr[i].startsWith(`'`)) delim = `'` + if(htmlArr[i].substr(1,1) !== htmlArr[i].substr(0,1)){ + let classesStr = htmlArr[i].split(delim)[1] + if(!classesStr) console.log('Error. invalid class ' + htmlArr[i]) + let classesArr = classesStr.split(" ") + for(let c of classesArr){ + //console.log('Class class ', c) + if(!classes[c]) classes[c] = true + } + } + if(i >= htmlArr.length-1) resolve(classes) + } + } + else resolve(classes) + }) +} + +//for all of the stylesheets it will parse classes and see if the class is present in the html. if not it will dlete the class from the stylesheet +function deleteUnusedCss(stylesheets, classes){ + console.log('CLASSES \n', classes) + return new Promise((resolve, reject) => { + for(let sheet of stylesheets){ + let stylesheet = fs.readFileSync(sheet, 'utf8') + let styles = stylesheet.split("}") + let i = 0; + for(let style of styles){ + let classLine = style.split("{")[0] + let classInstance = style+'}' + if(classLine.includes(",")){ + console.log('Multi class item') + /* let newsheet = stylesheet + let classLineItems = classLine.split(",") + let items = 0; + let toDel = 0; + for(let item of classLineItems) { + findClasses(sheet, item, classes, (err, data) => { + if(err) throw new Error(err) + else{ + items+=1 + if(data) { + newsheet = stylesheet.replace(item, "") + toDel += 1 + } + } + }) + } + if(items === toDel) { + //console.log("deleteing ", classInstance) + stylesheet = stylesheet.replace(classInstance, "") + } + else stylesheet = newsheet */ + //console.log(classLine) + } + else { + findClasses(sheet, classLine, classes, (err, data) => { + if(err) reject(err) + else{ + if(data){ + //console.log('CLASS INSTANCE ', classInstance) + stylesheet = stylesheet.replace(classInstance, "") + //console.log('deleted class ', data) + } + } + }) + } + i+=1 + } + let elems = styles.length -1 + let outputPath = 'output/' + sheet.split("input/", 2)[1] + //console.log(stylesheet) + if(i >= elems) fs.promises.writeFile(outputPath, stylesheet).then(()=> resolve(true)).catch((err) => reject(err)) + } + }) +} + +//splits a class line item into classes sepparated by dots +function findClasses(stylesheet, classLine, classes, callback){ + let classArr = classLine.trim().split(" ") + //console.log('STYLESHEET', stylesheet, classArr) + c = classArr[0].replace('\n',"").trim() + //console.log('CLASS ', c) + //console.log(c) + if(c.includes(".")){ + inst = c.substr(1, c.length) + //console.log('INST ', inst) + if(!classes[inst]) { + //console.log(inst) + callback(null, inst) + } + } + callback(null, null) +} + + +module.exports = { + createClassList, + deleteUnusedCss, + findClasses +} \ No newline at end of file diff --git a/lib/replaceWebp.js b/lib/replaceWebp.js new file mode 100644 index 0000000..238bde6 --- /dev/null +++ b/lib/replaceWebp.js @@ -0,0 +1,26 @@ +module.exports = function replaceWebp(images, html){ + return new Promise((resolve, reject) => { + let html2 = html + for(let i in images){ + let imgPath = images[i] + if(imgPath.endsWith('jpg')||imgPath.endsWith('jpeg')||imgPath.endsWith('png')){ + if(html.includes(`src="${imgPath}"`)){ + let splife = html.split(`src="${imgPath}"`); + let img_tag_bgn = splife[0].substr(splife[0].lastIndexOf('<')); + let img_tag_end = splife[1].substr(0, splife[1].indexOf('>')+1); + let img_tag = img_tag_bgn + `src="${imgPath}"` + img_tag_end; + let subPath = imgPath.substr(0, imgPath.lastIndexOf('.')); + let ext = imgPath.substr(imgPath.lastIndexOf('.')+1); + //let classes = ""; + //let alt = ""; + let webp_img = subPath + '.webp'; + let webp_tag = `` + //console.log("\x1b[31m", img_tag, '\n', webp_tag, "\x1b[0m") + html2 = html2.replace(img_tag, webp_tag) + } + } + if(i>=images.length-1)resolve(html2) + } + }) +} + diff --git a/lib/webp.js b/lib/webp.js deleted file mode 100644 index 4b59cb6..0000000 --- a/lib/webp.js +++ /dev/null @@ -1,55 +0,0 @@ -const sharp = require('sharp'); -var fs = require('fs') - -function compress(filePath, output){ - return new Promise((resolve, reject) => { - //let fileExtension = file.split(".")[1] - let fileSubPath = filePath.split(".")[0]; - sharp(filePath) - .webp({nearLossless: true, force: true}) - .toFile(`${output}/${fileSubPath}.webp`) - .then( data => { - //console.log(`Converted ${file} to webp`) - //console.log(`compressed your ${fileExtension} image and saved as webp`) - //console.log(data) - resolve(data.size) - }) - .catch(err => reject(err)); - }) -} - -function replace(imgPath, html){ - //scan the html file and find all instances of the image - return new Promise((resolve, reject) => { - //console.log("\x1b[33m", img, "\x1b[0m") - if(html.includes(`src="${imgPath}"`)){ - let splife = html.split(`src="${imgPath}"`); - let img_tag_bgn = splife[0].substr(splife[0].lastIndexOf('<')); - let img_tag_end = splife[1].substr(0, splife[1].indexOf('>')+1); - let img_tag = img_tag_bgn + `src="${imgPath}"` + img_tag_end; - let subPath = img.substr(0, img.lastIndexOf('.')); - let ext = img.substr(img.lastIndexOf('.')); - //let classes = ""; - //let alt = ""; - let webp_img = subPath + '.webp'; - let webp_tag = - `` - //console.log("\x1b[31m", img_tag, '\n', webp_tag, "\x1b[0m") - let html2 = html.replace(img_tag, webp_tag) - resolve(html2) - } - else { - //console.log(`image ${img} isnt used in the file ${filePath}`) - resolve(html) - } - }) -} - -module.exports = { - compress, - replace -} diff --git a/test/replaceWebpTest.js b/test/replaceWebpTest.js new file mode 100644 index 0000000..af9a7b3 --- /dev/null +++ b/test/replaceWebpTest.js @@ -0,0 +1,62 @@ +var assert = require('assert'); +const replaceWebp = require('../lib/replaceWebp') + +const html = +` + +
+ + + + +` + +const expected_html = +` + + + + + + +` + +const img_path = "img/test_image.jpeg" +const image = '' +const picture = `` + + +describe('replace pictures', function () { + describe('compare expected picture for an img', function () { + it('should match the expected html', async function () { + let response = await replaceWebp([img_path], image) + assert.equal(response, picture) + }); + }); + describe('compare expected html with picture', function () { + it('should match the expected html', async function () { + let response = await replaceWebp([img_path], html) + assert.equal(response, expected_html) + }); + }); +}); \ No newline at end of file