2015-01-05 58 views
0

我对bootstrapgrunt非常新,在我的计算机上设置了任何东西之后,我开始为CSS添加我自己的员工,任何工作都可以正常工作。jshint的bootstrap和grunt问题

现在,我喜欢在文件夹/bower_components/bootstrap/js/下注册我自己的app.js脚本。我喜欢这样做,为了grunt,通过jshint检查我的代码质量,并最终在引导的其他文件中组合并最小化我的脚本。 (我不知道这是很好的做法,所以如果是错了,请咨询我最好的做法:))

因此,该文件夹下,我上面提到的,我有我的创建文件app.js,并我已将以下代码放在该文件中:

+function ($) { 
    'use strict'; 
}(jQuery); 

它非常简单明了。

的问题是,我从grunt以下的输出:

>> File "js/app.js" changed. 
Running "jshint:src" (jshint) task 
Verifying property jshint.src exists in config...ERROR 
>> Unable to process task. 
Warning: Required config property "jshint.src" missing. Use --force to continue. 

Aborted due to warnings. 

这有什么错呢?有人可以帮我吗?

更新:1

我只是删除我的app.js文件,我用一个空格修改从默认bootstrap脚本和问题依然存在另一个文件,所以这个问题不会产生由于我的脚本,但gruntjshint未配置。

更新:2

这是我Gruntfile.js

/*! 
    * Bootstrap's Gruntfile 
* http://getbootstrap.com 
* Copyright 2013-2014 Twitter, Inc. 
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 
*/ 

