qa-control 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +1 -1
  2. package/bin/{0.3.0 → definition}/definition.js +680 -764
  3. package/bin/{0.3.0 → definition}/first-lines-both.txt +25 -25
  4. package/bin/definition/first-lines-client.txt +3 -0
  5. package/bin/{0.3.0 → definition}/first-lines-server-app.txt +2 -2
  6. package/bin/{0.3.0 → definition}/first-lines-server-cmd-tool.txt +2 -2
  7. package/bin/{0.3.0 → definition}/first-lines-server.txt +3 -3
  8. package/bin/definition/first-lines-web.txt +3 -0
  9. package/bin/qa-control.js +15 -42
  10. package/bin/qac-init.js +0 -18
  11. package/package.json +1 -1
  12. package/bin/0.0.1/definition.js +0 -556
  13. package/bin/0.0.1/first-lines-both.txt +0 -28
  14. package/bin/0.0.1/first-lines-client.txt +0 -6
  15. package/bin/0.0.1/first-lines-server-app.txt +0 -6
  16. package/bin/0.0.1/first-lines-server.txt +0 -6
  17. package/bin/0.0.2/definition.js +0 -577
  18. package/bin/0.0.2/first-lines-both.txt +0 -28
  19. package/bin/0.0.2/first-lines-client.txt +0 -6
  20. package/bin/0.0.2/first-lines-server-app.txt +0 -6
  21. package/bin/0.0.2/first-lines-server.txt +0 -6
  22. package/bin/0.1.3/definition.js +0 -653
  23. package/bin/0.1.3/first-lines-both.txt +0 -28
  24. package/bin/0.1.3/first-lines-client.txt +0 -6
  25. package/bin/0.1.3/first-lines-server-app.txt +0 -7
  26. package/bin/0.1.3/first-lines-server.txt +0 -7
  27. package/bin/0.1.4/definition.js +0 -706
  28. package/bin/0.1.4/first-lines-both.txt +0 -28
  29. package/bin/0.1.4/first-lines-client.txt +0 -6
  30. package/bin/0.1.4/first-lines-server-app.txt +0 -7
  31. package/bin/0.1.4/first-lines-server.txt +0 -7
  32. package/bin/0.2.0/definition.js +0 -771
  33. package/bin/0.2.0/first-lines-both.txt +0 -27
  34. package/bin/0.2.0/first-lines-client.txt +0 -5
  35. package/bin/0.2.0/first-lines-server-app.txt +0 -6
  36. package/bin/0.2.0/first-lines-server-cmd-tool.txt +0 -6
  37. package/bin/0.2.0/first-lines-server.txt +0 -6
  38. package/bin/0.3.0/first-lines-client.txt +0 -3
  39. package/bin/0.3.0/first-lines-web.txt +0 -3
