Skip to content

Commit

Permalink
Merge pull request hexojs#3681 from curbengh/sri
Browse files Browse the repository at this point in the history
feat(js_helper): add support for custom attributes
  • Loading branch information
curbengh authored Nov 2, 2019
2 parents 47433cb + 16cdafd commit 19ac04c
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 16 deletions.
47 changes: 40 additions & 7 deletions lib/plugins/helper/js.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,48 @@
'use strict';

const { htmlTag } = require('hexo-util');
const url_for = require('./url_for');

/* flatten() to be replaced by Array.flat()
after Node 10 has reached EOL */
const flatten = function(arr, result = []) {
for (const i in arr) {
const value = arr[i];
if (Array.isArray(value)) {
flatten(value, result);
} else {
result.push(value);
}
}
return result;
};

function jsHelper(...args) {
return args.reduce((result, path, i) => {
if (i) result += '\n';
let result = '\n';
let items = args;

if (!Array.isArray(args)) {
items = [args];
}

items = flatten(items);

if (Array.isArray(path)) {
return result + Reflect.apply(jsHelper, this, path);
items.forEach(item => {
// Old syntax
if (typeof item === 'string' || item instanceof String) {
let path = item;
if (!path.endsWith('.js')) {
path += '.js';
}
result += `<script src="${this.url_for(path)}"></script>\n`;
} else {
// New syntax
item.src = url_for.call(this, item.src);
if (!item.src.endsWith('.js')) item.src += '.js';
result += htmlTag('script', { ...item }, '') + '\n';
}
if (!path.includes('?') && !path.endsWith('.js')) path += '.js';
return `${result}<script src="${this.url_for(path)}"></script>`;
}, '');
});
return result;
}

module.exports = jsHelper;
55 changes: 46 additions & 9 deletions test/scripts/helpers/js.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use strict';

const cheerio = require('cheerio');

describe('js', () => {
const Hexo = require('../../../lib/hexo');
const hexo = new Hexo(__dirname);
Expand All @@ -12,14 +14,26 @@ describe('js', () => {

const js = require('../../../lib/plugins/helper/js').bind(ctx);

function assertResult(result) {
let expected = '';
function assertResult(result, expected) {
const $ = cheerio.load(result);

for (let i = 1, len = arguments.length; i < len; i++) {
expected += '<script src="' + arguments[i] + '"></script>\n';
if (!Array.isArray(expected)) {
expected = [expected];
}

result.should.eql(expected.trim());
expected.forEach((item, index) => {
if (typeof item === 'string' || item instanceof String) {
$('script').eq(index).attr('src').should.eql(item);
} else {
for (const attribute in item) {
if (item[attribute] === true) {
$('script').eq(index).attr(attribute).should.eql(attribute);
} else {
$('script').eq(index).attr(attribute).should.eql(item[attribute]);
}
}
}
});
}

it('a string', () => {
Expand All @@ -30,18 +44,41 @@ describe('js', () => {
});

it('an array', () => {
assertResult(js(['foo', 'bar', 'baz']), '/foo.js', '/bar.js', '/baz.js');
assertResult(js(['foo', 'bar', 'baz']), ['/foo.js', '/bar.js', '/baz.js']);
});

it('multiple strings', () => {
assertResult(js('foo', 'bar', 'baz'), '/foo.js', '/bar.js', '/baz.js');
assertResult(js('foo', 'bar', 'baz'), ['/foo.js', '/bar.js', '/baz.js']);
});

it('multiple arrays', () => {
assertResult(js(['foo', 'bar'], ['baz']), '/foo.js', '/bar.js', '/baz.js');
assertResult(js(['foo', 'bar'], ['baz']), ['/foo.js', '/bar.js', '/baz.js']);
});

it('mixed', () => {
assertResult(js(['foo', 'bar'], 'baz'), '/foo.js', '/bar.js', '/baz.js');
assertResult(js(['foo', 'bar'], 'baz'), ['/foo.js', '/bar.js', '/baz.js']);
});

it('an object', () => {
assertResult(js({src: 'script.js'}), {src: '/script.js'});
assertResult(js({src: '/script.js'}), {src: '/script.js'});
assertResult(js({src: '/script.js', foo: 'bar'}), {src: '/script.js', foo: 'bar'});
});

it('mulitple objects', () => {
assertResult(js({src: '/foo.js'}, {src: '/bar.js'}), [{src: '/foo.js'}, {src: '/bar.js'}]);
assertResult(js({src: '/aaa.js', bbb: 'ccc'}, {src: '/ddd.js', eee: 'fff'}),
[{src: '/aaa.js', bbb: 'ccc'}, {src: '/ddd.js', eee: 'fff'}]);
});

it('an array of objects', () => {
assertResult(js([{src: '/foo.js'}, {src: '/bar.js'}]), [{src: '/foo.js'}, {src: '/bar.js'}]);
assertResult(js([{src: '/aaa.js', bbb: 'ccc'}, {src: '/ddd.js', eee: 'fff'}]),
[{src: '/aaa.js', bbb: 'ccc'}, {src: '/ddd.js', eee: 'fff'}]);
});

it('async and defer attributes', () => {
assertResult(js({src: '/foo.js', 'async': true}), {src: '/foo.js', 'async': true});
assertResult(js({src: '/bar.js', 'defer': true}), {src: '/bar.js', 'defer': true});
});
});

0 comments on commit 19ac04c

Please sign in to comment.