module.exports = function (grunt) { 
    'use strict'; 

    // Force use of Unix newlines 
    grunt.util.linefeed = '\n'; 

    RegExp.quote = function (string) { 
    return string.replace(/[-\\^$*+?.()|[\]{}]/g, '\\$&'); 
    }; 

    var fs = require('fs'); 
    var path = require('path'); 
    var npmShrinkwrap = require('npm-shrinkwrap'); 
    var BsLessdocParser = require('./grunt/bs-lessdoc-parser.js'); 
    var getLessVarsData = function() { 
    var filePath = path.join(__dirname, 'less/variables.less'); 
    var fileContent = fs.readFileSync(filePath, { encoding: 'utf8' }); 
    var parser = new BsLessdocParser(fileContent); 
    return { sections: parser.parseFile() }; 
    }; 
    var generateRawFiles = require('./grunt/bs-raw-files-generator.js'); 
    var generateCommonJSModule = require('./grunt/bs-commonjs-generator.js'); 
    var configBridge = grunt.file.readJSON('./grunt/configBridge.json', { encoding: 'utf8' }); 

    Object.keys(configBridge.paths).forEach(function (key) { 
    configBridge.paths[key].forEach(function (val, i, arr) { 
     arr[i] = path.join('./docs/assets', val); 
    }); 
    }); 

    // Project configuration. 
    grunt.initConfig({ 

    // Metadata. 
    pkg: grunt.file.readJSON('package.json'), 
    banner: '/*!\n' + 
      ' * Bootstrap v<%= pkg.version %> (<%= pkg.homepage %>)\n' + 
      ' * Copyright 2011-<%= grunt.template.today("yyyy") %> <%= pkg.author %>\n' + 
      ' * Licensed under <%= pkg.license.type %> (<%= pkg.license.url %>)\n' + 
      ' */\n', 
    jqueryCheck: configBridge.config.jqueryCheck.join('\n'), 
    jqueryVersionCheck: configBridge.config.jqueryVersionCheck.join('\n'), 

    // Task configuration. 
    clean: { 
     dist: 'dist', 
     docs: 'docs/dist' 
    }, 

    jshint: { 
     files: ['js/*.js'], 
     src: { 
      files: ['js/*.js'] 
     }, 
     options: { 
     jshintrc: 'js/.jshintrc' 
     }, 
     grunt: { 
     options: { 
      jshintrc: 'grunt/.jshintrc' 
     }, 
     src: ['Gruntfile.js', 'grunt/*.js'] 
     }, 
     core: { 
     src: 'js/*.js' 
     }, 
     test: { 
     options: { 
      jshintrc: 'js/tests/unit/.jshintrc' 
     }, 
     src: 'js/tests/unit/*.js' 
     }, 
     assets: { 
     src: ['docs/assets/js/src/*.js', 'docs/assets/js/*.js', '!docs/assets/js/*.min.js'] 
     } 
    }, 

    jscs: { 
     options: { 
     config: 'js/.jscsrc' 
     }, 
     grunt: { 
     src: '<%= jshint.grunt.src %>' 
     }, 
     core: { 
     src: '<%= jshint.core.src %>' 
     }, 
     test: { 
     src: '<%= jshint.test.src %>' 
     }, 
     assets: { 
     options: { 
      requireCamelCaseOrUpperCaseIdentifiers: null 
     }, 
     src: '<%= jshint.assets.src %>' 
     } 
    }, 

    concat: { 
     options: { 
     banner: '<%= banner %>\n<%= jqueryCheck %>\n<%= jqueryVersionCheck %>', 
     stripBanners: false 
     }, 
     bootstrap: { 
     src: [ 
      'js/transition.js', 
      'js/alert.js', 
      'js/button.js', 
      'js/carousel.js', 
      'js/collapse.js', 
      'js/dropdown.js', 
      'js/modal.js', 
      'js/tooltip.js', 
      'js/popover.js', 
      'js/scrollspy.js', 
      'js/tab.js', 
      'js/affix.js', 
      'js/app.js' 
     ], 
     dest: 'dist/js/<%= pkg.name %>.js' 
     } 
    }, 

    uglify: { 
     options: { 
     preserveComments: 'some' 
     }, 
     core: { 
     src: '<%= concat.bootstrap.dest %>', 
     dest: 'dist/js/<%= pkg.name %>.min.js' 
     }, 
     customize: { 
     src: configBridge.paths.customizerJs, 
     dest: 'docs/assets/js/customize.min.js' 
     }, 
     docsJs: { 
     src: configBridge.paths.docsJs, 
     dest: 'docs/assets/js/docs.min.js' 
     } 
    }, 

    qunit: { 
     options: { 
     inject: 'js/tests/unit/phantom.js' 
     }, 
     files: 'js/tests/index.html' 
    }, 

    less: { 
     compileCore: { 
     options: { 
      strictMath: true, 
      sourceMap: true, 
      outputSourceFiles: true, 
      sourceMapURL: '<%= pkg.name %>.css.map', 
      sourceMapFilename: 'dist/css/<%= pkg.name %>.css.map' 
     }, 
     src: 'less/bootstrap.less', 
     dest: 'dist/css/<%= pkg.name %>.css' 
     }, 
     compileTheme: { 
     options: { 
      strictMath: true, 
      sourceMap: true, 
      outputSourceFiles: true, 
      sourceMapURL: '<%= pkg.name %>-theme.css.map', 
      sourceMapFilename: 'dist/css/<%= pkg.name %>-theme.css.map' 
     }, 
     src: 'less/theme.less', 
     dest: 'dist/css/<%= pkg.name %>-theme.css' 
     } 
    }, 

    autoprefixer: { 
     options: { 
     browsers: configBridge.config.autoprefixerBrowsers 
     }, 
     core: { 
     options: { 
      map: true 
     }, 
     src: 'dist/css/<%= pkg.name %>.css' 
     }, 
     theme: { 
     options: { 
      map: true 
     }, 
     src: 'dist/css/<%= pkg.name %>-theme.css' 
     }, 
     docs: { 
     src: 'docs/assets/css/src/docs.css' 
     }, 
     examples: { 
     expand: true, 
     cwd: 'docs/examples/', 
     src: ['**/*.css'], 
     dest: 'docs/examples/' 
     } 
    }, 

    csslint: { 
     options: { 
     csslintrc: 'less/.csslintrc' 
     }, 
     dist: [ 
     'dist/css/bootstrap.css', 
     'dist/css/bootstrap-theme.css' 
     ], 
     examples: [ 
     'docs/examples/**/*.css' 
     ], 
     docs: { 
     options: { 
      ids: false, 
      'overqualified-elements': false 
     }, 
     src: 'docs/assets/css/src/docs.css' 
     } 
    }, 

    cssmin: { 
     options: { 
     compatibility: 'ie8', 
     keepSpecialComments: '*', 
     noAdvanced: true 
     }, 
     minifyCore: { 
     src: 'dist/css/<%= pkg.name %>.css', 
     dest: 'dist/css/<%= pkg.name %>.min.css' 
     }, 
     minifyTheme: { 
     src: 'dist/css/<%= pkg.name %>-theme.css', 
     dest: 'dist/css/<%= pkg.name %>-theme.min.css' 
     }, 
     docs: { 
     src: [ 
      'docs/assets/css/src/docs.css', 
      'docs/assets/css/src/pygments-manni.css' 
     ], 
     dest: 'docs/assets/css/docs.min.css' 
     } 
    }, 

    usebanner: { 
     options: { 
     position: 'top', 
     banner: '<%= banner %>' 
     }, 
     files: { 
     src: 'dist/css/*.css' 
     } 
    }, 

    csscomb: { 
     options: { 
     config: 'less/.csscomb.json' 
     }, 
     dist: { 
     expand: true, 
     cwd: 'dist/css/', 
     src: ['*.css', '!*.min.css'], 
     dest: 'dist/css/' 
     }, 
     examples: { 
     expand: true, 
     cwd: 'docs/examples/', 
     src: '**/*.css', 
     dest: 'docs/examples/' 
     }, 
     docs: { 
     src: 'docs/assets/css/src/docs.css', 
     dest: 'docs/assets/css/src/docs.css' 
     } 
    }, 

    copy: { 
     fonts: { 
     src: 'fonts/*', 
     dest: 'dist/' 
     }, 
     docs: { 
     src: 'dist/*/*', 
     dest: 'docs/' 
     } 
    }, 

    connect: { 
     server: { 
     options: { 
      port: 3000, 
      base: '.' 
     } 
     } 
    }, 

    jekyll: { 
     docs: {} 
    }, 

    jade: { 
     options: { 
     pretty: true, 
     data: getLessVarsData 
     }, 
     customizerVars: { 
     src: 'docs/_jade/customizer-variables.jade', 
     dest: 'docs/_includes/customizer-variables.html' 
     }, 
     customizerNav: { 
     src: 'docs/_jade/customizer-nav.jade', 
     dest: 'docs/_includes/nav/customize.html' 
     } 
    }, 

    validation: { 
     options: { 
     charset: 'utf-8', 
     doctype: 'HTML5', 
     failHard: true, 
     reset: true, 
     relaxerror: [ 
      'Element img is missing required attribute src.', 
      'Attribute autocomplete not allowed on element input at this point.', 
      'Attribute autocomplete not allowed on element button at this point.' 
     ] 
     }, 
     files: { 
     src: '_gh_pages/**/*.html' 
     } 
    }, 

    watch: { 
     src: { 
     files: '<%= jshint.core.src %>', 
     tasks: ['jshint:src', 'qunit', 'concat'] 
     }, 
     test: { 
     files: '<%= jshint.test.src %>', 
     tasks: ['jshint:test', 'qunit'] 
     }, 
     less: { 
     files: 'less/**/*.less', 
     tasks: 'less' 
     } 
    }, 

    sed: { 
     versionNumber: { 
     pattern: (function() { 
      var old = grunt.option('oldver'); 
      return old ? RegExp.quote(old) : old; 
     })(), 
     replacement: grunt.option('newver'), 
     recursive: true 
     } 
    }, 

    'saucelabs-qunit': { 
     all: { 
     options: { 
      build: process.env.TRAVIS_JOB_ID, 
      concurrency: 10, 
      maxRetries: 3, 
      urls: ['http://127.0.0.1:3000/js/tests/index.html'], 
      browsers: grunt.file.readYAML('grunt/sauce_browsers.yml') 
     } 
     } 
    }, 

    exec: { 
     npmUpdate: { 
     command: 'npm update' 
     } 
    } 
    }); 


    // These plugins provide necessary tasks. 
    require('load-grunt-tasks')(grunt, { scope: 'devDependencies' }); 
    require('time-grunt')(grunt); 

    // Docs HTML validation task 
    grunt.registerTask('validate-html', ['jekyll', 'validation']); 

    var runSubset = function (subset) { 
    return !process.env.TWBS_TEST || process.env.TWBS_TEST === subset; 
    }; 
    var isUndefOrNonZero = function (val) { 
    return val === undefined || val !== '0'; 
    }; 

    // Test task. 
    var testSubtasks = []; 
    // Skip core tests if running a different subset of the test suite 
    if (runSubset('core')) { 
    testSubtasks = testSubtasks.concat(['dist-css', 'dist-js', 'csslint:dist', 'test-js', 'docs']); 
    } 
    // Skip HTML validation if running a different subset of the test suite 
    if (runSubset('validate-html') && 
     // Skip HTML5 validator on Travis when [skip validator] is in the commit message 
     isUndefOrNonZero(process.env.TWBS_DO_VALIDATOR)) { 
    testSubtasks.push('validate-html'); 
    } 
    // Only run Sauce Labs tests if there's a Sauce access key 
    if (typeof process.env.SAUCE_ACCESS_KEY !== 'undefined' && 
     // Skip Sauce if running a different subset of the test suite 
     runSubset('sauce-js-unit') && 
     // Skip Sauce on Travis when [skip sauce] is in the commit message 
     isUndefOrNonZero(process.env.TWBS_DO_SAUCE)) { 
    testSubtasks.push('connect'); 
    testSubtasks.push('saucelabs-qunit'); 
    } 
    grunt.registerTask('test', testSubtasks); 
    grunt.registerTask('test-js', ['jshint:core', 'jshint:test', 'jshint:grunt', 'jscs:core', 'jscs:test', 'jscs:grunt', 'qunit']); 

    // JS distribution task. 
    grunt.registerTask('dist-js', ['concat', 'uglify:core', 'commonjs']); 

    // CSS distribution task. 
    grunt.registerTask('less-compile', ['less:compileCore', 'less:compileTheme']); 
    grunt.registerTask('dist-css', ['less-compile', 'autoprefixer:core', 'autoprefixer:theme', 'usebanner', 'csscomb:dist', 'cssmin:minifyCore', 'cssmin:minifyTheme']); 

    // Full distribution task. 
    grunt.registerTask('dist', ['clean:dist', 'dist-css', 'copy:fonts', 'dist-js']); 

    // Default task. 
    grunt.registerTask('default', ['clean:dist', 'copy:fonts', 'test']); 

    // Version numbering task. 
    // grunt change-version-number --oldver=A.B.C --newver=X.Y.Z 
    // This can be overzealous, so its changes should always be manually reviewed! 
    grunt.registerTask('change-version-number', 'sed'); 

    // task for building customizer 
    grunt.registerTask('build-customizer', ['build-customizer-html', 'build-raw-files']); 
    grunt.registerTask('build-customizer-html', 'jade'); 
    grunt.registerTask('build-raw-files', 'Add scripts/less files to customizer.', function() { 
    var banner = grunt.template.process('<%= banner %>'); 
    generateRawFiles(grunt, banner); 
    }); 

    grunt.registerTask('commonjs', 'Generate CommonJS entrypoint module in dist dir.', function() { 
    var srcFiles = grunt.config.get('concat.bootstrap.src'); 
    var destFilepath = 'dist/js/npm.js'; 
    generateCommonJSModule(grunt, srcFiles, destFilepath); 
    }); 

    // Docs task. 
    grunt.registerTask('docs-css', ['autoprefixer:docs', 'autoprefixer:examples', 'csscomb:docs', 'csscomb:examples', 'cssmin:docs']); 
    grunt.registerTask('lint-docs-css', ['csslint:docs', 'csslint:examples']); 
    grunt.registerTask('docs-js', ['uglify:docsJs', 'uglify:customize']); 
    grunt.registerTask('lint-docs-js', ['jshint:assets', 'jscs:assets']); 
    grunt.registerTask('docs', ['docs-css', 'lint-docs-css', 'docs-js', 'lint-docs-js', 'clean:docs', 'copy:docs', 'build-customizer']); 

    // Task for updating the cached npm packages used by the Travis build (which are controlled by test-infra/npm-shrinkwrap.json). 
    // This task should be run and the updated file should be committed whenever Bootstrap's dependencies change. 
    grunt.registerTask('update-shrinkwrap', ['exec:npmUpdate', '_update-shrinkwrap']); 
    grunt.registerTask('_update-shrinkwrap', function() { 
    var done = this.async(); 
    npmShrinkwrap({ dev: true, dirname: __dirname }, function (err) { 
     if (err) { 
     grunt.fail.warn(err); 
     } 
     var dest = 'test-infra/npm-shrinkwrap.json'; 
     fs.renameSync('npm-shrinkwrap.json', dest); 
     grunt.log.writeln('File ' + dest.cyan + ' updated.'); 
     done(); 
    }); 
    }); 
}; 

