Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow srcset attribute paths of images to be fixed #50

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 45 additions & 26 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ function loadResources(locale, options) {
const file = path.join(options.localesPath, options.localeFile).replace('__lng__', locale);
const extension = path.extname(file);
return fs.readFile(file, options.encoding)
.then(data => parseTranslations(extension, data, options.localeRootKey, locale));
.then(data => parseTranslations(extension, data, options.localeRootKey, locale));
}

function getOptions(baseOptions) {
Expand Down Expand Up @@ -122,9 +122,9 @@ function getRawOutputFile(file, locale, options) {
function getOutput(file, locale, options, absolute) {
const output = getRawOutputFile(file, locale, options);
const outputFile = output
.replace('__lng__', locale)
.replace('__file__', file)
.replace('__basename__', path.basename(file, path.extname(file)));
.replace('__lng__', locale)
.replace('__file__', file)
.replace('__basename__', path.basename(file, path.extname(file)));
if (absolute !== false) {
const outdir = _.isString(options.outputDir) ? options.outputDir : options.baseDir;
return path.join(outdir, outputFile);
Expand Down Expand Up @@ -230,17 +230,36 @@ function fixHTMLPaths($, locale, options) {
return _.each({
'audio[src]': 'src',
'img[src]': 'src',
'img[srcset]': 'srcset',
'link[href]': 'href',
'script[src]': 'src',
'source[src]': 'src',
'source[srcset]': 'srcset',
'video[src]': 'src'
}, function(v, k) {
return $(k).each(function() {
const src = $(this).attr(v);
if (!(src[0] === '/' || absolutePathRegex.test(src))) {
const filepath = getPath(src, locale, options);
return $(this).attr(v, filepath);

const paths =
src.split(',')
.map((aSrc) => aSrc.trim())
.map(aSrc => {
if (!(aSrc[0] === '/' || absolutePathRegex.test(aSrc))) {
return getPath(aSrc, locale, options);
} else {
return aSrc;
}
});

let pathsFormatted;
if (paths && paths.length > 1) {
pathsFormatted = paths.reduce((acc, aSrc) => {
return `${acc}, ${aSrc}`;
});
} else {
pathsFormatted = paths[0];
}
$(this).attr(v, pathsFormatted);
});
});
}
Expand All @@ -255,7 +274,7 @@ function fixCSSPaths($, locale, options) {

if(style.match(urlRegEx)) {
const finalString = style.replace(urlRegEx, function (curr, src) {
if (!(src[0] === '/' || absolutePathRegex.test(src))) {
if (!(src[0] === '/' || src[0] === '#' || absolutePathRegex.test(src))) {
return "url('"+ getPath(src, locale, options) + "')";
} else {
return curr;
Expand Down Expand Up @@ -352,14 +371,14 @@ exports.processFile = function(file, options) {
options = getOptions(options);
options.file = options.file || file;
return fs.readFile(file, options.encoding)
.then((html) => exports.process(html, options))
.then((results) => {
if (options.outputDir) {
return outputFile(file, options, results);
} else {
return results;
}
});
.then((html) => exports.process(html, options))
.then((results) => {
if (options.outputDir) {
return outputFile(file, options, results);
} else {
return results;
}
});
};

function shouldExcludeFile(file, options) {
Expand All @@ -379,15 +398,15 @@ exports.processDir = function(dir, options) {
}
const pattern = options.files || defaults.files;
return promisify(glob)(path.join(dir, pattern))
.then((files) => _.reject(files, (f) => shouldExcludeFile(f, options)))
.mapSeries((file) =>
exports.processFile(file, options).then((r) => [file, r])
)
.then((results) => {
return _(results)
.fromPairs()
.mapKeys((_v, f) => path.relative(dir, f))
.value();
});
.then((files) => _.reject(files, (f) => shouldExcludeFile(f, options)))
.mapSeries((file) =>
exports.processFile(file, options).then((r) => [file, r])
)
.then((results) => {
return _(results)
.fromPairs()
.mapKeys((_v, f) => path.relative(dir, f))
.value();
});
};

68 changes: 49 additions & 19 deletions test/data/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,32 +15,62 @@
<link id="rel-link" rel="stylesheet" href="foo.css">
</head>
<body>
<img id="abs-img" src="//foo.png" />
<img id="rel-img" src="foo.png" />

<audio id="abs-audio" src="//foo.mp3"></audio>
<audio id="rel-audio" src="foo.mp3"></audio>
<img id="abs-img" src="//foo.png" srcset="//foo-mobile.png 640w, //foo-tablet.png 768w, //foo.png 1024w" />
<img id="rel-img" src="foo.png" srcset="foo-mobile.png 640w, foo-tablet.png 768w, foo.png 1024w" />

<video id="abs-video" src="//foo.mp4"></video>
<video id="rel-video" src="foo.mp4"></video>
<img id="abs-img-single-srcset" src="//foo.png" srcset="//foo-mobile.png" />
<img id="rel-img-single-srcset" src="foo.png" srcset="foo-mobile.png" />

<picture>
<source id="abs-source" src="//foo.jpg"></source>
<source id="rel-source" src="foo.jpg"></source>
</picture>
<audio id="abs-audio" src="//foo.mp3"></audio>
<audio id="rel-audio" src="foo.mp3"></audio>

<div id="abs-style" style="background-image: url(//bg.jpg); background: url('//bg.jpg')"></div>
<div id="rel-style" style="background-image: url(bg.jpg); background: url('bg.jpg')"></div>
<video id="abs-video" src="//foo.mp4"></video>
<video id="rel-video" src="foo.mp4"></video>

<!--[if lt IE 9]>
<p class="browsehappy" data-t>browsehappy</p>
<![endif]-->
<picture>
<source id="abs-source-src" src="//foo.jpg"></source>
<source id="rel-source-src" src="foo.jpg"></source>
</picture>

<h1 id="bar" data-t="foo.bar"></h1>
<h1 id="baz" data-t>foo.baz</h1>
<picture>
<source id="abs-source-single-srcset" srcset="//foo.jpg"></source>
<source id="rel-source-single-srcset" srcset="foo.jpg"></source>
</picture>

<h1 id="bar-replace"><span data-t>foo.bar</span></h1>
<picture>
<source id="abs-source-srcset" srcset="//foo-mobile.png 640w, //foo-tablet.png 768w, //foo.png 1024w"></source>
<source id="rel-source-srcset" srcset="foo-mobile.png 640w, foo-tablet.png 768w, foo.png 1024w"></source>
</picture>

<div id="abs-style" style="background-image: url(//bg.jpg); background: url('//bg.jpg')"></div>
<div id="rel-style" style="background-image: url(bg.jpg); background: url('bg.jpg')"></div>

<!--[if lt IE 9]>
<p class="browsehappy" data-t>browsehappy</p>
<![endif]-->

<h1 id="bar" data-t="foo.bar"></h1>
<h1 id="baz" data-t>foo.baz</h1>

<h1 id="bar-replace"><span data-t>foo.bar</span></h1>

<h1 id="bar-replace-sel"><t>foo.bar</t></h1>

<svg width="200" height="200">
<path d="M10 10"/>
<defs>
<path id="anId" d="M0,8c0,4.42,3.58,8,8,8c4.42,0,8-3.58,8-8s-3.58-8-8-8C3.58,0,0,3.58,0,8"/>
</defs>
<clipPath id="clip-path-url-id">
<use xlink:href="#anId" style="overflow:visible;"/>
</clipPath>
<linearGradient id="linear-gradient-id" gradientUnits="userSpaceOnUse" x1="2958.5095" y1="627.3567" x2="2958.8643" y2="627.3567" gradientTransform="matrix(0 -45.0926 -45.0926 0 28297.168 133423)">
<stop offset="0" style="stop-color:#0087C9"/>
<stop offset="1" style="stop-color:#05A5DB"/>
</linearGradient>
<rect id="svg-urls" x="0" style="clip-path:url(#clip-path-url-id);fill:url(#linear-gradient-id);" width="16" height="16"/>
</svg>

<h1 id="bar-replace-sel"><t>foo.bar</t></h1>
</body>
</html>
56 changes: 39 additions & 17 deletions test/index-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ describe('processor', function () {

it('should translate attributes include "t"', async function () {
const img =
'<img src="example.png" class="foo" id="ok" data-attr-t alt-t="foo.bar" tool-tip-t="foo.bar">';
'<img src="example.png" class="foo" id="ok" data-attr-t alt-t="foo.bar" tool-tip-t="foo.bar">';
const results = await staticI18n.process(img, options);
const $ = cheerio.load(results.en);
expect(results).to.only.have.keys(['en']);
Expand All @@ -61,16 +61,16 @@ describe('processor', function () {
it('should translate attributes with interpolation', async function () {
options = _.merge({}, options, { locales: ['en', 'ja'] });
const input =
'<input data-attr-t data-attr-t-interpolate href-t="{{links.baseAbsolute}}filename.{{links.extension}}">';
'<input data-attr-t data-attr-t-interpolate href-t="{{links.baseAbsolute}}filename.{{links.extension}}">';
const results = await staticI18n.process(input, options);
let $ = cheerio.load(results.en);
expect($('input').attr('href')).to.be(
'http://www.example.com/filename.html'
'http://www.example.com/filename.html'
);
expect($('input').attr('data-attr-t-interpolate')).to.be(undefined);
$ = cheerio.load(results.ja);
expect($('input').attr('href')).to.be(
'http://www.example.com/ja/filename.htm'
'http://www.example.com/ja/filename.htm'
);
expect($('input').attr('data-attr-t-interpolate')).to.be(undefined);
});
Expand All @@ -79,7 +79,7 @@ describe('processor', function () {
options = _.merge({}, options, { locales: ['en'] });

const input =
'<p data-t data-t-interpolate>texto aqui<div>Whatever here</div></p>';
'<p data-t data-t-interpolate>texto aqui<div>Whatever here</div></p>';
const results = await staticI18n.process(input, options);
const $ = cheerio.load(results.en);
expect($('p').attr('data-t-interpolate')).to.be(undefined);
Expand Down Expand Up @@ -186,18 +186,18 @@ describe('processor', function () {
await staticI18n.processDir(basepath, options);
let files = await fs.readdir(dir);
_.each(['index.html', 'other.html', 'ja', 'sub'], (f) =>
expect(files).to.contain(f)
expect(files).to.contain(f)
);
files = await fs.readdir(path.join(dir, 'ja'));
_.each(['index.html', 'other.html', 'sub'], (f) =>
expect(files).to.contain(f)
expect(files).to.contain(f)
);
let $ = cheerio.load(
await fs.readFile(path.join(dir, 'index.html'), 'utf8')
await fs.readFile(path.join(dir, 'index.html'), 'utf8')
);
expect($('#bar').text()).to.be('bar');
$ = cheerio.load(
await fs.readFile(path.join(dir, 'sub', 'index.html'), 'utf8')
await fs.readFile(path.join(dir, 'sub', 'index.html'), 'utf8')
);
expect($('#bar').text()).to.be('bar');
});
Expand All @@ -209,50 +209,72 @@ describe('processor', function () {
await staticI18n.processDir(basepath, options);
const files = fs.readdirSync(dir);
_.each(['foo.html', 'other.html', 'ja'], (f) =>
expect(files).to.contain(f)
expect(files).to.contain(f)
);
expect(files).to.not.contain('index.html');
});

it('should fix paths', async function () {
await staticI18n.processDir(basepath, options);
let $ = cheerio.load(
await fs.readFile(path.join(dir, 'ja', 'index.html'), 'utf8')
await fs.readFile(path.join(dir, 'ja', 'index.html'), 'utf8')
);

expect($('#rel-script').attr('src')).to.be('../foo.js');
expect($('#abs-script').attr('src')).to.be('//foo.js');

expect($('#rel-link').attr('href')).to.be('../foo.css');
expect($('#abs-link').attr('href')).to.be('//foo.css');

expect($('#rel-img').attr('src')).to.be('../foo.png');
expect($('#rel-img').attr('srcset')).to.be('../foo-mobile.png 640w, ../foo-tablet.png 768w, ../foo.png 1024w');
expect($('#abs-img').attr('src')).to.be('//foo.png');
expect($('#abs-img').attr('srcset')).to.be('//foo-mobile.png 640w, //foo-tablet.png 768w, //foo.png 1024w');

expect($('#rel-img-single-srcset').attr('src')).to.be('../foo.png');
expect($('#rel-img-single-srcset').attr('srcset')).to.be('../foo-mobile.png');
expect($('#abs-img-single-srcset').attr('src')).to.be('//foo.png');
expect($('#abs-img-single-srcset').attr('srcset')).to.be('//foo-mobile.png');

expect($('#rel-audio').attr('src')).to.be('../foo.mp3');
expect($('#abs-audio').attr('src')).to.be('//foo.mp3');

expect($('#rel-video').attr('src')).to.be('../foo.mp4');
expect($('#abs-video').attr('src')).to.be('//foo.mp4');

expect($('#rel-source').attr('src')).to.be('../foo.jpg');
expect($('#abs-source').attr('src')).to.be('//foo.jpg');
expect($('#rel-source-src').attr('src')).to.be('../foo.jpg');
expect($('#abs-source-src').attr('src')).to.be('//foo.jpg');

expect($('#rel-source-single-srcset').attr('srcset')).to.be('../foo.jpg');
expect($('#abs-source-single-srcset').attr('srcset')).to.be('//foo.jpg');

expect($('#rel-source-srcset').attr('srcset')).to.be('../foo-mobile.png 640w, ../foo-tablet.png 768w, ../foo.png 1024w');
expect($('#abs-source-srcset').attr('srcset')).to.be('//foo-mobile.png 640w, //foo-tablet.png 768w, //foo.png 1024w');

expect($('#rel-style').attr('style')).to.be(
"background-image: url('../bg.jpg'); background: url('../bg.jpg')"
"background-image: url('../bg.jpg'); background: url('../bg.jpg')"
);
expect($('#abs-style').attr('style')).to.be(
"background-image: url(//bg.jpg); background: url('//bg.jpg')"
"background-image: url(//bg.jpg); background: url('//bg.jpg')"
);
expect($('#svg-urls').attr('style')).to.be(
"clip-path:url(#clip-path-url-id);fill:url(#linear-gradient-id);"
);

$ = cheerio.load(fs.readFileSync(path.join(dir, 'index.html'), 'utf8'));
expect($('#rel-script').attr('src')).to.be('foo.js');
expect($('#rel-link').attr('href')).to.be('foo.css');
expect($('#rel-img').attr('src')).to.be('foo.png');
expect($('#rel-img-single-srcset').attr('src')).to.be('foo.png');
expect($('#rel-img').attr('srcset')).to.be('foo-mobile.png 640w, foo-tablet.png 768w, foo.png 1024w');
expect($('#rel-img-single-srcset').attr('srcset')).to.be('foo-mobile.png');
expect($('#rel-audio').attr('src')).to.be('foo.mp3');
expect($('#rel-video').attr('src')).to.be('foo.mp4');
expect($('#rel-source').attr('src')).to.be('foo.jpg');
expect($('#rel-source-src').attr('src')).to.be('foo.jpg');
expect($('#rel-source-single-srcset').attr('srcset')).to.be('foo.jpg');
expect($('#rel-source-srcset').attr('srcset')).to.be('foo-mobile.png 640w, foo-tablet.png 768w, foo.png 1024w');
expect($('#rel-style').attr('style')).to.be(
"background-image: url('bg.jpg'); background: url('bg.jpg')"
"background-image: url('bg.jpg'); background: url('bg.jpg')"
);
});
});
Expand Down