Skip to content

Commit

Permalink
chore: handle relative images present in articles
Browse files Browse the repository at this point in the history
  • Loading branch information
rafaelcamargo committed Jul 9, 2021
1 parent c8424e5 commit df066c3
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 12 deletions.
Binary file added src/images/varejao.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions src/mocks/images.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
![Adriana Varejão Gallery](../images/varejao.jpeg)

_Adriana Varejão Gallery_

![Valeska Soares Gallery](http://valeskasoares.net/wp-content/uploads/2009/10/DSC8218.jpg)

_Valeska Soares Gallery_

![Sonic Pavillion](https://www.inhotim.org.br/wp-content/webp-express/webp-images/uploads/2021/02/CAPA_02042021DSC07311Joao_Kehl_.jpg.webp)

_Sonic Pavillion_
5 changes: 3 additions & 2 deletions src/services/article.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
const markdownService = require('./markdown');
const assetsService = require('./assets');
const dateService = require('./date');
const domService = require('./dom');
const excerptService = require('./excerpt');
const { fileService } = require('./file');
const markdownService = require('./markdown');
const stylesService = require('./styles');
const summaryService = require('./summary');
const templateService = require('./template');
Expand Down Expand Up @@ -39,7 +40,7 @@ function fillTemplate(template, article, summary){
const $ = parseHTMLString(template.replace('{{article}}', wrapArticle(summary, article)));
$('html').attr('lang', summary.lang);
$('head').append(`<title>${summary.title}</title>`).append(buildMetaTags(summary));
return stylesService.appendBaseStylesheet($.html());
return stylesService.appendBaseStylesheet(assetsService.handleRelativeImages($.html()));
}

function wrapArticle({ title, date, lang }, article){
Expand Down
32 changes: 32 additions & 0 deletions src/services/article.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const path = require('path');
const configService = require('./config');
const { fileService } = require('./file');
const articleService = require('./article');

describe('Articles Service', () => {
function mockTrivenConfig(){
const config = {
sourceDirectory: path.join(__dirname, '../mocks'),
outputDirectory: path.join(process.cwd(), './triven')
};
configService.get = jest.fn(() => config);
return config;
}

beforeEach(() => {
fileService.copySync = jest.fn();
});

it('should copy relative images to assets directory and update its source in markup', () => {
const { outputDirectory } = mockTrivenConfig();
const filepath = path.join(__dirname, '../mocks/images.md');
const { article } = articleService.build(filepath);
const expectedFilename = 'varejao-a8774002d2f7fef27b27f665c7e7227c.jpeg';
expect(article).toContain(`<img src="assets/${expectedFilename}" alt="Adriana Varejão Gallery">`);
expect(fileService.copySync).toHaveBeenCalledTimes(1);
expect(fileService.copySync).toHaveBeenCalledWith(
`${path.join(__dirname, '../images/varejao.jpeg')}`,
`${outputDirectory}/assets/${expectedFilename}`
);
});
});
67 changes: 57 additions & 10 deletions src/services/assets.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
const md5 = require('md5');
const path = require('path');
const domService = require('./dom');
const configService = require('./config');
const minifyService = require('./minify');
const { fileService } = require('./file');
Expand All @@ -7,34 +9,79 @@ const _public = {};

let cache = [];

_public.save = filepath => {
const cachedFilename = findFilenameByFilepath(filepath);
if(cachedFilename) return cachedFilename;
const filename = saveAsset(filepath);
cache.push({ filepath, filename });
return filename;
_public.save = filepath => handle(filepath, () => saveAsset(filepath));

_public.copy = filepath => handle(filepath, () => copyAsset(filepath));

_public.handleRelativeImages = htmlString => {
const $ = domService.parseHTMLString(htmlString);
$('img').filter((index, el) => isRelativeImage($(el).attr('src'))).each((index, el) => {
const filename = _public.copy(buildLocalImageFilepath($(el).attr('src')));
$(el).attr('src', `${getAssetsDirectoryName()}/${filename}`);
});
return $.html();
};

_public.flushCache = () => {
cache = [];
};

function handle(filepath, act){
const cachedFilename = findFilenameByFilepath(filepath);
if(cachedFilename) return cachedFilename;
const filename = act();
cache.push({ filepath, filename });
return filename;
}

function findFilenameByFilepath(filepath){
const cachedItem = cache.find(item => item.filepath === filepath);
return cachedItem && cachedItem.filename;
}

function saveAsset(filepath){
return store(filepath, ({ filename, file }) => {
fileService.write(`${getAssetsDirectoryFilepath()}/${filename}`, file);
});
}

function copyAsset(filepath){
return store(filepath, ({ filename }) => {
fileService.copySync(filepath, `${getAssetsDirectoryFilepath()}/${filename}`);
});
}

function store(filepath, storeAsset){
const { filename, file } = identifyFile(filepath);
storeAsset({ filename, file });
return filename;
}

function identifyFile(filepath){
const { name, extension } = fileService.getFileInfoByFilepath(filepath);
const file = minifyService.minifyByFilepath(filepath);
const filename = `${name}-${md5(file)}.${extension}`;
fileService.write(`${getAssetsDirectory()}/${filename}`, file);
return filename;
return { filename, file };
}

function getAssetsDirectory(){
function getAssetsDirectoryFilepath(){
const { outputDirectory } = configService.get();
return `${outputDirectory}/assets`;
return `${outputDirectory}/${getAssetsDirectoryName()}`;
}

function getAssetsDirectoryName(){
return 'assets';
}

function isRelativeImage(imgSrc){
return !isAbsoluteSrcRegex.test(imgSrc);
}

function buildLocalImageFilepath(imgSrc){
const { sourceDirectory } = configService.get();
return path.join(sourceDirectory, imgSrc);
}

const isAbsoluteSrcRegex = new RegExp(/^https?:\/\/.+/);

module.exports = _public;

0 comments on commit df066c3

Please sign in to comment.