回答

3

它看起来像你的jshint配置不正确设置...的错误响应jshint:SRC没有被定义你的配置。

确保jshint有一个src配置设置

grunt.initConfig({ 
     jshint: { 
      files: ['path/to/*.js'], 
      src: { 
       files: ['path/to/*.js'] 
      } 
     } 
}); 

或者在您注册的任务只是叫grunt.registerTask('default', ['jshint']);使用默认配置。

+0

谢谢您的回答,但现在我得到以下警告:'警告:“在”运营商不能使用搜索在JS“src”中/ * JS使用--force可以continue.' –

+0

能你发布完整的grunt.initConfig,甚至是你的整个gruntFile,如果它不是太大? –

+0

我刚刚分享了我的'Gruntfile.js'。 –

3

我遇到了这个问题,通过使用grunt watch任务。 我想通了,手表任务正在调用jshint:src任务 但是这个任务没有定义。

watch: { 
    src: { 
    files: '<%= jshint.core.src %>', 
    tasks: ['jshint:src', 'qunit', 'concat'] 
    }, 
    test: { 
    files: '<%= jshint.test.src %>', 
    tasks: ['jshint:test', 'qunit'] 
    }, 
    less: { 
    files: 'less/**/*.less', 
    tasks: 'less' 
    } 
}, 

我把它改为jshint:核心,它是工作。

watch: { 
    src: { 
    files: '<%= jshint.core.src %>', 
    tasks: ['jshint:core', 'qunit', 'concat'] 
    }, 
    test: { 
    files: '<%= jshint.test.src %>', 
    tasks: ['jshint:test', 'qunit'] 
    }, 
    less: { 
    files: 'less/**/*.less', 
    tasks: 'less' 
    } 
},