@@ -1,764 +1,680 @@
1
- "use strict";
2
-
3
- var stripBom = require("strip-bom-string");
4
- var semver = require("semver");
5
- var jsh = require('jshint');
6
- var esl = require('eslint');
7
- var eslintLinter = new esl.Linter();
8
- function eslintrcToFlatConfig(rc) {
9
- var flat = {};
10
- if (rc.rules) { flat.rules = rc.rules; }
11
- var sourceType = (rc.env && rc.env.node) ? 'commonjs' : 'script';
12
- flat.languageOptions = { ecmaVersion: 'latest', sourceType: sourceType };
13
- flat.linterOptions = { reportUnusedDisableDirectives: 'off' };
14
- return flat;
15
- }
16
- var multilang = require('multilang');
17
- var fs = require('fs-promise');
18
- var Path = require('path');
19
- var yaml = require('js-yaml');
20
-
21
- module.exports = function(qaControl){
22
- return {
23
- fileNameMainDoc: 'LEEME.md',
24
- sections: { // podria llamarse 'json-sections'...
25
- 'run-in': {
26
- mandatory: true,
27
- values: {
28
- server:{},
29
- both:{},
30
- client:{}
31
- }
32
- },
33
- type: {
34
- mandatory:true,
35
- values: {
36
- app: {},
37
- lib: {},
38
- "cmd-tool": {},
39
- web: {}
40
- }
41
- }
42
- },
43
- files:{
44
- 'README.md':{ mandatory:true },
45
- 'LEEME.md':{ mandatory:true },
46
- '.travis.yml':{ mandatory:true },
47
- '.gitignore':{
48
- mandatory:true,
49
- mandatoryLines:['local-*','*-local.*']
50
- },
51
- 'LICENSE':{ mandatory:true },
52
- 'appveyor.yml':{
53
- presentIf:function(packageJson){
54
- return !!packageJson['qa-control']["test-appveyor"];
55
- }
56
- },
57
- '.jshintrc':{ mandatory:true },
58
- '.eslintrc.yml':{ mandatory:true }
59
- },
60
- cucardas:{
61
- 'proof-of-concept':{
62
- check: function(packageJson){
63
- return packageJson['qa-control'].purpose==='proof-of-concept';
64
- },
65
- md:'![proof-of-concept](https://img.shields.io/badge/stability-proof_of_concept-ff70c0.svg)',
66
- imgExample:'https://img.shields.io/badge/stability-designing-red.svg'
67
- },
68
- designing:{
69
- check: function(packageJson){
70
- return semver.satisfies(packageJson.version,'0.0.x') && !packageJson['qa-control'].purpose;
71
- },
72
- md:'![designing](https://img.shields.io/badge/stability-designing-red.svg)',
73
- imgExample:'https://img.shields.io/badge/stability-designing-red.svg',
74
- docDescription: 'opt. manual'
75
- },
76
- extending:{
77
- check: function(packageJson){
78
- return semver.satisfies(packageJson.version,'0.x.x') &&
79
- !semver.satisfies(packageJson.version,'0.0.x') &&
80
- !packageJson['qa-control'].purpose;
81
- },
82
- md:'![extending](https://img.shields.io/badge/stability-extending-orange.svg)',
83
- imgExample:'https://img.shields.io/badge/stability-extending-orange.svg',
84
- docDescription: 'opt. manual'
85
- },
86
- training:{
87
- check: function(packageJson){
88
- return packageJson['qa-control'].purpose==='training';
89
- },
90
- md:'![training](https://img.shields.io/badge/stability-training-ffa0c0.svg)',
91
- imgExample:'https://img.shields.io/badge/stability-training-ffa0c0.svg'
92
- },
93
- example:{
94
- check: function(packageJson){
95
- return packageJson['qa-control'].purpose==='example';
96
- },
97
- md:'![example](https://img.shields.io/badge/stability-example-a0a0f0.svg)',
98
- imgExample:'https://img.shields.io/badge/stability-example-a0a0f0.svg'
99
- },
100
- stable:{
101
- check: function(packageJson){
102
- return semver.satisfies(packageJson.version,'>=1.0.0') && !packageJson['qa-control'].purpose;
103
- },
104
- md:'![stable](https://img.shields.io/badge/stability-stable-brightgreen.svg)',
105
- imgExample:'https://img.shields.io/badge/stability-stable-brightgreen.svg'
106
- },
107
- 'npm-version':{
108
- mandatory:true,
109
- md:'[![npm-version](https://img.shields.io/npm/v/yyy.svg)](https://npmjs.org/package/yyy)',
110
- imgExample:'https://raw.githubusercontent.com/codenautas/codenautas/master/img/npm-version.png',
111
- docDescription: ''
112
- },
113
- downloads:{
114
- mandatory:true,
115
- md:'[![downloads](https://img.shields.io/npm/dm/yyy.svg)](https://npmjs.org/package/yyy)',
116
- imgExample:'https://raw.githubusercontent.com/codenautas/codenautas/master/img/downloads.png',
117
- docDescription: ''
118
- },
119
- build:{
120
- check: function(packageJson){
121
- return !packageJson['qa-control']['test-appveyor'];
122
- },
123
- md:'[![build](https://img.shields.io/travis/xxx/yyy/master.svg)](https://travis-ci.org/xxx/yyy)',
124
- imgExample:'https://raw.githubusercontent.com/codenautas/codenautas/master/img/medalla-ejemplo-linux.png',
125
- docDescription: 'linux/build'
126
- },
127
- linux:{
128
- check: function(packageJson){
129
- return !!packageJson['qa-control']['test-appveyor'];
130
- },
131
- md:'[![linux](https://img.shields.io/travis/xxx/yyy/master.svg)](https://travis-ci.org/xxx/yyy)',
132
- imgExample:'https://raw.githubusercontent.com/codenautas/codenautas/master/img/medalla-ejemplo-linux.png',
133
- hideInManual: true,
134
- },
135
- windows:{
136
- check: function(packageJson){
137
- return !!packageJson['qa-control']['test-appveyor'];
138
- },
139
- md:'[![windows](https://ci.appveyor.com/api/projects/status/github/xxx/yyy?svg=true)](https://ci.appveyor.com/project/xxx/yyy)',
140
- imgExample:'https://ci.appveyor.com/api/projects/status/github/codenautas/pg-promise-strict?svg=true',
141
- docDescription: 'casos especiales'
142
- },
143
- coverage:{
144
- check: function(packageJson){
145
- return packageJson['qa-control'].coverage;
146
- },
147
- md:'[![coverage](https://img.shields.io/coveralls/xxx/yyy/master.svg)](https://coveralls.io/r/xxx/yyy)',
148
- imgExample:'https://raw.githubusercontent.com/codenautas/codenautas/master/img/coverage.png',
149
- docDescription: ''
150
- },
151
- climate:{
152
- check: function(packageJson){
153
- return packageJson['qa-control'].coverage || ! packageJson['qa-control'].purpose;
154
- },
155
- md:'[![climate](https://img.shields.io/codeclimate/github/xxx/yyy.svg)](https://codeclimate.com/github/xxx/yyy)',
156
- imgExample:'https://raw.githubusercontent.com/codenautas/codenautas/master/img/climate.png',
157
- docDescription: ''
158
- },
159
- dependencies:{
160
- mandatory:true,
161
- md:'[![dependencies](https://img.shields.io/david/xxx/yyy.svg)](https://david-dm.org/xxx/yyy)',
162
- imgExample:'https://raw.githubusercontent.com/codenautas/codenautas/master/img/medalla-ejemplo-dependencies.png',
163
- docDescription: ''
164
- },
165
- 'qa-control':{
166
- mandatory:true,
167
- md:'[![qa-control](http://codenautas.com/github/xxx/yyy.svg)](http://codenautas.com/github/xxx/yyy)',
168
- docDescription: ''
169
- }
170
- },
171
- customs:{
172
- softRegExp:function(realRegex) {
173
- var re=realRegex.replace(/\\/g, '\\\\')
174
- .replace(/\s*(=+)\s*/g,'\\s*$1\\s*')
175
- .replace(/ /g, '\\s+')
176
- .replace(/\(/g, '\\(')
177
- .replace(/\)/g, '\\)');
178
- return new RegExp(re, 'im');
179
- },
180
- funtion_eid:{
181
- detect:'function eid',
182
- match:'function eid(id){ return document.getElementById(id); }'
183
- },
184
- var_winos:{
185
- // separo los siguientes dos strings en dos partes para que no salte un warning
186
- detect:'var '+'winos=',
187
- match:"var "+"winOS = Path.sep==='\\\\';"
188
- },
189
- var_path:{
190
- detect:'var path=',
191
- match:"var Path = require('path');"
192
- }
193
- },
194
- jshint_options: { "asi": false, "curly": true, "forin": true },
195
- eslint_options: {
196
- "env": {
197
- "node": false
198
- },
199
- "rules": {
200
- "strict": 0,
201
- "no-console": 1,
202
- "no-unused-vars": 1
203
- }
204
- },
205
- // Si info.scoring == true, cada regla debe agregar junto al warning, un objeto 'scoring'
206
- // con na o m�s de las siguientes propiedades:
207
- // qac: 1
208
- // mandatories: 1
209
- // cucardas:1
210
- // multilang:1
211
- // versions:1
212
- // parameters:1
213
- // format:1
214
- // customs:1
215
- // jshint:1
216
- // dependencies:1
217
- // Emilio redefinir� valores de cada score
218
- rules:{
219
- exist_package_json:{
220
- checks:[{
221
- warnings:function(info){
222
- if(!info.files['package.json']){
223
- return [{warning:'no_package_json', scoring:{fatal:1}}];
224
- }
225
- return [];
226
- }
227
- }],
228
- shouldAbort:true
229
- },
230
- qa_control_section_in_package_json:{
231
- checks:[{
232
- warnings:function(info){
233
- if(!info.packageJson['qa-control']){
234
- return [{warning:info.files['package.json'].content.match(/codenautas/)?
235
- 'no_qa_control_section_in_codenautas_project':
236
- 'no_qa_control_section_in_package_json', scoring:{fatal:1}}];
237
- }
238
- return [];
239
- }
240
- }],
241
- shouldAbort:true
242
- },
243
- package_version_in_qa_control_section:{
244
- checks:[{
245
- warnings:function(info){
246
- if(!info.packageJson['qa-control']['package-version']){
247
- return [{warning:'no_package_version_in_qa_control_section', scoring:{fatal:1}}];
248
- } else {
249
- // defino la version para para siguientes checks
250
- info.packageVersion = info.packageJson['qa-control']['package-version'];
251
- }
252
- return [];
253
- }
254
- }],
255
- shouldAbort:true
256
- },
257
- invalid_qa_control_version: {
258
- checks:[{
259
- warnings:function(info){
260
- var ver=info.packageVersion;
261
- if(! semver.valid(ver)){
262
- return [{warning:'invalid_qa_control_version',params:[ver], scoring:{versions:1}}];
263
- }
264
- return [];
265
- }
266
- }],
267
- shouldAbort:true
268
- },
269
- deprecated_control_version: {
270
- checks:[{
271
- warnings:function(info) {
272
- var ver=info.packageVersion;
273
- if(semver.satisfies(ver, qaControl.deprecatedVersions)){
274
- return [{warning:'deprecated_qa_control_version',params:[ver], scoring:{warning:1}}];
275
- }
276
- return [];
277
- }
278
- }],
279
- shouldAbort:true
280
- },
281
- mandatory_files:{
282
- checks:[{
283
- warnings:function(info) {
284
- var warns =[];
285
- var files=qaControl.projectDefinition[info.packageVersion].files;
286
- for(var fileName in files) {
287
- if(files.hasOwnProperty(fileName)) {
288
- var file = files[fileName];
289
- if(file.mandatory && !info.files[fileName]) {
290
- warns.push({warning:'lack_of_mandatory_file_1', params:[fileName], scoring:{mandatories:1}});
291
- } else {
292
- if(file.presentIf && file.presentIf(info.packageJson) && !info.files[fileName]) {
293
- warns.push({warning:'lack_of_mandatory_file_1', params:[fileName], scoring:{mandatories:1}});
294
- }
295
- }
296
- }
297
- }
298
- return warns;
299
- }
300
- }],
301
- shouldAbort:true
302
- },
303
- repository_in_package_json:{
304
- checks:[{
305
- warnings:function(info) {
306
- var warns = [];
307
- if(!('repository' in info.packageJson)) {
308
- warns.push({warning:'lack_of_repository_section_in_package_json', scoring:{mandatories:1}});
309
- } else {
310
- if(! qaControl.getRepositoryUrl(info.packageJson).match(/^([-a-zA-Z0-9_.]+\/[-a-zA-Z0-9_.]+)$/)){
311
- return [{warning:'repository_name_not_found', scoring:{mandatories:1}}];
312
- }
313
- }
314
- return warns;
315
- }
316
- }],
317
- shouldAbort:true
318
- },
319
- valid_values_for_qa_control_keys:{
320
- checks:[{
321
- warnings:function(info){
322
- var warns=[];
323
- var qaControlSection=info.packageJson['qa-control'];
324
- var sections=qaControl.projectDefinition[info.packageVersion].sections;
325
- /*jshint forin: false */
326
- for(var sectionName in sections){
327
- var sectionDef=sections[sectionName];
328
- if(sectionDef.mandatory && !(sectionName in qaControlSection)){
329
- warns.push({warning:'lack_of_mandatory_section_1',params:[sectionName], scoring:{mandatories:1}});
330
- }else{
331
- var observedValue=qaControlSection[sectionName];
332
- if(sectionDef.values && !(observedValue in sectionDef.values)){
333
- warns.push({warning:'invalid_value_1_in_parameter_2',params:[observedValue,sectionName], scoring:{warnings:1}});
334
- }
335
- }
336
- }
337
- /*jshint forin: true */
338
- return warns;
339
- }
340
- }],
341
- shouldAbort:true
342
- },
343
- mandatory_lines:{
344
- checks:[{
345
- warnings:function(info) {
346
- var warns =[];
347
- var files=qaControl.projectDefinition[info.packageVersion].files;
348
- for(var fileName in files) {
349
- var file=files[fileName];
350
- if(file.mandatoryLines) {
351
- var fileContent = info.files[fileName].content;
352
- file.mandatoryLines.forEach(function(mandatoryLine) {
353
- // agrego '\n' antes para no utilizar expresiones regulares
354
- if(fileContent.indexOf('\n'+mandatoryLine)===-1) {
355
- warns.push({warning:'lack_of_mandatory_line_1_in_file_2',
356
- params:[mandatoryLine, fileName],
357
- scoring:{mandatories:1}});
358
- }
359
- });
360
- }
361
- }
362
- return warns;
363
- }
364
- }]
365
- }, // agregar desde ac�
366
- no_test_in_last_node:{
367
- checks:[{
368
- warnings:function(info){
369
- if(info.dotTravis && info.dotTravis.node_js.filter(function(x){ return x[0].match(qaControl.nodeVerInTravisRE); }).length<2){
370
- return [{warning:'no_test_in_last_node', scoring:{conventions:1}}];
371
- }
372
- return [];
373
- }
374
- }],
375
- },
376
- no_multilang_section_in_1:{
377
- checks:[{
378
- warnings:function(info){
379
- if(!info.files[qaControl.mainDoc()].content.match(/<!--multilang v[0-9]+\s+(.+)(-->)/)) {
380
- return [{
381
- warning:'no_multilang_section_in_1',
382
- params:[qaControl.mainDoc()],
383
- scoring:{multilang:1}
384
- }];
385
- }
386
- return [];
387
- }
388
- }]
389
- },
390
- invalid_repository_in_package_json:{
391
- checks:[{
392
- warnings:function(info) {
393
- var warns = [];
394
- var repoParts = qaControl.getRepositoryUrl(info.packageJson).split('/');
395
- var projName = repoParts[repoParts.length-1];
396
- if(projName !== info.packageJson.name) {
397
- return [{warning:'invalid_repository_section_in_package_json', scoring:{repository:1}}];
398
- }
399
- return warns;
400
- }
401
- }]
402
- },
403
- cucardas:{
404
- eclipsers:['invalid_repository_section_in_package_json', 'lack_of_repository_section_in_package_json'],
405
- checks:[{
406
- warnings:function(info){
407
- var warns=[];
408
- var readme=info.files[qaControl.mainDoc()].content;
409
- if(readme.indexOf(qaControl.cucaMarker) === -1) {
410
- warns.push({warning:'lack_of_cucarda_marker_in_readme'});
411
- }
412
- var cucardas=qaControl.projectDefinition[info.packageVersion].cucardas;
413
- var modulo=info.packageJson.name;
414
- var repo=qaControl.getRepositoryUrl(info.packageJson).replace('/'+modulo,'');
415
- /*jshint forin: false */
416
- for(var nombreCucarda in cucardas) {
417
- var cucarda = cucardas[nombreCucarda];
418
- var cucaID = '!['+/!\[([-a-z]+)]/.exec(cucarda.md)[1]+']';
419
- var cucaStr = cucarda.md.replace(/\bxxx\b/g,repo).replace(/\byyy\b/g,modulo);
420
- if(readme.indexOf(cucaID) === -1) {
421
- if(cucarda.mandatory) {
422
- warns.push({warning:'lack_of_mandatory_cucarda_1', params:[nombreCucarda], scoring:{cucardas:1}});
423
- }
424
- } else {
425
- if('check' in cucarda && ! cucarda.check(info.packageJson)) {
426
- warns.push({warning:'wrong_format_in_cucarda_1', params:[nombreCucarda], scoring:{cucardas:1}});
427
- }
428
- if(readme.indexOf(cucaStr) === -1) {
429
- // si tengo cucarda mal formada, devuelvo warning aunque no sea obligatoria
430
- // porque existi� la intenci�n de definirla
431
- warns.push({warning:'wrong_format_in_cucarda_1', params:[nombreCucarda], scoring:{cucardas:1}});
432
- }
433
- }
434
- }
435
- /*jshint forin: true */
436
- if(warns.length || qaControl.cucardas_always) {
437
- fs.writeFile(Path.normalize(info.projectDir+'/cucardas.log'), qaControl.generateCucardas(cucardas, info.packageJson));
438
- }
439
- return warns;
440
- }
441
- }]
442
- },
443
- customs:{
444
- checks:[{
445
- warnings:function(info) {
446
- var warns=[];
447
- var customs = qaControl.projectDefinition[info.packageVersion].customs;
448
- function makeCheck(strOrRegexp, isMatchFunc) {
449
- var checker;
450
- if(!strOrRegexp){
451
- checker=function() { return false; };
452
- }else if(strOrRegexp instanceof RegExp) {
453
- checker=function(str) {
454
- return strOrRegexp.test(str);
455
- };
456
- } else {
457
- checker=function(str) {
458
- if(isMatchFunc) {
459
- return str.indexOf(strOrRegexp) !== -1;
460
- } else {
461
- return customs.softRegExp(strOrRegexp).test(str);
462
- }
463
- };
464
- }
465
- return checker;
466
- }
467
- for(var file in info.files) {
468
- if(file.match(/(.js)$/)) {
469
- for(var customeName in customs) {
470
- if(customs.hasOwnProperty(customeName)) {
471
- var content = info.files[file].content;
472
- var custom = customs[customeName];
473
- var detect = makeCheck(custom.detect);
474
- var match = makeCheck(custom.match, true);
475
- //console.log(file, " detect:", detect(content), " match: ", match(content))
476
- if(detect(content) && ! match(content)) {
477
- warns.push({warning:'file_1_does_not_match_custom_2', params:[file,customeName], scoring:{conventions:1}});
478
- }
479
- }
480
- }
481
- }
482
- }
483
- return warns;
484
- }
485
- }]
486
- },
487
- first_lines:{
488
- checks:[{
489
- warnings:function(info) {
490
- var warns=[];
491
- var qaControlSection=info.packageJson['qa-control'];
492
- var whichRunIn=qaControlSection['run-in'];
493
- var whichType=qaControlSection.type;
494
- var firstLines=qaControl.projectDefinition[info.packageVersion].firstLines[whichRunIn][whichType];
495
- if(firstLines) {
496
- var ProjectName = qaControl.jsProjectName(info.packageJson.name);
497
- var projectName = qaControl.first("toLowerCase")(ProjectName);
498
- var mainName = ('main' in info.packageJson) ? info.packageJson.main : 'index.js';
499
- if(!(mainName in info.files)) {
500
- warns.push({warning:'packagejson_main_file_1_does_not_exists', params:[mainName], scoring:{warning:1}});
501
- } else {
502
- var fileContent = stripBom(info.files[mainName].content);
503
-
504
- if(!qaControl.startsWith(fileContent, firstLines.replace(/nombreDelModulo/g, ProjectName)) &&
505
- !qaControl.startsWith(fileContent, firstLines.replace(/nombreDelModulo/g, projectName))
506
- ) {
507
- if(qaControl.verbose){
508
- var code=qaControl.fixEOL(fileContent);
509
- var model1=qaControl.fixEOL(firstLines.replace(/nombreDelModulo/g, projectName));
510
- var model2=qaControl.fixEOL(firstLines.replace(/nombreDelModulo/g, ProjectName));
511
- for(var i=0; i<model1.length; i++){
512
- if(code[i]!== model1[i] && code[i] !== model2[i]){
513
- console.log('RUN-IN', whichRunIn);
514
- console.log('DIF STARTS IN:',JSON.stringify(code.substring(i, Math.min(model1.length, i+20))));
515
- console.log('MODEL 1 :',JSON.stringify(model1.substring(i, Math.min(model1.length, i+20))));
516
- console.log('MODEL 2 :',JSON.stringify(model2.substring(i, Math.min(model1.length, i+20))));
517
- console.log('FOR MODULE NAME:',projectName,'OR',ProjectName);
518
- break;
519
- }
520
- }
521
- }
522
- warns.push({warning:'first_lines_does_not_match_in_file_1', params:[mainName], scoring:{warning:1}});
523
- }
524
- }
525
- }
526
- return warns;
527
- }
528
- }]
529
- },
530
- normal_promises:{
531
- checks:[{
532
- warnings:function(info){
533
- var warns = [];
534
- for(var file in info.files) {
535
- if(file.match(/(.js)$/)) {
536
- var content = info.files[file].content;
537
- if(content.match(/require\(["'](promise|q|rsvp|es6promise)['"]\)/m)) {
538
- warns.push({warning:'using_normal_promise_in_file_1', params:[file], scoring:{conventions:1}});
539
- }
540
- }
541
- }
542
- return warns;
543
- }
544
- }]
545
- },
546
- jshint:{
547
- eclipsers:['packagejson_main_file_1_does_not_exists', 'first_lines_does_not_match_in_file_1'],
548
- checks:[{
549
- warnings:function(info){
550
- var warns = [];
551
- var jshintOpts = JSON.parse(info.files['.jshintrc'].content);
552
- for(var file in info.files) {
553
- if(file.match(/(.js)$/)) {
554
- var content = info.files[file].content;
555
- jsh.JSHINT(content, jshintOpts , false);
556
- var data = jsh.JSHINT.data();
557
- if(data.errors) {
558
- if(qaControl.verbose){
559
- console.log('JSHINT output:');
560
- console.log('jshintOpts',jshintOpts);
561
- console.log('There are '+data.length+ " JSHINT errors");
562
- console.log(data.errors);
563
- //console.log(data);
564
- }
565
- warns.push({warning:'jshint_warnings_in_file_1', params:[file], scoring:{jshint:1}});
566
- }
567
- }
568
- }
569
- return warns;
570
- }
571
- }]
572
- },
573
- eslint:{
574
- eclipsers:['packagejson_main_file_1_does_not_exists', 'first_lines_does_not_match_in_file_1'],
575
- checks:[{
576
- warnings:function(info){
577
- var warns = [];
578
- var eslintOpts = eslintrcToFlatConfig(yaml.load(info.files['.eslintrc.yml'].content));
579
- for(var file in info.files) {
580
- if(file.match(/(.js)$/)) {
581
- var content = info.files[file].content;
582
- var data = eslintLinter.verify(content, eslintOpts);
583
- if(data.length) {
584
- if(qaControl.verbose){
585
- console.log('ESLINT output:');
586
- console.log('eslintOpts',eslintOpts);
587
- console.log('There are '+data.length+ " ESLINT errors");
588
- console.log(data);
589
- //console.log(data);
590
- }
591
- warns.push({warning:'eslint_warnings_in_file_1', params:[file], scoring:{eslint:1}});
592
- }
593
- }
594
- }
595
- return warns;
596
- }
597
- }]
598
- },
599
- multilang:{
600
- checks:[{
601
- warnings:function(info) {
602
- var warns = [];
603
- var defReadme = qaControl.mainDoc();
604
- var content = info.files[defReadme].content;
605
- var obtainedLangs = multilang.obtainLangs(content);
606
- /*jshint forin: false */
607
- for(var lang in obtainedLangs.langs) {
608
- var file=obtainedLangs.langs[lang].fileName;
609
- if(file !== defReadme) {
610
- var mlContent = multilang.changeNamedDoc(file, content, lang);
611
- if(mlContent !== info.files[file].content) {
612
- //var now=Date.now();
613
- // fs.writeFileSync("_"+now+"_gen_"+file, mlContent, 'utf8');
614
- // fs.writeFileSync("_"+now+"_ori_"+file, info.files[file].content, 'utf8');
615
- warns.push({warning:'readme_multilang_not_sincronized_with_file_1', params:[file], scoring:{multilang:1}});
616
- }
617
- }
618
- }
619
- /*jshint forin: true */
620
- return warns;
621
- }
622
- }]
623
- },
624
- dependencies:{
625
- checks:[{
626
- warnings:qaControl.checkDepVerNumberFormat
627
- }]
628
- },
629
- use_strict:{
630
- checks:[{
631
- warnings:function(info){
632
- var warns = [];
633
- function hasColonOutsideQuotes(line) {
634
- return line.replace(/([\'"])(.*?)\1/g,'').match(/:/);
635
- }
636
- for(var file in info.files) {
637
- if(file.match(/(.js)$/)) {
638
- var content = info.files[file].content;
639
- var lines = info.files[file].content.split(/\r?\n/);
640
- var prevLine = null;
641
- for(var l=0; l<lines.length; ++l) {
642
- var line = lines[l];
643
- var trimLine = line.replace(/^(\s+)/,'');
644
- //console.log("line:"+l, '['+line+']', "trimmed", '['+trimLine+']', "prev", '['+prevLine+']');
645
- if(trimLine.length>0
646
- && trimLine[0].match(/['"]/)
647
- && prevLine
648
- && prevLine.match(/{\s?$/)
649
- //&& ! line.match(/["'].*["']\s*:/)
650
- && ! hasColonOutsideQuotes(trimLine)
651
- )
652
- {
653
- if(! trimLine.match(/"use strict";/)) {
654
- if(qaControl.verbose){
655
- console.log('['+file+']');
656
- console.log(' '+(l-1)+':"'+prevLine+'"');
657
- console.log(' '+(l)+':"'+line+'"');
658
- }
659
- warns.push({warning:'wrong_use_strict_spelling_in_file_1', params:[file], scoring:{conventions:1}});
660
- }
661
- }
662
- prevLine = line;
663
- }
664
- }
665
- }
666
- return warns;
667
- }
668
- }]
669
- },
670
- files_in_package_json:{
671
- checks:[{
672
- warnings:function(info) {
673
- var warns = [];
674
- if(!('files' in info.packageJson)) {
675
- warns.push({warning:'lack_of_files_section_in_package_json', scoring:{mandatories:1}});
676
- } else {
677
- var detail=[];
678
- //console.log("info.files", Object.keys(info.files));
679
- //console.log("files", info.packageJson.files.join(" "));
680
- var qaFiles=qaControl.projectDefinition[info.packageVersion].files;
681
- for(var fileName in info.packageJson.files) {
682
- var file = info.packageJson.files[fileName];
683
- if(file==='package.json') { detail.push('"'+file+'" is always included by npm'); }
684
- if(file.match(/^(\.)/)) { detail.push('"'+file+'" is a .dot file'); }
685
- if(file in qaFiles) {
686
- detail.push('"'+file+'" cannot be in files section');
687
- } else {
688
- try {
689
- var stat = fs.statSync(Path.resolve(info.projectDir+'/'+file));
690
- if(! stat.isDirectory()) {
691
- if(!(file in info.files)) { detail.push('"'+file+'" should exist'); }
692
- }
693
- } catch(e) { detail.push('"'+file+'" does not exists'); }
694
- }
695
- }
696
- if(detail.length) {
697
- warns.push({warning:'invalid_files_section_in_package_json', scoring:{mandatories:1}});
698
- if(qaControl.verbose) {
699
- console.log("Invalid files:");
700
- console.log("\t"+detail.join("\n\t"));
701
- }
702
- }
703
- }
704
- return warns;
705
- }
706
- }]
707
- },
708
- lint_sections_in_package_json:{
709
- checks:[{
710
- warnings:function(info) {
711
- var warns = [];
712
- if('jshintConfig' in info.packageJson) {
713
- warns.push({warning:'unexpected_jshintconfig_section_in_package_json', scoring:{conventions:1}});
714
- }
715
- if('eslintConfig' in info.packageJson) {
716
- warns.push({warning:'unexpected_eslintconfig_section_in_package_json', scoring:{conventions:1}});
717
- }
718
- return warns;
719
- }
720
- }]
721
- },
722
- travis_node_versions:{
723
- checks:[{
724
- warnings:function(info) {
725
- var warns = [];
726
- var travisYML = yaml.load(info.files['.travis.yml'].content);
727
- var mandatories = travisYML.node_js;
728
- var optionals = travisYML.matrix.allow_failures;
729
- var versions=[{num:'4'},{num:'6'} ,{num:7, optional:true}];
730
- versions.forEach(function(version) {
731
- var re = RegExp('^('+version.num+'\.?)');
732
- if(! mandatories.some(function(ver) { return re.test(ver); })) {
733
- warns.push({warning:'lack_of_travis_check_for_node_version_1', params:[version.num], scoring:{mandatories:1}});
734
- } else if(! version.optional && optionals) {
735
- if(optionals.some(function(opt) { return opt.node_js && re.test(opt.node_js); })) {
736
- warns.push({warning:'not_allowed_travis_failure_for_node_version_1', params:[version.num], scoring:{mandatories:1}});
737
- }
738
- }
739
- });
740
- return warns;
741
- }
742
- }]
743
- },
744
- non_recomended_dependencies:{
745
- checks:[{
746
- warnings:function(info) {
747
- var warns = [];
748
- var nonRecomended = ['best-promise', 'lodash', 'promise-plus'];
749
- var dependencies = info.packageJson.dependencies;
750
- var devDependencies = info.packageJson.devDependencies;
751
- if(dependencies) {
752
- nonRecomended.forEach(function(badDep) {
753
- if(badDep in dependencies || badDep in devDependencies) {
754
- warns.push({warning:'non_recomended_dependency_1_in_package_json', params:[badDep], scoring:{dependencies:1}});
755
- }
756
- });
757
- }
758
- return warns;
759
- }
760
- }]
761
- }
762
- }
763
- };
764
- };
1
+ "use strict";
2
+
3
+ var stripBom = require("strip-bom-string");
4
+ var semver = require("semver");
5
+ var jsh = require('jshint');
6
+ var esl = require('eslint');
7
+ var eslintLinter = new esl.Linter();
8
+ function eslintrcToFlatConfig(rc) {
9
+ var flat = {};
10
+ if (rc.rules) { flat.rules = rc.rules; }
11
+ var sourceType = (rc.env && rc.env.node) ? 'commonjs' : 'script';
12
+ flat.languageOptions = { ecmaVersion: 'latest', sourceType: sourceType };
13
+ flat.linterOptions = { reportUnusedDisableDirectives: 'off' };
14
+ return flat;
15
+ }
16
+ var multilang = require('multilang');
17
+ var fs = require('fs-promise');
18
+ var Path = require('path');
19
+ var yaml = require('js-yaml');
20
+
21
+ module.exports = function(qaControl){
22
+ return {
23
+ fileNameMainDoc: 'LEEME.md',
24
+ sections: { // podria llamarse 'json-sections'...
25
+ 'run-in': {
26
+ mandatory: true,
27
+ values: {
28
+ server:{},
29
+ both:{},
30
+ client:{}
31
+ }
32
+ },
33
+ type: {
34
+ mandatory:true,
35
+ values: {
36
+ app: {},
37
+ lib: {},
38
+ "cmd-tool": {},
39
+ web: {}
40
+ }
41
+ }
42
+ },
43
+ files:{
44
+ 'README.md':{ mandatory:true },
45
+ 'LEEME.md':{ mandatory:true },
46
+ '.gitignore':{
47
+ mandatory:true,
48
+ mandatoryLines:['local-*','*-local.*']
49
+ },
50
+ 'LICENSE':{ mandatory:true },
51
+ 'appveyor.yml':{
52
+ presentIf:function(packageJson){
53
+ return !!packageJson['qa-control']["test-appveyor"];
54
+ }
55
+ },
56
+ '.jshintrc':{ presentIf: function(pj) { return pj['qa-control'] && pj['qa-control'].profile !== 'minimum'; } },
57
+ '.eslintrc.yml':{ presentIf: function(pj) { return pj['qa-control'] && pj['qa-control'].profile !== 'minimum'; } }
58
+ },
59
+ cucardas:{
60
+ 'proof-of-concept':{
61
+ check: function(packageJson){
62
+ return packageJson['qa-control'].purpose==='proof-of-concept';
63
+ },
64
+ md:'![proof-of-concept](https://img.shields.io/badge/stability-proof_of_concept-ff70c0.svg)',
65
+ imgExample:'https://img.shields.io/badge/stability-designing-red.svg'
66
+ },
67
+ designing:{
68
+ check: function(packageJson){
69
+ return semver.satisfies(packageJson.version,'0.0.x') && !packageJson['qa-control'].purpose;
70
+ },
71
+ md:'![designing](https://img.shields.io/badge/stability-designing-red.svg)',
72
+ imgExample:'https://img.shields.io/badge/stability-designing-red.svg',
73
+ docDescription: 'opt. manual'
74
+ },
75
+ extending:{
76
+ check: function(packageJson){
77
+ return semver.satisfies(packageJson.version,'0.x.x') &&
78
+ !semver.satisfies(packageJson.version,'0.0.x') &&
79
+ !packageJson['qa-control'].purpose;
80
+ },
81
+ md:'![extending](https://img.shields.io/badge/stability-extending-orange.svg)',
82
+ imgExample:'https://img.shields.io/badge/stability-extending-orange.svg',
83
+ docDescription: 'opt. manual'
84
+ },
85
+ training:{
86
+ check: function(packageJson){
87
+ return packageJson['qa-control'].purpose==='training';
88
+ },
89
+ md:'![training](https://img.shields.io/badge/stability-training-ffa0c0.svg)',
90
+ imgExample:'https://img.shields.io/badge/stability-training-ffa0c0.svg'
91
+ },
92
+ example:{
93
+ check: function(packageJson){
94
+ return packageJson['qa-control'].purpose==='example';
95
+ },
96
+ md:'![example](https://img.shields.io/badge/stability-example-a0a0f0.svg)',
97
+ imgExample:'https://img.shields.io/badge/stability-example-a0a0f0.svg'
98
+ },
99
+ stable:{
100
+ check: function(packageJson){
101
+ return semver.satisfies(packageJson.version,'>=1.0.0') && !packageJson['qa-control'].purpose;
102
+ },
103
+ md:'![stable](https://img.shields.io/badge/stability-stable-blue.svg)',
104
+ imgExample:'https://img.shields.io/badge/stability-stable-blue.svg'
105
+ },
106
+ 'npm-version':{
107
+ mandatory:true,
108
+ md:'[![npm-version](https://img.shields.io/npm/v/yyy.svg)](https://npmjs.org/package/yyy)',
109
+ imgExample:'https://raw.githubusercontent.com/codenautas/codenautas/master/img/npm-version.png',
110
+ docDescription: ''
111
+ },
112
+ downloads:{
113
+ mandatory:true,
114
+ md:'[![downloads](https://img.shields.io/npm/dm/yyy.svg)](https://npmjs.org/package/yyy)',
115
+ imgExample:'https://raw.githubusercontent.com/codenautas/codenautas/master/img/downloads.png',
116
+ docDescription: ''
117
+ },
118
+ build:{
119
+ check: function(packageJson){
120
+ return !packageJson['qa-control']['test-appveyor'];
121
+ },
122
+ md:'[![build](https://github.com/xxx/yyy/workflows/node.js.yml/badge.svg)](https://github.com/xxx/yyy/workflows/node.js.yml)',
123
+ imgExample:'https://raw.githubusercontent.com/codenautas/codenautas/master/img/medalla-ejemplo-linux.png',
124
+ docDescription: 'linux/build'
125
+ },
126
+ linux:{
127
+ check: function(packageJson){
128
+ return !!packageJson['qa-control']['test-appveyor'];
129
+ },
130
+ md:'[![linux](https://github.com/xxx/yyy/workflows/node.js.yml/badge.svg)](https://github.com/xxx/yyy/workflows/node.js.yml)',
131
+ imgExample:'https://raw.githubusercontent.com/codenautas/codenautas/master/img/medalla-ejemplo-linux.png',
132
+ hideInManual: true,
133
+ },
134
+ windows:{
135
+ check: function(packageJson){
136
+ return !!packageJson['qa-control']['test-appveyor'];
137
+ },
138
+ md:'[![windows](https://ci.appveyor.com/api/projects/status/github/xxx/yyy?svg=true)](https://ci.appveyor.com/project/xxx/yyy)',
139
+ imgExample:'https://ci.appveyor.com/api/projects/status/github/codenautas/pg-promise-strict?svg=true',
140
+ docDescription: 'casos especiales'
141
+ },
142
+ coverage:{
143
+ check: function(packageJson){
144
+ return packageJson['qa-control'].coverage;
145
+ },
146
+ md:'[![coverage](https://img.shields.io/coveralls/xxx/yyy/master.svg)](https://coveralls.io/r/xxx/yyy)',
147
+ imgExample:'https://raw.githubusercontent.com/codenautas/codenautas/master/img/coverage.png',
148
+ docDescription: ''
149
+ },
150
+ climate:{
151
+ check: function(packageJson){
152
+ return packageJson['qa-control'].coverage || ! packageJson['qa-control'].purpose;
153
+ },
154
+ md:'[![climate](https://img.shields.io/codeclimate/github/xxx/yyy.svg)](https://codeclimate.com/github/xxx/yyy)',
155
+ imgExample:'https://raw.githubusercontent.com/codenautas/codenautas/master/img/climate.png',
156
+ docDescription: ''
157
+ },
158
+ dependencies:{
159
+ mandatory:true,
160
+ md:'[![dependencies](https://snyk.io/test/github/xxx/yyy/badge.svg)](https://snyk.io/test/github/xxx/yyy)',
161
+ imgExample:'https://raw.githubusercontent.com/codenautas/codenautas/master/img/medalla-ejemplo-dependencies.png',
162
+ docDescription: ''
163
+ },
164
+ 'qa-control':{
165
+ mandatory:false,
166
+ md:'[![qa-control](http://codenautas.com/github/xxx/yyy.svg)](http://codenautas.com/github/xxx/yyy)',
167
+ docDescription: ''
168
+ }
169
+ },
170
+ customs:{
171
+ softRegExp:function(realRegex) {
172
+ var re=realRegex.replace(/\\/g, '\\\\')
173
+ .replace(/\s*(=+)\s*/g,'\\s*$1\\s*')
174
+ .replace(/ /g, '\\s+')
175
+ .replace(/\(/g, '\\(')
176
+ .replace(/\)/g, '\\)');
177
+ return new RegExp(re, 'im');
178
+ },
179
+ funtion_eid:{
180
+ detect:'function eid',
181
+ match:'function eid(id){ return document.getElementById(id); }'
182
+ },
183
+ var_winos:{
184
+ // separo los siguientes dos strings en dos partes para que no salte un warning
185
+ detect:'var '+'winos=',
186
+ match:"var "+"winOS = Path.sep==='\\\\';"
187
+ },
188
+ var_path:{
189
+ detect:'var path=',
190
+ match:"var Path = require('path');"
191
+ }
192
+ },
193
+ jshint_options: { "asi": false, "curly": true, "forin": true },
194
+ eslint_options: {
195
+ "env": {
196
+ "node": false
197
+ },
198
+ "rules": {
199
+ "strict": 0,
200
+ "no-console": 1,
201
+ "no-unused-vars": 1
202
+ }
203
+ },
204
+ rules:{
205
+ exist_package_json:{
206
+ checks:[{
207
+ warnings:function(info){
208
+ if(!info.files['package.json']){
209
+ return [{warning:'no_package_json', scoring:{fatal:1}}];
210
+ }
211
+ return [];
212
+ }
213
+ }],
214
+ shouldAbort:true
215
+ },
216
+ qa_control_section_in_package_json:{
217
+ checks:[{
218
+ warnings:function(info){
219
+ if(!info.packageJson['qa-control']){
220
+ return [{warning:info.files['package.json'].content.match(/codenautas/)?
221
+ 'no_qa_control_section_in_codenautas_project':
222
+ 'no_qa_control_section_in_package_json', scoring:{fatal:1}}];
223
+ }
224
+ return [];
225
+ }
226
+ }],
227
+ shouldAbort:true
228
+ },
229
+ mandatory_files:{
230
+ checks:[{
231
+ warnings:function(info) {
232
+ var warns =[];
233
+ var files=qaControl.definition.files;
234
+ for(var fileName in files) {
235
+ if(files.hasOwnProperty(fileName)) {
236
+ var file = files[fileName];
237
+ if(file.mandatory && !info.files[fileName]) {
238
+ warns.push({warning:'lack_of_mandatory_file_1', params:[fileName], scoring:{mandatories:1}});
239
+ } else {
240
+ if(file.presentIf && file.presentIf(info.packageJson) && !info.files[fileName]) {
241
+ warns.push({warning:'lack_of_mandatory_file_1', params:[fileName], scoring:{mandatories:1}});
242
+ }
243
+ }
244
+ }
245
+ }
246
+ return warns;
247
+ }
248
+ }],
249
+ shouldAbort:true
250
+ },
251
+ repository_in_package_json:{
252
+ checks:[{
253
+ warnings:function(info) {
254
+ var warns = [];
255
+ if(!('repository' in info.packageJson)) {
256
+ warns.push({warning:'lack_of_repository_section_in_package_json', scoring:{mandatories:1}});
257
+ } else {
258
+ if(! qaControl.getRepositoryUrl(info.packageJson).match(/^([-a-zA-Z0-9_.]+\/[-a-zA-Z0-9_.]+)$/)){
259
+ return [{warning:'repository_name_not_found', scoring:{mandatories:1}}];
260
+ }
261
+ }
262
+ return warns;
263
+ }
264
+ }],
265
+ shouldAbort:true
266
+ },
267
+ valid_values_for_qa_control_keys:{
268
+ checks:[{
269
+ warnings:function(info){
270
+ var warns=[];
271
+ var qaControlSection=info.packageJson['qa-control'];
272
+ var sections=qaControl.definition.sections;
273
+ /*jshint forin: false */
274
+ for(var sectionName in sections){
275
+ var sectionDef=sections[sectionName];
276
+ if(sectionDef.mandatory && !(sectionName in qaControlSection)){
277
+ warns.push({warning:'lack_of_mandatory_section_1',params:[sectionName], scoring:{mandatories:1}});
278
+ }else{
279
+ var observedValue=qaControlSection[sectionName];
280
+ if(sectionDef.values && !(observedValue in sectionDef.values)){
281
+ warns.push({warning:'invalid_value_1_in_parameter_2',params:[observedValue,sectionName], scoring:{warnings:1}});
282
+ }
283
+ }
284
+ }
285
+ /*jshint forin: true */
286
+ return warns;
287
+ }
288
+ }],
289
+ shouldAbort:true
290
+ },
291
+ mandatory_lines:{
292
+ checks:[{
293
+ warnings:function(info) {
294
+ var warns =[];
295
+ var files=qaControl.definition.files;
296
+ for(var fileName in files) {
297
+ var file=files[fileName];
298
+ if(file.mandatoryLines) {
299
+ var fileContent = info.files[fileName].content;
300
+ file.mandatoryLines.forEach(function(mandatoryLine) {
301
+ // agrego '\n' antes para no utilizar expresiones regulares
302
+ if(fileContent.indexOf('\n'+mandatoryLine)===-1) {
303
+ warns.push({warning:'lack_of_mandatory_line_1_in_file_2',
304
+ params:[mandatoryLine, fileName],
305
+ scoring:{mandatories:1}});
306
+ }
307
+ });
308
+ }
309
+ }
310
+ return warns;
311
+ }
312
+ }]
313
+ },
314
+ no_multilang_section_in_1:{
315
+ checks:[{
316
+ warnings:function(info){
317
+ if(!info.files[qaControl.mainDoc()].content.match(/<!--multilang v[0-9]+\s+(.+)(-->)/)) {
318
+ return [{
319
+ warning:'no_multilang_section_in_1',
320
+ params:[qaControl.mainDoc()],
321
+ scoring:{multilang:1}
322
+ }];
323
+ }
324
+ return [];
325
+ }
326
+ }]
327
+ },
328
+ invalid_repository_in_package_json:{
329
+ checks:[{
330
+ warnings:function(info) {
331
+ var warns = [];
332
+ var repoParts = qaControl.getRepositoryUrl(info.packageJson).split('/');
333
+ var projName = repoParts[repoParts.length-1];
334
+ if(projName !== info.packageJson.name) {
335
+ return [{warning:'invalid_repository_section_in_package_json', scoring:{repository:1}}];
336
+ }
337
+ return warns;
338
+ }
339
+ }]
340
+ },
341
+ cucardas:{
342
+ eclipsers:['invalid_repository_section_in_package_json', 'lack_of_repository_section_in_package_json'],
343
+ checks:[{
344
+ warnings:function(info){
345
+ var warns=[];
346
+ var readme=info.files[qaControl.mainDoc()].content;
347
+ if(readme.indexOf(qaControl.cucaMarker) === -1) {
348
+ warns.push({warning:'lack_of_cucarda_marker_in_readme'});
349
+ }
350
+ var cucardas=qaControl.definition.cucardas;
351
+ var modulo=info.packageJson.name;
352
+ var repo=qaControl.getRepositoryUrl(info.packageJson).replace('/'+modulo,'');
353
+ /*jshint forin: false */
354
+ for(var nombreCucarda in cucardas) {
355
+ var cucarda = cucardas[nombreCucarda];
356
+ var cucaID = '!['+/!\[([-a-z]+)]/.exec(cucarda.md)[1]+']';
357
+ var cucaStr = cucarda.md.replace(/\bxxx\b/g,repo).replace(/\byyy\b/g,modulo);
358
+ if(readme.indexOf(cucaID) === -1) {
359
+ if(cucarda.mandatory) {
360
+ warns.push({warning:'lack_of_mandatory_cucarda_1', params:[nombreCucarda], scoring:{cucardas:1}});
361
+ }
362
+ } else {
363
+ if('check' in cucarda && ! cucarda.check(info.packageJson)) {
364
+ warns.push({warning:'wrong_format_in_cucarda_1', params:[nombreCucarda], scoring:{cucardas:1}});
365
+ }
366
+ if(readme.indexOf(cucaStr) === -1) {
367
+ // si tengo cucarda mal formada, devuelvo warning aunque no sea obligatoria
368
+ // porque existió la intención de definirla
369
+ warns.push({warning:'wrong_format_in_cucarda_1', params:[nombreCucarda], scoring:{cucardas:1}});
370
+ }
371
+ }
372
+ }
373
+ /*jshint forin: true */
374
+ if(warns.length || qaControl.cucardas_always) {
375
+ fs.writeFile(Path.normalize(info.projectDir+'/cucardas.log'), qaControl.generateCucardas(cucardas, info.packageJson));
376
+ }
377
+ return warns;
378
+ }
379
+ }]
380
+ },
381
+ customs:{
382
+ checks:[{
383
+ warnings:function(info) {
384
+ var warns=[];
385
+ var customs = qaControl.definition.customs;
386
+ function makeCheck(strOrRegexp, isMatchFunc) {
387
+ var checker;
388
+ if(!strOrRegexp){
389
+ checker=function() { return false; };
390
+ }else if(strOrRegexp instanceof RegExp) {
391
+ checker=function(str) {
392
+ return strOrRegexp.test(str);
393
+ };
394
+ } else {
395
+ checker=function(str) {
396
+ if(isMatchFunc) {
397
+ return str.indexOf(strOrRegexp) !== -1;
398
+ } else {
399
+ return customs.softRegExp(strOrRegexp).test(str);
400
+ }
401
+ };
402
+ }
403
+ return checker;
404
+ }
405
+ for(var file in info.files) {
406
+ if(file.match(/(.js)$/)) {
407
+ for(var customeName in customs) {
408
+ if(customs.hasOwnProperty(customeName)) {
409
+ var content = info.files[file].content;
410
+ var custom = customs[customeName];
411
+ var detect = makeCheck(custom.detect);
412
+ var match = makeCheck(custom.match, true);
413
+ //console.log(file, " detect:", detect(content), " match: ", match(content))
414
+ if(detect(content) && ! match(content)) {
415
+ warns.push({warning:'file_1_does_not_match_custom_2', params:[file,customeName], scoring:{conventions:1}});
416
+ }
417
+ }
418
+ }
419
+ }
420
+ }
421
+ return warns;
422
+ }
423
+ }]
424
+ },
425
+ first_lines:{
426
+ checks:[{
427
+ warnings:function(info) {
428
+ var warns=[];
429
+ var qaControlSection=info.packageJson['qa-control'];
430
+ var whichRunIn=qaControlSection['run-in'];
431
+ var whichType=qaControlSection.type;
432
+ var firstLines=qaControl.definition.firstLines[whichRunIn][whichType];
433
+ if(firstLines) {
434
+ var ProjectName = qaControl.jsProjectName(info.packageJson.name);
435
+ var projectName = qaControl.first("toLowerCase")(ProjectName);
436
+ var mainName = ('main' in info.packageJson) ? info.packageJson.main : 'index.js';
437
+ if(!(mainName in info.files)) {
438
+ warns.push({warning:'packagejson_main_file_1_does_not_exists', params:[mainName], scoring:{warning:1}});
439
+ } else {
440
+ var fileContent = stripBom(info.files[mainName].content);
441
+
442
+ if(!qaControl.startsWith(fileContent, firstLines.replace(/nombreDelModulo/g, ProjectName)) &&
443
+ !qaControl.startsWith(fileContent, firstLines.replace(/nombreDelModulo/g, projectName))
444
+ ) {
445
+ if(qaControl.verbose){
446
+ var code=qaControl.fixEOL(fileContent);
447
+ var model1=qaControl.fixEOL(firstLines.replace(/nombreDelModulo/g, projectName));
448
+ var model2=qaControl.fixEOL(firstLines.replace(/nombreDelModulo/g, ProjectName));
449
+ for(var i=0; i<model1.length; i++){
450
+ if(code[i]!== model1[i] && code[i] !== model2[i]){
451
+ console.log('RUN-IN', whichRunIn);
452
+ console.log('DIF STARTS IN:',JSON.stringify(code.substring(i, Math.min(model1.length, i+20))));
453
+ console.log('MODEL 1 :',JSON.stringify(model1.substring(i, Math.min(model1.length, i+20))));
454
+ console.log('MODEL 2 :',JSON.stringify(model2.substring(i, Math.min(model1.length, i+20))));
455
+ console.log('FOR MODULE NAME:',projectName,'OR',ProjectName);
456
+ break;
457
+ }
458
+ }
459
+ }
460
+ warns.push({warning:'first_lines_does_not_match_in_file_1', params:[mainName], scoring:{warning:1}});
461
+ }
462
+ }
463
+ }
464
+ return warns;
465
+ }
466
+ }]
467
+ },
468
+ normal_promises:{
469
+ checks:[{
470
+ warnings:function(info){
471
+ var warns = [];
472
+ for(var file in info.files) {
473
+ if(file.match(/(.js)$/)) {
474
+ var content = info.files[file].content;
475
+ if(content.match(/require\(["'](promise|q|rsvp|es6promise)['"]\)/m)) {
476
+ warns.push({warning:'using_normal_promise_in_file_1', params:[file], scoring:{conventions:1}});
477
+ }
478
+ }
479
+ }
480
+ return warns;
481
+ }
482
+ }]
483
+ },
484
+ jshint:{
485
+ eclipsers:['packagejson_main_file_1_does_not_exists', 'first_lines_does_not_match_in_file_1'],
486
+ mandatory:false,
487
+ checks:[{
488
+ warnings:function(info){
489
+ if(info.packageJson['qa-control'] && info.packageJson['qa-control'].profile === 'minimum') { return []; }
490
+ var warns = [];
491
+ var jshintOpts = JSON.parse(info.files['.jshintrc'].content);
492
+ for(var file in info.files) {
493
+ if(file.match(/(.js)$/)) {
494
+ var content = info.files[file].content;
495
+ jsh.JSHINT(content, jshintOpts , false);
496
+ var data = jsh.JSHINT.data();
497
+ if(data.errors) {
498
+ if(qaControl.verbose){
499
+ console.log('JSHINT output:');
500
+ console.log('jshintOpts',jshintOpts);
501
+ console.log('There are '+data.length+ " JSHINT errors");
502
+ console.log(data.errors);
503
+ //console.log(data);
504
+ }
505
+ warns.push({warning:'jshint_warnings_in_file_1', params:[file], scoring:{jshint:1}});
506
+ }
507
+ }
508
+ }
509
+ return warns;
510
+ }
511
+ }]
512
+ },
513
+ eslint:{
514
+ eclipsers:['packagejson_main_file_1_does_not_exists', 'first_lines_does_not_match_in_file_1'],
515
+ checks:[{
516
+ warnings:function(info){
517
+ if(info.packageJson['qa-control'] && info.packageJson['qa-control'].profile === 'minimum') { return []; }
518
+ var warns = [];
519
+ var eslintOpts = eslintrcToFlatConfig(yaml.load(info.files['.eslintrc.yml'].content));
520
+ for(var file in info.files) {
521
+ if(file.match(/(.js)$/)) {
522
+ var content = info.files[file].content;
523
+ var data = eslintLinter.verify(content, eslintOpts);
524
+ if(data.length) {
525
+ if(qaControl.verbose){
526
+ console.log('ESLINT output:');
527
+ console.log('eslintOpts',eslintOpts);
528
+ console.log('There are '+data.length+ " ESLINT errors");
529
+ console.log(data);
530
+ //console.log(data);
531
+ }
532
+ warns.push({warning:'eslint_warnings_in_file_1', params:[file], scoring:{eslint:1}});
533
+ }
534
+ }
535
+ }
536
+ return warns;
537
+ }
538
+ }]
539
+ },
540
+ multilang:{
541
+ checks:[{
542
+ warnings:function(info) {
543
+ var warns = [];
544
+ var defReadme = qaControl.mainDoc();
545
+ var content = info.files[defReadme].content;
546
+ var obtainedLangs = multilang.obtainLangs(content);
547
+ /*jshint forin: false */
548
+ for(var lang in obtainedLangs.langs) {
549
+ var file=obtainedLangs.langs[lang].fileName;
550
+ if(file !== defReadme) {
551
+ var mlContent = multilang.changeNamedDoc(file, content, lang);
552
+ if(mlContent !== info.files[file].content) {
553
+ warns.push({warning:'readme_multilang_not_sincronized_with_file_1', params:[file], scoring:{multilang:1}});
554
+ }
555
+ }
556
+ }
557
+ /*jshint forin: true */
558
+ return warns;
559
+ }
560
+ }]
561
+ },
562
+ dependencies:{
563
+ checks:[{
564
+ warnings:qaControl.checkDepVerNumberFormat
565
+ }]
566
+ },
567
+ use_strict:{
568
+ checks:[{
569
+ warnings:function(info){
570
+ var warns = [];
571
+ function hasColonOutsideQuotes(line) {
572
+ return line.replace(/([\'"])(.*?)\1/g,'').match(/:/);
573
+ }
574
+ for(var file in info.files) {
575
+ if(file.match(/(.js)$/)) {
576
+ var content = info.files[file].content;
577
+ var lines = info.files[file].content.split(/\r?\n/);
578
+ var prevLine = null;
579
+ for(var l=0; l<lines.length; ++l) {
580
+ var line = lines[l];
581
+ var trimLine = line.replace(/^(\s+)/,'');
582
+ //console.log("line:"+l, '['+line+']', "trimmed", '['+trimLine+']', "prev", '['+prevLine+']');
583
+ if(trimLine.length>0
584
+ && trimLine[0].match(/['"]/)
585
+ && prevLine
586
+ && prevLine.match(/{\s?$/)
587
+ //&& ! line.match(/["'].*["']\s*:/)
588
+ && ! hasColonOutsideQuotes(trimLine)
589
+ )
590
+ {
591
+ if(! trimLine.match(/"use strict";/)) {
592
+ if(qaControl.verbose){
593
+ console.log('['+file+']');
594
+ console.log(' '+(l-1)+':"'+prevLine+'"');
595
+ console.log(' '+(l)+':"'+line+'"');
596
+ }
597
+ warns.push({warning:'wrong_use_strict_spelling_in_file_1', params:[file], scoring:{conventions:1}});
598
+ }
599
+ }
600
+ prevLine = line;
601
+ }
602
+ }
603
+ }
604
+ return warns;
605
+ }
606
+ }]
607
+ },
608
+ files_in_package_json:{
609
+ checks:[{
610
+ warnings:function(info) {
611
+ var warns = [];
612
+ if(!('files' in info.packageJson)) {
613
+ warns.push({warning:'lack_of_files_section_in_package_json', scoring:{mandatories:1}});
614
+ } else {
615
+ var detail=[];
616
+ //console.log("info.files", Object.keys(info.files));
617
+ //console.log("files", info.packageJson.files.join(" "));
618
+ var qaFiles=qaControl.definition.files;
619
+ for(var fileName in info.packageJson.files) {
620
+ var file = info.packageJson.files[fileName];
621
+ if(file==='package.json') { detail.push('"'+file+'" is always included by npm'); }
622
+ if(file.match(/^(\.)/)) { detail.push('"'+file+'" is a .dot file'); }
623
+ if(file in qaFiles) {
624
+ detail.push('"'+file+'" cannot be in files section');
625
+ } else {
626
+ try {
627
+ var stat = fs.statSync(Path.resolve(info.projectDir+'/'+file));
628
+ if(! stat.isDirectory()) {
629
+ if(!(file in info.files)) { detail.push('"'+file+'" should exist'); }
630
+ }
631
+ } catch(e) { detail.push('"'+file+'" does not exists'); }
632
+ }
633
+ }
634
+ if(detail.length) {
635
+ warns.push({warning:'invalid_files_section_in_package_json', scoring:{mandatories:1}});
636
+ if(qaControl.verbose) {
637
+ console.log("Invalid files:");
638
+ console.log("\t"+detail.join("\n\t"));
639
+ }
640
+ }
641
+ }
642
+ return warns;
643
+ }
644
+ }]
645
+ },
646
+ lint_sections_in_package_json:{
647
+ checks:[{
648
+ warnings:function(info) {
649
+ var warns = [];
650
+ if('jshintConfig' in info.packageJson) {
651
+ warns.push({warning:'unexpected_jshintconfig_section_in_package_json', scoring:{conventions:1}});
652
+ }
653
+ if('eslintConfig' in info.packageJson) {
654
+ warns.push({warning:'unexpected_eslintconfig_section_in_package_json', scoring:{conventions:1}});
655
+ }
656
+ return warns;
657
+ }
658
+ }]
659
+ },
660
+ non_recomended_dependencies:{
661
+ checks:[{
662
+ warnings:function(info) {
663
+ var warns = [];
664
+ var nonRecomended = ['best-promise', 'lodash', 'promise-plus'];
665
+ var dependencies = info.packageJson.dependencies;
666
+ var devDependencies = info.packageJson.devDependencies;
667
+ if(dependencies) {
668
+ nonRecomended.forEach(function(badDep) {
669
+ if(badDep in dependencies || badDep in devDependencies) {
670
+ warns.push({warning:'non_recomended_dependency_1_in_package_json', params:[badDep], scoring:{dependencies:1}});
671
+ }
672
+ });
673
+ }
674
+ return warns;
675
+ }
676
+ }]
677
+ }
678
+ }
679
+ };
680
+ };