├── .editorconfig ├── .eslintrc ├── .gitignore ├── .jscsrc ├── .npmignore ├── .travis.yml ├── LICENSE ├── README.md ├── compat └── legacy-loader.js ├── index.js ├── lib └── util.js └── package.json /.editorconfig: -------------------------------------------------------------------------------- 1 | ; editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 4 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.json] 13 | indent_size = 2 14 | 15 | [*.yml] 16 | indent_size = 2 17 | 18 | [*.md] 19 | indent_size = 2 20 | 21 | [{.eslintrc,.jscsrc}] 22 | indent_size = 2 23 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | --- 2 | # https://github.com/eslint/eslint/blob/master/docs/configuring/README.md 3 | 4 | env: 5 | node: true 6 | browser: true 7 | 8 | # https://github.com/eslint/eslint/tree/master/docs/rules 9 | rules: 10 | # possible errors 11 | no-cond-assign: 1 12 | no-console: 1 13 | no-constant-condition: 2 14 | no-comma-dangle: 1 15 | no-control-regex: 1 16 | no-debugger: 2 17 | no-dupe-keys: 2 18 | no-empty: 2 19 | no-empty-class: 2 20 | no-ex-assign: 2 21 | no-extra-boolean-cast: 1 22 | no-extra-parens: 1 23 | no-extra-semi: 2 24 | no-func-assign: 2 25 | no-inner-declarations: 1 26 | no-invalid-regexp: 2 27 | no-negated-in-lhs: 1 28 | no-obj-calls: 2 29 | no-regex-spaces: 1 30 | no-sparse-arrays: 2 31 | no-unreachable: 2 32 | use-isnan: 2 33 | valid-jsdoc: 1 34 | valid-typeof: 2 35 | 36 | # best practices 37 | block-scoped-var: 1 38 | complexity: 0 39 | consistent-return: 1 40 | curly: 2 41 | default-case: 1 42 | dot-notation: 0 43 | eqeqeq: 2 44 | guard-for-in: 1 45 | no-alert: 2 46 | no-caller: 2 47 | no-div-regex: 0 48 | no-else-return: 1 49 | no-empty-label: 2 50 | no-eq-null: 2 51 | no-eval: 2 52 | no-extend-native: 2 53 | no-fallthrough: 1 54 | no-floating-decimal: 1 55 | no-implied-eval: 2 56 | no-labels: 2 57 | no-iterator: 2 58 | no-lone-blocks: 2 59 | no-loop-func: 1 60 | no-multi-str: 1 61 | no-native-reassign: 2 62 | no-new: 0 63 | no-new-func: 2 64 | no-new-wrappers: 1 65 | no-octal: 2 66 | no-octal-escape: 2 67 | no-proto: 2 68 | no-redeclare: 2 69 | no-return-assign: 2 70 | no-script-url: 2 71 | no-self-compare: 2 72 | no-sequences: 1 73 | no-unused-expressions: 2 74 | # Definition for rule 'no-void' was not found 75 | # no-void: 2 76 | no-warning-comments: 0 77 | no-with: 2 78 | radix: 1 79 | wrap-iife: 1 80 | yoda: 0 81 | 82 | # strict mode 83 | # Definition for rule 'global-strict' was not found 84 | # global-strict: [2, "always"] 85 | no-extra-strict: 2 86 | strict: 2 87 | 88 | # variables 89 | no-catch-shadow: 2 90 | no-delete-var: 2 91 | no-label-var: 2 92 | no-shadow: 1 93 | no-shadow-restricted-names: 2 94 | no-undef: 2 95 | no-undefined: 2 96 | no-undef-init: 1 97 | no-unused-vars: 1 98 | no-use-before-define: 2 99 | 100 | # Node.js 101 | handle-callback-err: 2 102 | no-mixed-requires: 0 103 | no-path-concat: 2 104 | no-process-exit: 2 105 | no-restricted-modules: 0 106 | no-sync: 0 107 | 108 | # stylistic issues, disabled because of JSCS 109 | brace-style: 0 110 | camelcase: 0 111 | consistent-this: 0 112 | eol-last: 0 113 | func-names: 0 114 | func-style: 0 115 | new-cap: 1 116 | new-parens: 1 117 | no-nested-ternary: 0 118 | no-array-constructor: 1 119 | no-lonely-if: 1 120 | no-new-object: 1 121 | no-spaced-func: 0 122 | no-space-before-semi: 0 123 | no-ternary: 0 124 | no-trailing-spaces: 0 125 | no-underscore-dangle: 0 126 | no-wrap-func: 0 127 | no-mixed-spaces-and-tabs: 0 128 | quotes: 0 129 | quote-props: 0 130 | semi: 2 131 | sort-vars: 0 132 | space-after-keywords: 0 133 | space-in-brackets: 0 134 | space-in-parens: 0 135 | space-infix-ops: 0 136 | space-return-throw-case: 1 137 | space-unary-word-ops: 1 138 | max-nested-callbacks: 0 139 | one-var: 0 140 | wrap-regex: 0 141 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | tmp/ 3 | *.sublime-* 4 | *.log 5 | .DS_Store 6 | -------------------------------------------------------------------------------- /.jscsrc: -------------------------------------------------------------------------------- 1 | { 2 | "requireCurlyBraces": [ 3 | "if", 4 | "else", 5 | "for", 6 | "while", 7 | "do", 8 | "try", 9 | "catch", 10 | "case", 11 | "default" 12 | ], 13 | "requireSpaceAfterKeywords": [ 14 | "if", 15 | "else", 16 | "for", 17 | "while", 18 | "do", 19 | "switch", 20 | "return", 21 | "try", 22 | "catch" 23 | ], 24 | "requireSpaceBeforeBlockStatements": true, 25 | "requireParenthesesAroundIIFE": true, 26 | "requireSpacesInConditionalExpression": { 27 | "afterTest": true, 28 | "beforeConsequent": true, 29 | "afterConsequent": true, 30 | "beforeAlternate": true 31 | }, 32 | "requireSpacesInAnonymousFunctionExpression": { 33 | "beforeOpeningCurlyBrace": true 34 | }, 35 | "disallowSpacesInAnonymousFunctionExpression": { 36 | "beforeOpeningRoundBrace": true 37 | }, 38 | "requireSpacesInNamedFunctionExpression": { 39 | "beforeOpeningCurlyBrace": true 40 | }, 41 | "disallowSpacesInNamedFunctionExpression": { 42 | "beforeOpeningRoundBrace": true 43 | }, 44 | "requireBlocksOnNewline": true, 45 | "requireSpacesInsideObjectBrackets": "all", 46 | "requireSpacesInsideArrayBrackets": "all", 47 | "disallowSpaceAfterObjectKeys": true, 48 | "requireCommaBeforeLineBreak": true, 49 | "requireOperatorBeforeLineBreak": [ 50 | "?", 51 | "=", 52 | "+", 53 | "-", 54 | "/", 55 | "*", 56 | "==", 57 | "===", 58 | "!=", 59 | "!==", 60 | ">", 61 | ">=", 62 | "<", 63 | "<=" 64 | ], 65 | "disallowSpaceAfterPrefixUnaryOperators": [ "++", "--", "+", "-", "~", "!" ], 66 | "disallowSpaceBeforePostfixUnaryOperators": [ "++", "--" ], 67 | "requireSpaceBeforeBinaryOperators": [ 68 | "=", 69 | "+", 70 | "-", 71 | "/", 72 | "*", 73 | "==", 74 | "===", 75 | "!=", 76 | "!==" 77 | ], 78 | "requireSpaceAfterBinaryOperators": [ 79 | "=", 80 | ",", 81 | "+", 82 | "-", 83 | "/", 84 | "*", 85 | "==", 86 | "===", 87 | "!=", 88 | "!==" 89 | ], 90 | "requireCamelCaseOrUpperCaseIdentifiers": true, 91 | "disallowMultipleLineBreaks": true, 92 | "validateLineBreaks": "LF", 93 | "validateQuoteMarks": "'", 94 | "validateIndentation": 4, 95 | "disallowMixedSpacesAndTabs": true, 96 | "disallowTrailingWhitespace": true, 97 | "disallowTrailingComma": true, 98 | "disallowKeywordsOnNewLine": ["else"], 99 | "requireLineFeedAtFileEnd": true, 100 | "requireCapitalizedConstructors": true, 101 | "safeContextKeyword": ["that"], 102 | "disallowYodaConditions": true, 103 | "requireSpaceAfterLineComment": true, 104 | "requireAnonymousFunctions": true, 105 | "disallowNewlineBeforeBlockStatements": true, 106 | "disallowMultipleVarDecl": true 107 | } 108 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .gitignore 2 | .editorconfig 3 | .eslintrc 4 | .jscsrc 5 | .travis.yml 6 | tmp/ 7 | *.sublime-* 8 | *.log 9 | .DS_Store 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - 0.10 5 | - 0.11 6 | 7 | matrix: 8 | allow_failures: 9 | - node_js: 0.11 10 | 11 | branches: 12 | only: 13 | - master 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2015 Kir Belevich 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## "Baggage" loader for [webpack](https://webpack.github.io/) 2 | 3 | [![npm](http://img.shields.io/npm/v/baggage-loader.svg?style=flat-square)](https://www.npmjs.org/package/baggage-loader) 4 | [![travis](http://img.shields.io/travis/deepsweet/baggage-loader.svg?style=flat-square)](https://travis-ci.org/deepsweet/baggage-loader) 5 | [![climate](http://img.shields.io/codeclimate/github/deepsweet/baggage-loader.svg?style=flat-square)](https://codeclimate.com/github/deepsweet/baggage-loader/code) 6 | [![peer deps](http://img.shields.io/david/peer/deepsweet/baggage-loader.svg?style=flat-square)](https://david-dm.org/deepsweet/baggage-loader#info=peerDependencies) 7 | [![gratipay](http://img.shields.io/gratipay/deepsweet.svg?style=flat-square)](https://gratipay.com/deepsweet/) 8 | 9 | Automatically require any resources related to the required one. See example below. 10 | 11 | [Documentation: Using loaders](https://webpack.github.io/docs/using-loaders.html). 12 | 13 | ## Install 14 | 15 | ```sh 16 | $ npm i -S baggage-loader 17 | ``` 18 | 19 | ## Example 20 | 21 | Imagine that you have project structure like this and you're using webpack: 22 | 23 | ``` 24 | components/ 25 | ├── component-1/ 26 | │   ├── script.js 27 | │   ├── styles.css 28 | │   └── template.html 29 | ├── component-2/ 30 | │   ├── script.js 31 | │   └── template.html 32 | └── component-3/ 33 | ├── script.js 34 | └── styles.css 35 | ``` 36 | 37 | and in each of component's `script.js` you're doing something like this: 38 | 39 | ```javascript 40 | var template = require('./template.html'); 41 | require('./styles.css'); 42 | 43 | var html = template({ foo: 'bar' }); 44 | ``` 45 | 46 | Now you can stop and let `baggage-loader` handle those `require`s, like so: 47 | 48 | ```javascript 49 | module: { 50 | loaders: [ { 51 | test: /\/components\/.+script\.js$/, 52 | loader: 'baggage?{"template.html":{"varName":"template"},"styles.css":{}}' 53 | } ] 54 | } 55 | ``` 56 | 57 | The example above will become the necessary requires, with variable declarations, if the corresponding files exist: 58 | 59 | ```javascript 60 | // injected by preloader at the top of script.js 61 | var template = require('./template.html'); 62 | require('./styles.css'); 63 | 64 | // your code 65 | var html = template({ foo: 'bar' }; 66 | ``` 67 | 68 | ## Usage 69 | The 'baggage' -- the additional `require`s you want `baggage-loader` to insert -- is specified via the loader's query string. This query string must be written as a JSON string (see below for deprecated url-style query string syntax). 70 | 71 | ## Format 72 | ### Basic require (no options): 73 | `?{"filename.ext":{}}` 74 | 75 | This will insert `require('./filename.ext');` into each module to which the loader is applied 76 | 77 | ### Require with variable name: 78 | `?{"filename.ext":{"varName":"foo"}}` 79 | 80 | This will insert `var foo = require('./filename.ext');` 81 | 82 | ### Require with 'inline' loaders: 83 | `?{"filename.ext":{"loaders":"style*css*sass"}}` 84 | 85 | This will insert `require('style!css!sass!./filename.ext');`. Note that asterisks are replaced with exclamation points; the loader will append the final exclamation point between your loaders and the file path. If you are overriding existing loader config, you will need to prefix your loader string with `*` so that the loader string begins with `!` (the leading exclamation point is webpack's syntax for overriding loaders). 86 | 87 | ### Combined 88 | Any of the above can be combined, for example: 89 | 90 | `?{"filename.ext":{"varName":"foo","loaders":"style*css*sass}}` 91 | 92 | will insert `var foo = require('style!css!sass!./filename.ext');`. You can also have more than one baggage file in your params: 93 | 94 | `?{"filename.js":{},"filename.scss":{}}` 95 | 96 | The above will insert 97 | 98 | ```javascript 99 | require('./filename.js'); 100 | require('./filename.scss'); 101 | ``` 102 | 103 | When defining a large amount of loader parameters, you may find it easier to define the JSON object and then stringify it for use in your loader config. 104 | 105 | ### Supported placeholders 106 | 107 | The placeholder strings `[dir]`, `[Dir]`, `[file]` and `[File]` can be used in the keys of the loader params object (the file path) or in the `varName` value. The values for file and directory are taken from the module being loaded. For example: 108 | 109 | ``` 110 | alert/ 111 | ├── view.js 112 | ├── templateAlert.html 113 | └── alertViewStyles.css 114 | ``` 115 | 116 | ```javascript 117 | loader: 'baggage?template[Dir].html=[file]Template&[dir][File]Styles.css' 118 | ``` 119 | 120 | ```javascript 121 | var viewTemplate = require('./templateAlert.html'); 122 | require('./alertViewStyles.css'); 123 | ``` 124 | 125 | ## Pre-1.0 Usage 126 | Before version 1.0, the loader supported both JSON-style query strings and url-style query strings, and the syntax was different. The breaking change for the loader's parameters was made to support a greater range of parmaters to control the loader's behavior. The older syntax is still supported, but **only** when params are specfied as a url-style query string. (In other words, all url-style params will be treated as the old syntax, all JSON-style params will be treated as the 1.x+ syntax.) In the future, support for the older styntax will likely be removed; users are encouraged to update to the 1.x syntax. 127 | 128 | `?template.html=template&styles.css` 129 | 130 | The above would insert 131 | 132 | ``` 133 | var template = require('./template.html'); 134 | require('./styles.css'); 135 | ``` 136 | 137 | Note that the argument 'name' in this syntax is the file path, and if you assign a 'value', that value becomes the variable name. The file and directory placeholders may be used in this syntax just as in the 1.x+ syntax. 138 | 139 | Note that the above example demonstrates all of the functionality of the legacy syntax. Newer features, such as specifying loaders, are not supported. -------------------------------------------------------------------------------- /compat/legacy-loader.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Legacy version of baggage-loader (to 0.2.4). Does not support advanced config via JSON. 3 | * Deprecated; support will likely be removed at some point in the future. Use v1+ JSON-based 4 | * config instead. 5 | */ 6 | 7 | 'use strict'; 8 | 9 | var path = require('path'); 10 | var fs = require('fs'); 11 | var loaderUtils = require('loader-utils'); 12 | var SourceMap = require('source-map'); 13 | 14 | var util = require('../lib/util'); 15 | 16 | module.exports = function(source, sourceMap) { 17 | var query = loaderUtils.parseQuery(this.query); 18 | 19 | // /foo/bar/file.js 20 | var srcFilepath = this.resourcePath; 21 | // /foo/bar/file.js -> file 22 | var srcFilename = path.basename(srcFilepath, path.extname(srcFilepath)); 23 | // /foo/bar/file.js -> /foo/bar 24 | var srcDirpath = path.dirname(srcFilepath); 25 | // /foo/bar -> bar 26 | var srcDirname = srcDirpath.split(path.sep).pop(); 27 | 28 | if (this.cacheable) { 29 | this.cacheable(); 30 | } 31 | 32 | if (Object.keys(query).length) { 33 | var inject = '\n/* injects from baggage-loader */\n'; 34 | 35 | Object.keys(query).forEach(function(baggageFile) { 36 | var baggageVar = query[baggageFile]; 37 | 38 | // TODO: not so quick and dirty validation 39 | if (typeof baggageVar === 'string' || baggageVar === true) { 40 | // apply filename placeholders 41 | baggageFile = util.applyPlaceholders(baggageFile, srcDirname, srcFilename); 42 | 43 | // apply var placeholders 44 | if (baggageVar.length) { 45 | baggageVar = util.applyPlaceholders(baggageVar, srcDirname, srcFilename); 46 | } 47 | 48 | try { 49 | // check if absoluted from srcDirpath + baggageFile path exists 50 | var stats = fs.statSync(path.resolve(srcDirpath, baggageFile)); 51 | 52 | if (stats.isFile()) { 53 | // assign it to variable 54 | if (baggageVar.length) { 55 | inject += 'var ' + baggageVar + ' = '; 56 | } 57 | 58 | // and require 59 | inject += 'require(\'./' + baggageFile + '\');\n'; 60 | } 61 | } catch (e) {} 62 | } 63 | }); 64 | 65 | inject += '\n'; 66 | 67 | // support existing SourceMap 68 | // https://github.com/mozilla/source-map#sourcenode 69 | // https://github.com/webpack/imports-loader/blob/master/index.js#L34-L44 70 | // https://webpack.github.io/docs/loaders.html#writing-a-loader 71 | if (sourceMap) { 72 | var currentRequest = loaderUtils.getCurrentRequest(this); 73 | var SourceNode = SourceMap.SourceNode; 74 | var SourceMapConsumer = SourceMap.SourceMapConsumer; 75 | var sourceMapConsumer = new SourceMapConsumer(sourceMap); 76 | var node = SourceNode.fromStringWithSourceMap(source, sourceMapConsumer); 77 | 78 | node.prepend(inject); 79 | 80 | var result = node.toStringWithSourceMap({ 81 | file: currentRequest 82 | }); 83 | 84 | this.callback(null, result.code, result.map.toJSON()); 85 | 86 | return; 87 | } 88 | 89 | // prepend collected inject at the top of file 90 | return inject + source; 91 | } 92 | 93 | // return the original source and sourceMap 94 | if (sourceMap) { 95 | this.callback(null, source, sourceMap); 96 | return; 97 | } 98 | 99 | // return the original source 100 | return source; 101 | }; 102 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable consistent-return */ 2 | 'use strict'; 3 | 4 | var path = require('path'); 5 | var fs = require('fs'); 6 | var loaderUtils = require('loader-utils'); 7 | var SourceMap = require('source-map'); 8 | 9 | var legacyLoader = require('./compat/legacy-loader.js'); 10 | var util = require('./lib/util'); 11 | 12 | var injectBanner = '\n/* injects from baggage-loader */\n'; 13 | 14 | module.exports = function(source, sourceMap) { 15 | // parseQuery will always give us an object, for back-compat we 16 | // want to know if we're working with JSON query or query string 17 | if (!util.isJSONString(this.query.replace('?', ''))) { 18 | return legacyLoader.call(this, source, sourceMap); 19 | } 20 | 21 | var query = loaderUtils.parseQuery(this.query); 22 | 23 | // /foo/bar/file.js 24 | var srcFilepath = this.resourcePath; 25 | // /foo/bar/file.js -> file 26 | var srcFilename = path.basename(srcFilepath, path.extname(srcFilepath)); 27 | // /foo/bar/file.js -> /foo/bar 28 | var srcDirpath = path.dirname(srcFilepath); 29 | // /foo/bar -> bar 30 | var srcDirname = srcDirpath.split(path.sep).pop(); 31 | 32 | if (this.cacheable) { 33 | this.cacheable(); 34 | } 35 | 36 | var filePaths = Object.keys(query); 37 | var injections = []; 38 | if (filePaths.length) { 39 | injections = filePaths.map(function(filePath) { 40 | 41 | var varName; 42 | var loadersForFile = ''; 43 | var inject = null; 44 | 45 | if (typeof query[filePath] === 'object') { 46 | var fileConfig = query[filePath]; 47 | var loaderStringForFile = fileConfig.loaders || ''; 48 | if (loaderStringForFile) { 49 | loadersForFile = loaderStringForFile.replace(/\*/g, '!') + '!'; 50 | } 51 | 52 | varName = fileConfig.varName; 53 | } 54 | 55 | filePath = util.applyPlaceholders(filePath, srcDirname, srcFilename); 56 | if (varName) { 57 | varName = util.applyPlaceholders(varName, srcDirname, srcFilename); 58 | } 59 | 60 | // @todo support mandatory/optional requires via config 61 | try { 62 | 63 | // check if absoluted from srcDirpath + baggageFile path exists 64 | var stats = fs.statSync(path.resolve(srcDirpath, filePath)); 65 | 66 | if (stats.isFile()) { 67 | inject = ''; 68 | if (varName) { 69 | inject = 'var ' + varName + ' = '; 70 | } 71 | 72 | inject += 'require(\'' + loadersForFile + './' + filePath + '\');\n'; 73 | } 74 | } catch (e) {} 75 | 76 | return inject; 77 | }); 78 | 79 | injections.filter(function(inject) { 80 | return typeof inject === 'string'; 81 | }); 82 | 83 | if (injections.length) { 84 | var srcInjection = injectBanner + injections.join('\n'); 85 | 86 | // support existing SourceMap 87 | // https://github.com/mozilla/source-map#sourcenode 88 | // https://github.com/webpack/imports-loader/blob/master/index.js#L34-L44 89 | // https://webpack.github.io/docs/loaders.html#writing-a-loader 90 | if (sourceMap) { 91 | var currentRequest = loaderUtils.getCurrentRequest(this); 92 | var SourceNode = SourceMap.SourceNode; 93 | var SourceMapConsumer = SourceMap.SourceMapConsumer; 94 | var sourceMapConsumer = new SourceMapConsumer(sourceMap); 95 | var node = SourceNode.fromStringWithSourceMap(source, sourceMapConsumer); 96 | 97 | node.prepend(srcInjection); 98 | 99 | var result = node.toStringWithSourceMap({ 100 | file: currentRequest 101 | }); 102 | 103 | this.callback(null, result.code, result.map.toJSON()); 104 | 105 | return; 106 | } 107 | 108 | // prepend collected inject at the top of file 109 | return srcInjection + source; 110 | } 111 | 112 | } 113 | 114 | // return the original source and sourceMap 115 | if (sourceMap) { 116 | this.callback(null, source, sourceMap); 117 | return; 118 | } 119 | 120 | // return the original source 121 | return source; 122 | }; 123 | -------------------------------------------------------------------------------- /lib/util.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var capitalize = exports.capitalize = function(str) { 4 | return str.charAt(0).toUpperCase() + str.slice(1); 5 | }; 6 | 7 | var util = { 8 | applyPlaceholders: function(str, dirname, filename) { 9 | if (!str.length) { 10 | return str; 11 | } 12 | 13 | return str 14 | .split('[dir]').join(dirname) 15 | .split('[Dir]').join(capitalize(dirname)) 16 | .split('[file]').join(filename) 17 | .split('[File]').join(capitalize(filename)); 18 | }, 19 | 20 | isJSONString: function(str) { 21 | try { 22 | JSON.parse(str); 23 | return true; 24 | } catch (err) { 25 | return false; 26 | } 27 | } 28 | }; 29 | 30 | module.exports = util; 31 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "baggage-loader", 3 | "version": "1.0.0", 4 | "description": "Webpack loader to automatically require any resources related to the required one", 5 | "keywords": [ 6 | "webpack", 7 | "loader" 8 | ], 9 | "homepage": "https://github.com/deepsweet/baggage-loader", 10 | "repository": { 11 | "type": "git", 12 | "url": "git://github.com/deepsweet/baggage-loader.git" 13 | }, 14 | "author": { 15 | "name": "Kir Belevich", 16 | "email": "kir@soulshine.in", 17 | "url": "https://github.com/deepsweet" 18 | }, 19 | "main": "index.js", 20 | "peerDependencies": { 21 | "webpack": "1.x.x", 22 | "loader-utils": "0.x.x", 23 | "source-map": "0.x.x" 24 | }, 25 | "devDependencies": { 26 | "eslint": "^0.8.2", 27 | "jscs": "^1.6.2" 28 | }, 29 | "scripts": { 30 | "test": "eslint index.js lib/*.js && jscs index.js lib/*.js" 31 | }, 32 | "engines": { 33 | "node": ">=0.10.0" 34 | }, 35 | "license": "MIT" 36 | } 37 | --------------------------------------------------------------------------------