зеркало из
1
0
Форкнуть 0

feat(build): scan emails for invalid style attributes

adds a grunt task to generate the emails and check the style attributes
This commit is contained in:
Sai Pc 2015-07-27 15:54:12 -07:00 коммит произвёл Shane Tomlinson
Родитель 8c62233812
Коммит b14b59f00b
5 изменённых файлов: 216 добавлений и 0 удалений

2
.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,2 @@
node_modules
.tmp

18
Gruntfile.js Normal file
Просмотреть файл

@ -0,0 +1,18 @@
#!/usr/bin/env node
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
module.exports = function (grunt) {
// load all grunt tasks based on environment
// show elapsed time at the end
require('time-grunt')(grunt);
require('load-grunt-tasks')(grunt);
grunt.initConfig({
pkg: grunt.file.readJSON('package.json')
});
grunt.loadTasks('grunttasks');
};

74
grunttasks/po2json.js Normal file
Просмотреть файл

@ -0,0 +1,74 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// grunt task to create .json files out of .po files.
// .po files are expected to already be downloaded.
var path = require('path');
var i18n = require('i18n-abide');
module.exports = function (grunt) {
grunt.config('po2json', {
options: {
format: 'raw',
fuzzy: true,
output_filename: function (file) { //eslint-disable-line camelcase
/**
* the files are stored in the locale subdirectory with a directory
* structure of:
* locale/
* <locale_name>/
* LC_MESSAGES/
* server.po
* client.po
*
* Each locale is stored in its own subdirectory in the output i18n
* directory.
**/
var matches = /^locale\/([^\/]+)\/LC_MESSAGES\/(.*)$/.exec(file);
// In order to make sure the locale is in a form that i18n-abide expects
// we convert it from locale to langauge back to locale.
var locale = i18n.normalizeLocale(matches[1]);
var filename = matches[2];
if (filename === 'server.po') {
filename = 'messages.json';
} else {
// get rid of the .po extension, replace with .json
filename = path.basename(filename, '.po') + '.json';
}
return locale + '/' + filename;
},
output_transform: function (data) { //eslint-disable-line camelcase
// write the first translation only, ignore pluralization.
var isArray = function (item) {
return Object.prototype.toString.call(item) === '[object Array]';
};
var transformed = {};
for (var msgid in data) {
var translation = data[msgid];
if (isArray(translation) && translation.length >= 2) {
translation = translation[1];
}
transformed[msgid] = translation;
}
return transformed;
}
},
all: {
src: ['locale/**/**/*.po'],
dest: '.tmp/l10n/'
},
template: {
src: ['locale/templates/**/*.pot'],
dest: '.tmp/l10n'
}
});
};

Просмотреть файл

@ -0,0 +1,115 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
module.exports = function (grunt) {
grunt.registerTask('scan-email-translations', 'Scan the generated emails for invalid style tags', [
'generate-valid-styles',
'po2json',
'verify-styles'
]
);
grunt.registerMultiTask('verify-styles', 'Verify whether the translated styles are valid', function (){
var options = this.options({
validStyles: []
});
var styleArray = options.validStyles;
var fileArray = this.files[0].src;
var hasErrors = 0;
var styleRegex = /style="[\S\s]*?"/ig;
fileArray.forEach(function (src) {
var json = grunt.file.readJSON(src);
var styleList = [];
for(var key in json) {
if(key.indexOf('style') > 0) {
styleList.push(key);
}
}
// Check if there were any styles found, .match() might return null
if (styleList !== null) {
styleList = styleList.map(stripSpecialChars);
// retrieve the style attribute and its contents and store
styleList = styleList.map(function (str) {
if (styleRegex.test(str)) {
str = str.match(styleRegex)[0];
return str;
}
});
styleList.forEach(function (style) {
if(style !== undefined){
if (styleArray.indexOf(style) === -1) {
grunt.log.error('Found a style which should not be there', style, src);
hasErrors = hasErrors + 1;
}
}
});
}
});
if (hasErrors !== 0) {
grunt.fail.warn('Found ' + hasErrors + ' ' + grunt.util.pluralize(hasErrors, 'error/errors') + ' in ' + fileArray.length + ' files');
} else {
grunt.log.writeln('Checked ' + fileArray.length + ' files for valid styles and found nothing wrong.');
}
});
grunt.config('verify-styles', {
dist: {
options: {
validStyles: grunt.file.readJSON('.tmp/validStyles.json')
},
files: [
{
expand: false,
src: [
'.tmp/l10n/*/*.json'
]
}
]
}
});
grunt.registerMultiTask('generate-valid-styles', 'Generate the list of valid styles for translation', function () {
//different regex from above, uses single quotes not double
var styleRegex = /style='[\s\S]*?'/ig;
var styleArray = [];
// iterate through .pot file and extract the styles
this.files[0].src.forEach(function (src) {
var contents = grunt.file.read(src);
if (styleRegex.test(contents)) {
Array.prototype.push.apply(styleArray, contents.match(styleRegex));
}
});
styleArray = styleArray.map(stripSpecialChars);
// write out the styles to a temporary JSON file
grunt.file.write(this.files[0].dest, JSON.stringify(styleArray));
grunt.log.writeln('Generated styles from ' + this.files[0].src.length + ' files');
});
grunt.config('generate-valid-styles', {
dist: {
files: [
{
expand: false,
src: [
'locale/templates/*/server.pot'
],
dest: '.tmp/validStyles.json'
}
]
}
});
function stripSpecialChars(str) {
str = str.replace(/'/g, '"');
str = str.replace(/""/g, '');
str = str.replace(/\n/g, '');
return str.replace(/(\\)/g, '');
}
};

Просмотреть файл

@ -13,5 +13,12 @@
"license": "MPL-2.0",
"bugs": {
"url": "https://github.com/mozilla/fxa-content-server-l10n/issues"
},
"devDependencies": {
"grunt": "0.4.5",
"grunt-po2json": "git://github.com/shane-tomlinson/grunt-po2json.git#aa276503e",
"i18n-abide": "0.0.23",
"load-grunt-tasks": "3.2.0",
"time-grunt": "1.2.1"
}
}