@microsoft/windows-admin-center-sdk
Version:
Microsoft - Windows Admin Center Shell
202 lines (200 loc) • 9.11 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const buffer_1 = require("buffer");
const fs_1 = tslib_1.__importDefault(require("fs"));
const fancy_log_1 = tslib_1.__importDefault(require("fancy-log"));
const plugin_error_1 = tslib_1.__importDefault(require("plugin-error"));
const through2_1 = tslib_1.__importDefault(require("through2"));
const vinyl_1 = tslib_1.__importDefault(require("vinyl"));
const util = tslib_1.__importStar(require("../utilities"));
const PLUGIN_NAME = 'gulp-update-notes-resource';
function gulpUpdateNotesResources(options) {
function findResourceKey(node, results) {
const match = 'resources:strings:';
const keys = Object.keys(node);
if (keys && keys.length > 0) {
keys.forEach(key => {
const target = node[key];
if (target) {
if (typeof target === 'string') {
if (target.indexOf(match) === 0) {
const value = target.substring(match.length);
if (results.indexOf(value) < 0) {
results.push(value);
}
}
}
else {
findResourceKey(target, results);
}
}
});
}
}
// override options settings if not specified.
options = Object.assign({
updateNotes: 'packages/shell/src/assets/updates/update-notes.json',
localeOffset: 1
}, options || {});
const resources = {};
const keyToResources = {};
return through2_1.default.obj(
/**
* Transform
*/
function (file, encoding, callback) {
let locale = 'default';
if (resources.default) {
// if default is set already, find current locale from the file path.
const pathSegments = file.history[0].split('\\');
locale = pathSegments[pathSegments.length - (2 + options.localeOffset)];
}
resources[locale] = {};
if (resources.default) {
// if default is set already, pre-fill all resource items from default.
for (const resourceId in resources.default) {
if (resources.default.hasOwnProperty(resourceId)) {
resources[locale][resourceId] = resources.default[resourceId];
}
}
}
// remove comments, /* multiline comment */ and // one line comment and "//": "JSON element comment"
const content = file.contents.toString('utf8')
.replace(/(\/\*([^*]|[\n]|(\*+([^*/]|[\n])))*\*\/+)|( +\/\/.*)|( +\"\/\/\".*)/g, '');
const object = JSON.parse(content);
if (object[options.resourceName] && object[options.resourceName]['App']['UpdateNotes']) {
// supports <ResourceName>.Manifest.<KeyName> format.
const items = object[options.resourceName]['App']['UpdateNotes'];
for (const key in items) {
if (items.hasOwnProperty(key)) {
// Each key will have two children, title and description
// no need to separate in JSON form
resources[locale][key] = items[key];
// Used to keep an alternate mapping we use later
if (!keyToResources.hasOwnProperty(key)) {
keyToResources[key] = {};
}
if (keyToResources.hasOwnProperty(key) &&
!keyToResources[key].hasOwnProperty(locale)) {
keyToResources[key][locale] = {};
}
keyToResources[key][locale] = items[key];
}
}
}
else {
// supports <ResourceName>_App_UpdateNotes format.
const resourceUpdateNotes = options.resourceName + '_App_UpdateNotes_';
for (const name in object) {
if (object.hasOwnProperty(name)) {
const index = name.indexOf(resourceUpdateNotes);
if (index === 0) {
// Check if this resource has the specific substring or not
const value = object[name];
// If it contains '_' we split it so we keep only the key
const resourceId2 = name.substring(resourceUpdateNotes.length);
// Split to separate <KeyValue>_<type>
// Possible types are title or description
const splitText = resourceId2.split('_');
const key = splitText[0];
const type = splitText[1];
if (!resources[locale].hasOwnProperty(key)) {
resources[locale][key] = {};
}
resources[locale][key][type] = value;
// Used to keep a mapping of keys to resources for faster
// processing later
if (!keyToResources.hasOwnProperty(key)) {
keyToResources[key] = {};
}
if (keyToResources.hasOwnProperty(key) &&
!keyToResources[key].hasOwnProperty(locale)) {
keyToResources[key][locale] = {};
}
keyToResources[key][locale][type] = value;
}
}
}
}
return callback();
},
/**
* Flush
*/
function (callback) {
try {
const updateNotesObject = JSON.parse(fs_1.default.readFileSync(options.updateNotes, 'utf8'));
const keys = [];
findResourceKey(updateNotesObject, keys);
const missingType = [];
const missing = [];
const unused = Object.keys(resources.default);
keys.forEach(function (key) {
const index = unused.indexOf(key);
if (index >= 0) {
// If the item exists, remove it from the unused set
unused.splice(index, 1);
// We have to check each item has a title and description
const typeKeys = Object.keys(keyToResources[key].default);
const requiredTypesSet = new Set();
requiredTypesSet.add('title');
requiredTypesSet.add('description');
typeKeys.forEach(item => {
if (requiredTypesSet.has(item)) {
requiredTypesSet.delete(item);
}
});
// If it did not have we save it throw error later
if (requiredTypesSet.size > 0) {
missingType.push(key);
}
}
else {
missing.push(key);
}
});
if (missing.length > 0) {
missing.forEach(item => {
fancy_log_1.default.error('Missing resource: ' + item);
});
throw new Error('Missing resource found in manifest.json!');
}
if (unused.length > 0) {
unused.forEach(item => {
fancy_log_1.default.error('Unused resource: ' + item);
});
throw new Error('Unused resource found in strings.resjson!');
}
if (missingType.length > 0) {
missingType.forEach(item => {
fancy_log_1.default.error('Missing title or description: ' + item);
});
throw new Error('Key without title or description found in strings.resjson!');
}
updateNotesObject.map((item, index) => {
if (item.hasOwnProperty('stringJsonKey')) {
const key = item.stringJsonKey.replace('resources:strings:', '');
// Key to resource maps key -> all locales
item.resources = keyToResources[key];
}
updateNotesObject[index] = item;
});
const updateNotesFile = new vinyl_1.default({
cwd: '.',
base: '.',
path: './update-notes.json',
contents: buffer_1.Buffer.from(JSON.stringify(updateNotesObject, null, 2), 'utf8')
});
this.push(updateNotesFile);
}
catch (e) {
const error = (!e.plugin || (e.plugin !== PLUGIN_NAME)) ?
util.extendError(new plugin_error_1.default({ plugin: PLUGIN_NAME, message: e.message }), e) : e;
fancy_log_1.default.error(error);
}
callback();
});
}
module.exports = gulpUpdateNotesResources;
//# sourceMappingURL=index.js.map